2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
31 BROWSER_EXTENSION2_VERSION_1_1
,
35 IsBrowserDataModified
,
43 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
44 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
45 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
46 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
48 UINTN gBrowserContextCount
= 0;
49 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
50 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
51 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
52 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
53 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
55 BOOLEAN mSystemSubmit
= FALSE
;
56 BOOLEAN gResetRequired
;
57 BOOLEAN gExitRequired
;
58 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
59 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
60 EXIT_HANDLER ExitHandlerFunction
= NULL
;
61 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
64 // Browser Global Strings
67 CHAR16
*mUnknownString
= L
"!";
69 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
71 extern EFI_GUID mCurrentFormSetGuid
;
72 extern EFI_HII_HANDLE mCurrentHiiHandle
;
73 extern UINT16 mCurrentFormId
;
74 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
77 Create a menu with specified formset GUID and form ID, and add it as a child
78 of the given parent menu.
80 @param HiiHandle Hii handle related to this formset.
81 @param FormSetGuid The Formset Guid of menu to be added.
82 @param FormId The Form ID of menu to be added.
83 @param QuestionId The question id of this menu to be added.
85 @return A pointer to the newly added menu or NULL if memory is insufficient.
90 IN EFI_HII_HANDLE HiiHandle
,
91 IN EFI_GUID
*FormSetGuid
,
96 FORM_ENTRY_INFO
*MenuList
;
98 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
99 if (MenuList
== NULL
) {
103 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
105 MenuList
->HiiHandle
= HiiHandle
;
106 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
107 MenuList
->FormId
= FormId
;
108 MenuList
->QuestionId
= QuestionId
;
111 // If parent is not specified, it is the root Form of a Formset
113 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
119 Return the form id for the input hiihandle and formset.
121 @param HiiHandle HiiHandle for FormSet.
122 @param FormSetGuid The Formset GUID of the menu to search.
124 @return First form's id for this form set.
129 IN EFI_HII_HANDLE HiiHandle
,
130 IN EFI_GUID
*FormSetGuid
134 FORM_BROWSER_FORM
*Form
;
136 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
137 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
143 Search Menu with given FormSetGuid and FormId in all cached menu list.
145 @param HiiHandle HiiHandle for FormSet.
146 @param FormSetGuid The Formset GUID of the menu to search.
147 @param FormId The Form ID of menu to search.
149 @return A pointer to menu found or NULL if not found.
154 IN EFI_HII_HANDLE HiiHandle
,
155 IN EFI_GUID
*FormSetGuid
,
160 FORM_ENTRY_INFO
*MenuList
;
161 FORM_ENTRY_INFO
*RetMenu
;
162 EFI_FORM_ID FirstFormId
;
166 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
167 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
168 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
169 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
172 // If already find the menu, free the menus behind it.
174 if (RetMenu
!= NULL
) {
175 RemoveEntryList (&MenuList
->Link
);
181 // Find the same FromSet.
183 if (MenuList
->HiiHandle
== HiiHandle
) {
184 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
186 // FormSetGuid is not specified.
189 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
190 if (MenuList
->FormId
== FormId
) {
192 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
193 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
194 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
206 Find parent menu for current menu.
208 @param CurrentMenu Current Menu
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.
210 In form level, just find the parent menu;
211 In formset level, find the parent menu which has different
214 @retval The parent menu for current menu.
218 IN FORM_ENTRY_INFO
*CurrentMenu
,
219 IN BROWSER_SETTING_SCOPE SettingLevel
222 FORM_ENTRY_INFO
*ParentMenu
;
225 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
227 if (CurrentMenu
== NULL
) {
232 Link
= &CurrentMenu
->Link
;
234 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
235 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
237 if (SettingLevel
== FormLevel
) {
239 // For FormLevel, just find the parent menu, return.
244 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
246 // For SystemLevel, must find the menu which has different formset.
251 Link
= Link
->BackLink
;
255 // Not find the parent menu, just return NULL.
257 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
265 Free Menu list linked list.
267 @param MenuListHead One Menu list point in the menu list.
272 LIST_ENTRY
*MenuListHead
275 FORM_ENTRY_INFO
*MenuList
;
277 while (!IsListEmpty (MenuListHead
)) {
278 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
279 RemoveEntryList (&MenuList
->Link
);
286 Copy current Menu list to the new menu list.
288 @param NewMenuListHead New create Menu list.
289 @param CurrentMenuListHead Current Menu list.
294 OUT LIST_ENTRY
*NewMenuListHead
,
295 IN LIST_ENTRY
*CurrentMenuListHead
299 FORM_ENTRY_INFO
*MenuList
;
300 FORM_ENTRY_INFO
*NewMenuEntry
;
303 // If new menu list not empty, free it first.
305 UiFreeMenuList (NewMenuListHead
);
307 Link
= GetFirstNode (CurrentMenuListHead
);
308 while (!IsNull (CurrentMenuListHead
, Link
)) {
309 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
310 Link
= GetNextNode (CurrentMenuListHead
, Link
);
312 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
313 ASSERT (NewMenuEntry
!= NULL
);
314 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
315 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
316 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
317 NewMenuEntry
->FormId
= MenuList
->FormId
;
318 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
320 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
325 Load all hii formset to the browser.
333 FORM_BROWSER_FORMSET
*LocalFormSet
;
334 EFI_HII_HANDLE
*HiiHandles
;
338 FORM_BROWSER_FORMSET
*OldFormset
;
340 OldFormset
= mSystemLevelFormSet
;
343 // Get all the Hii handles
345 HiiHandles
= HiiGetHiiHandles (NULL
);
346 ASSERT (HiiHandles
!= NULL
);
349 // Search for formset of each class type
351 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
353 // Check HiiHandles[Index] does exist in global maintain list.
355 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
360 // Initilize FormSet Setting
362 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
363 ASSERT (LocalFormSet
!= NULL
);
364 mSystemLevelFormSet
= LocalFormSet
;
366 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
367 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
368 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
369 DestroyFormSet (LocalFormSet
);
372 InitializeCurrentSetting (LocalFormSet
);
375 // Initilize Questions' Value
377 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
378 if (EFI_ERROR (Status
)) {
379 DestroyFormSet (LocalFormSet
);
385 // Free resources, and restore gOldFormSet and gClassOfVfr
387 FreePool (HiiHandles
);
389 mSystemLevelFormSet
= OldFormset
;
393 Pop up the error info.
395 @param BrowserStatus The input browser status.
396 @param HiiHandle The Hiihandle for this opcode.
397 @param OpCode The opcode use to get the erro info and timeout value.
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
403 IN UINT32 BrowserStatus
,
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
406 IN CHAR16
*ErrorString
409 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
410 USER_INPUT UserInputData
;
414 if (OpCode
!= NULL
) {
415 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
416 ASSERT (Statement
!= NULL
);
417 Statement
->OpCode
= OpCode
;
418 gDisplayFormData
.HighLightedStatement
= Statement
;
422 // Used to compatible with old display engine.
423 // New display engine not use this field.
425 gDisplayFormData
.ErrorString
= ErrorString
;
426 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
428 if (HiiHandle
!= NULL
) {
429 gDisplayFormData
.HiiHandle
= HiiHandle
;
432 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
434 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
435 gDisplayFormData
.ErrorString
= NULL
;
437 if (OpCode
!= NULL
) {
438 FreePool (Statement
);
441 return UserInputData
.Action
;
445 This is the routine which an external caller uses to direct the browser
446 where to obtain it's information.
449 @param This The Form Browser protocol instanse.
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
451 display a list of the formsets for the handles specified.
452 @param HandleCount The number of Handles specified in Handle.
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
454 field in the EFI_IFR_FORM_SET op-code for the specified
455 forms-based package. If FormSetGuid is NULL, then this
456 function will display the first found forms package.
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first
458 displayable page. If this field has a value of 0x0000, then
459 the forms browser will render the specified forms in their encoded order.
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
462 @param ActionRequest Points to the action recommended by the form.
464 @retval EFI_SUCCESS The function completed successfully.
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
466 @retval EFI_NOT_FOUND No valid forms could be found to display.
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
473 IN EFI_HII_HANDLE
*Handles
,
474 IN UINTN HandleCount
,
475 IN EFI_GUID
*FormSetGuid
, OPTIONAL
476 IN UINT16 FormId
, OPTIONAL
477 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
482 UI_MENU_SELECTION
*Selection
;
484 FORM_BROWSER_FORMSET
*FormSet
;
485 FORM_ENTRY_INFO
*MenuList
;
488 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
490 if (mFormDisplay
== NULL
) {
491 return EFI_UNSUPPORTED
;
495 // Save globals used by SendForm()
497 SaveBrowserContext ();
499 gResetRequired
= FALSE
;
500 gExitRequired
= FALSE
;
501 Status
= EFI_SUCCESS
;
503 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
505 for (Index
= 0; Index
< HandleCount
; Index
++) {
506 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
507 ASSERT (Selection
!= NULL
);
509 Selection
->Handle
= Handles
[Index
];
510 if (FormSetGuid
!= NULL
) {
511 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
512 Selection
->FormId
= FormId
;
514 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
518 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
519 ASSERT (FormSet
!= NULL
);
522 // Validate the HiiHandle
523 // if validate failed, find the first validate parent HiiHandle.
525 if (!ValidateHiiHandle(Selection
->Handle
)) {
526 FindNextMenu (Selection
, FormSetLevel
);
530 // Initialize internal data structures of FormSet
532 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
533 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
534 DestroyFormSet (FormSet
);
537 Selection
->FormSet
= FormSet
;
538 mSystemLevelFormSet
= FormSet
;
541 // Display this formset
543 gCurrentSelection
= Selection
;
545 Status
= SetupBrowser (Selection
);
547 gCurrentSelection
= NULL
;
548 mSystemLevelFormSet
= NULL
;
551 // If no data is changed, don't need to save current FormSet into the maintain list.
553 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
554 CleanBrowserStorage(FormSet
);
555 RemoveEntryList (&FormSet
->Link
);
556 DestroyFormSet (FormSet
);
559 if (EFI_ERROR (Status
)) {
562 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
564 FreePool (Selection
);
567 if (ActionRequest
!= NULL
) {
568 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
569 if (gResetRequired
) {
570 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
574 mFormDisplay
->ExitDisplay();
577 // Clear the menu history data.
579 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
580 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
581 RemoveEntryList (&MenuList
->Link
);
586 // Restore globals used by SendForm()
588 RestoreBrowserContext ();
594 Get or set data to the storage.
596 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
597 @param ResultsData A string returned from an IFR browser or
598 equivalent. The results string will have no
599 routing information in them.
600 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
601 (if RetrieveData = TRUE) data from the uncommitted
602 browser state information or set (if RetrieveData
603 = FALSE) data in the uncommitted browser state
605 @param Storage The pointer to the storage.
607 @retval EFI_SUCCESS The results have been distributed or are awaiting
613 IN OUT UINTN
*ResultsDataSize
,
614 IN OUT EFI_STRING
*ResultsData
,
615 IN BOOLEAN RetrieveData
,
616 IN BROWSER_STORAGE
*Storage
627 // Generate <ConfigResp>
629 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
630 if (EFI_ERROR (Status
)) {
635 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
636 // Also need to consider add "\0" at first time.
638 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
639 BufferSize
= StrSize (StrPtr
);
643 // Copy the data if the input buffer is bigger enough.
645 if (*ResultsDataSize
>= BufferSize
) {
646 StrCpy (*ResultsData
, StrPtr
);
649 *ResultsDataSize
= BufferSize
;
650 FreePool (ConfigResp
);
653 // Prepare <ConfigResp>
655 TmpSize
= StrLen (*ResultsData
);
656 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
657 ConfigResp
= AllocateZeroPool (BufferSize
);
658 ASSERT (ConfigResp
!= NULL
);
660 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
661 StrCat (ConfigResp
, L
"&");
662 StrCat (ConfigResp
, *ResultsData
);
665 // Update Browser uncommited data
667 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
668 FreePool (ConfigResp
);
669 if (EFI_ERROR (Status
)) {
678 This routine called this service in the browser to retrieve or set certain uncommitted
679 state information that resides in the open formsets.
681 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
683 @param ResultsDataSize A pointer to the size of the buffer associated
685 @param ResultsData A string returned from an IFR browser or
686 equivalent. The results string will have no
687 routing information in them.
688 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
689 (if RetrieveData = TRUE) data from the uncommitted
690 browser state information or set (if RetrieveData
691 = FALSE) data in the uncommitted browser state
693 @param VariableGuid An optional field to indicate the target variable
695 @param VariableName An optional field to indicate the target
696 human-readable variable name.
698 @retval EFI_SUCCESS The results have been distributed or are awaiting
700 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
701 contain the results data.
707 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
708 IN OUT UINTN
*ResultsDataSize
,
709 IN OUT EFI_STRING ResultsData
,
710 IN BOOLEAN RetrieveData
,
711 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
712 IN CONST CHAR16
*VariableName OPTIONAL
717 BROWSER_STORAGE
*Storage
;
718 FORMSET_STORAGE
*FormsetStorage
;
722 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
723 return EFI_INVALID_PARAMETER
;
726 TotalSize
= *ResultsDataSize
;
729 Status
= EFI_SUCCESS
;
731 if (VariableGuid
!= NULL
) {
733 // Try to find target storage in the current formset.
735 Link
= GetFirstNode (&gBrowserStorageList
);
736 while (!IsNull (&gBrowserStorageList
, Link
)) {
737 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
738 Link
= GetNextNode (&gBrowserStorageList
, Link
);
740 // Check the current storage.
742 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
746 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
747 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
749 // Buffer storage require both GUID and Name
751 if (VariableName
== NULL
) {
752 return EFI_NOT_FOUND
;
755 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
760 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
761 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
762 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
763 return EFI_NOT_FOUND
;
766 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
771 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
772 if (EFI_ERROR (Status
)) {
776 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
777 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
781 // Different formsets may have same varstore, so here just set the flag
782 // not exit the circle.
789 return EFI_NOT_FOUND
;
793 // GUID/Name is not specified, take the first storage in FormSet
795 if (mSystemLevelFormSet
== NULL
) {
796 return EFI_NOT_READY
;
800 // Generate <ConfigResp>
802 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
803 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
804 return EFI_UNSUPPORTED
;
807 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
809 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
810 if (EFI_ERROR (Status
)) {
816 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
817 *ResultsDataSize
= TotalSize
;
826 Callback function for SimpleTextInEx protocol install events
828 @param Event the event that is signaled.
829 @param Context not used here.
834 FormDisplayCallback (
841 if (mFormDisplay
!= NULL
) {
845 Status
= gBS
->LocateProtocol (
846 &gEdkiiFormDisplayEngineProtocolGuid
,
848 (VOID
**) &mFormDisplay
853 Initialize Setup Browser driver.
855 @param ImageHandle The image handle.
856 @param SystemTable The system table.
858 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
859 @return Other value if failed to initialize the Setup Browser module.
865 IN EFI_HANDLE ImageHandle
,
866 IN EFI_SYSTEM_TABLE
*SystemTable
873 // Locate required Hii relative protocols
875 Status
= gBS
->LocateProtocol (
876 &gEfiHiiDatabaseProtocolGuid
,
878 (VOID
**) &mHiiDatabase
880 ASSERT_EFI_ERROR (Status
);
882 Status
= gBS
->LocateProtocol (
883 &gEfiHiiConfigRoutingProtocolGuid
,
885 (VOID
**) &mHiiConfigRouting
887 ASSERT_EFI_ERROR (Status
);
889 Status
= gBS
->LocateProtocol (
890 &gEfiDevicePathFromTextProtocolGuid
,
892 (VOID
**) &mPathFromText
896 // Install FormBrowser2 protocol
898 mPrivateData
.Handle
= NULL
;
899 Status
= gBS
->InstallProtocolInterface (
900 &mPrivateData
.Handle
,
901 &gEfiFormBrowser2ProtocolGuid
,
902 EFI_NATIVE_INTERFACE
,
903 &mPrivateData
.FormBrowser2
905 ASSERT_EFI_ERROR (Status
);
908 // Install FormBrowserEx2 protocol
910 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
911 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
912 mPrivateData
.Handle
= NULL
;
913 Status
= gBS
->InstallProtocolInterface (
914 &mPrivateData
.Handle
,
915 &gEdkiiFormBrowserEx2ProtocolGuid
,
916 EFI_NATIVE_INTERFACE
,
917 &mPrivateData
.FormBrowserEx2
919 ASSERT_EFI_ERROR (Status
);
921 Status
= gBS
->InstallProtocolInterface (
922 &mPrivateData
.Handle
,
923 &gEfiFormBrowserExProtocolGuid
,
924 EFI_NATIVE_INTERFACE
,
925 &mPrivateData
.FormBrowserEx
927 ASSERT_EFI_ERROR (Status
);
929 InitializeDisplayFormData ();
931 Status
= gBS
->LocateProtocol (
932 &gEdkiiFormDisplayEngineProtocolGuid
,
934 (VOID
**) &mFormDisplay
937 if (EFI_ERROR (Status
)) {
938 EfiCreateProtocolNotifyEvent (
939 &gEdkiiFormDisplayEngineProtocolGuid
,
952 Create a new string in HII Package List.
954 @param String The String to be added
955 @param HiiHandle The package list in the HII database to insert the
958 @return The output string.
964 IN EFI_HII_HANDLE HiiHandle
967 EFI_STRING_ID StringId
;
969 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
970 ASSERT (StringId
!= 0);
977 Delete a string from HII Package List.
979 @param StringId Id of the string in HII database.
980 @param HiiHandle The HII package list handle.
982 @retval EFI_SUCCESS The string was deleted successfully.
987 IN EFI_STRING_ID StringId
,
988 IN EFI_HII_HANDLE HiiHandle
993 NullChar
= CHAR_NULL
;
994 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1000 Get the string based on the StringId and HII Package List Handle.
1002 @param Token The String's ID.
1003 @param HiiHandle The package list in the HII database to search for
1004 the specified string.
1006 @return The output string.
1011 IN EFI_STRING_ID Token
,
1012 IN EFI_HII_HANDLE HiiHandle
1017 if (HiiHandle
== NULL
) {
1021 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1022 if (String
== NULL
) {
1023 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1024 ASSERT (String
!= NULL
);
1026 return (CHAR16
*) String
;
1031 Allocate new memory and then copy the Unicode string Source to Destination.
1033 @param Dest Location to copy string
1034 @param Src String to copy
1039 IN OUT CHAR16
**Dest
,
1043 if (*Dest
!= NULL
) {
1046 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1047 ASSERT (*Dest
!= NULL
);
1052 Allocate new memory and concatinate Source on the end of Destination.
1054 @param Dest String to added to the end of.
1055 @param Src String to concatinate.
1060 IN OUT CHAR16
**Dest
,
1067 if (*Dest
== NULL
) {
1068 NewStringCpy (Dest
, Src
);
1072 TmpSize
= StrSize (*Dest
);
1073 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1074 ASSERT (NewString
!= NULL
);
1076 StrCpy (NewString
, *Dest
);
1077 StrCat (NewString
, Src
);
1084 Get Value for given Name from a NameValue Storage.
1086 @param Storage The NameValue Storage.
1087 @param Name The Name.
1088 @param Value The retured Value.
1089 @param GetValueFrom Where to get source value, from EditValue or Value.
1091 @retval EFI_SUCCESS Value found for given Name.
1092 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1097 IN BROWSER_STORAGE
*Storage
,
1099 IN OUT CHAR16
**Value
,
1100 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1104 NAME_VALUE_NODE
*Node
;
1106 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1107 return EFI_INVALID_PARAMETER
;
1112 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1113 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1114 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1116 if (StrCmp (Name
, Node
->Name
) == 0) {
1117 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1118 NewStringCpy (Value
, Node
->EditValue
);
1120 NewStringCpy (Value
, Node
->Value
);
1125 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1128 return EFI_NOT_FOUND
;
1133 Set Value of given Name in a NameValue Storage.
1135 @param Storage The NameValue Storage.
1136 @param Name The Name.
1137 @param Value The Value to set.
1138 @param SetValueTo Whether update editValue or Value.
1139 @param ReturnNode The node use the input name.
1141 @retval EFI_SUCCESS Value found for given Name.
1142 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1147 IN BROWSER_STORAGE
*Storage
,
1150 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1151 OUT NAME_VALUE_NODE
**ReturnNode
1155 NAME_VALUE_NODE
*Node
;
1158 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1159 return EFI_INVALID_PARAMETER
;
1162 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1163 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1164 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1166 if (StrCmp (Name
, Node
->Name
) == 0) {
1167 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1168 Buffer
= Node
->EditValue
;
1170 Buffer
= Node
->Value
;
1172 if (Buffer
!= NULL
) {
1175 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1176 ASSERT (Buffer
!= NULL
);
1177 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1178 Node
->EditValue
= Buffer
;
1180 Node
->Value
= Buffer
;
1183 if (ReturnNode
!= NULL
) {
1190 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1193 return EFI_NOT_FOUND
;
1198 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1200 @param Storage The Storage to be conveted.
1201 @param ConfigResp The returned <ConfigResp>.
1202 @param ConfigRequest The ConfigRequest string.
1203 @param GetEditBuf Get the data from editbuffer or buffer.
1205 @retval EFI_SUCCESS Convert success.
1206 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1210 StorageToConfigResp (
1211 IN BROWSER_STORAGE
*Storage
,
1212 IN CHAR16
**ConfigResp
,
1213 IN CHAR16
*ConfigRequest
,
1214 IN BOOLEAN GetEditBuf
1218 EFI_STRING Progress
;
1220 NAME_VALUE_NODE
*Node
;
1223 Status
= EFI_SUCCESS
;
1225 switch (Storage
->Type
) {
1226 case EFI_HII_VARSTORE_BUFFER
:
1227 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1228 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1229 Status
= mHiiConfigRouting
->BlockToConfig (
1239 case EFI_HII_VARSTORE_NAME_VALUE
:
1241 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1243 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1244 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1245 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1247 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1248 NewStringCat (ConfigResp
, L
"&");
1249 NewStringCat (ConfigResp
, Node
->Name
);
1250 NewStringCat (ConfigResp
, L
"=");
1252 NewStringCat (ConfigResp
, Node
->EditValue
);
1254 NewStringCat (ConfigResp
, Node
->Value
);
1257 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1261 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1263 Status
= EFI_INVALID_PARAMETER
;
1272 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1274 @param Storage The Storage to receive the settings.
1275 @param ConfigResp The <ConfigResp> to be converted.
1277 @retval EFI_SUCCESS Convert success.
1278 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1282 ConfigRespToStorage (
1283 IN BROWSER_STORAGE
*Storage
,
1284 IN CHAR16
*ConfigResp
1288 EFI_STRING Progress
;
1294 Status
= EFI_SUCCESS
;
1296 switch (Storage
->Type
) {
1297 case EFI_HII_VARSTORE_BUFFER
:
1298 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1299 BufferSize
= Storage
->Size
;
1300 Status
= mHiiConfigRouting
->ConfigToBlock (
1303 Storage
->EditBuffer
,
1309 case EFI_HII_VARSTORE_NAME_VALUE
:
1310 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1311 if (StrPtr
== NULL
) {
1314 StrPtr
= StrStr (ConfigResp
, L
"&");
1315 while (StrPtr
!= NULL
) {
1319 StrPtr
= StrPtr
+ 1;
1321 StrPtr
= StrStr (StrPtr
, L
"=");
1322 if (StrPtr
== NULL
) {
1330 StrPtr
= StrPtr
+ 1;
1332 StrPtr
= StrStr (StrPtr
, L
"&");
1333 if (StrPtr
!= NULL
) {
1336 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1340 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1342 Status
= EFI_INVALID_PARAMETER
;
1350 Convert the buffer value to HiiValue.
1352 @param Question The question.
1353 @param Value Unicode buffer save the question value.
1355 @retval Status whether convert the value success.
1360 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1365 BOOLEAN IsBufferStorage
;
1377 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1378 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1379 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1380 IsBufferStorage
= TRUE
;
1382 IsBufferStorage
= FALSE
;
1386 // Question Value is provided by Buffer Storage or NameValue Storage
1388 if (Question
->BufferValue
!= NULL
) {
1390 // This Question is password or orderedlist
1392 Dst
= Question
->BufferValue
;
1395 // Other type of Questions
1397 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1401 // Temp cut at the end of this section, end with '\0' or '&'.
1404 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1407 TempChar
= *StringPtr
;
1410 LengthStr
= StrLen (Value
);
1411 Status
= EFI_SUCCESS
;
1412 if (!IsBufferStorage
&& IsString
) {
1414 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1415 // Add string tail char L'\0' into Length
1417 Length
= Question
->StorageWidth
+ sizeof (CHAR16
);
1418 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1419 Status
= EFI_BUFFER_TOO_SMALL
;
1421 DstBuf
= (CHAR16
*) Dst
;
1422 ZeroMem (TemStr
, sizeof (TemStr
));
1423 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1424 StrnCpy (TemStr
, Value
+ Index
, 4);
1425 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1428 // Add tailing L'\0' character
1430 DstBuf
[Index
/4] = L
'\0';
1433 if (Question
->StorageWidth
< ((LengthStr
+ 1) / 2)) {
1434 Status
= EFI_BUFFER_TOO_SMALL
;
1436 ZeroMem (TemStr
, sizeof (TemStr
));
1437 for (Index
= 0; Index
< LengthStr
; Index
++) {
1438 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1439 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1440 if ((Index
& 1) == 0) {
1441 Dst
[Index
/2] = DigitUint8
;
1443 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1449 *StringPtr
= TempChar
;
1455 Get Question's current Value.
1457 @param FormSet FormSet data structure.
1458 @param Form Form data structure.
1459 @param Question Question to be initialized.
1460 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1462 @retval EFI_SUCCESS The function completed successfully.
1467 IN FORM_BROWSER_FORMSET
*FormSet
,
1468 IN FORM_BROWSER_FORM
*Form
,
1469 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1470 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1479 BROWSER_STORAGE
*Storage
;
1480 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1481 CHAR16
*ConfigRequest
;
1486 BOOLEAN IsBufferStorage
;
1488 Status
= EFI_SUCCESS
;
1492 if (GetValueFrom
>= GetSetValueWithMax
) {
1493 return EFI_INVALID_PARAMETER
;
1497 // Question value is provided by an Expression, evaluate it
1499 if (Question
->ValueExpression
!= NULL
) {
1500 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1501 if (!EFI_ERROR (Status
)) {
1502 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1503 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1504 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1505 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1506 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1508 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1509 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1511 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1513 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1514 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1520 // Get question value by read expression.
1522 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1523 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1524 if (!EFI_ERROR (Status
) &&
1525 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1527 // Only update question value to the valid result.
1529 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1530 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1531 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1532 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1533 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1535 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1536 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1538 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1540 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1541 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1547 // Question value is provided by RTC
1549 Storage
= Question
->Storage
;
1550 QuestionValue
= &Question
->HiiValue
.Value
;
1551 if (Storage
== NULL
) {
1553 // It's a Question without storage, or RTC date/time
1555 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1557 // Date and time define the same Flags bit
1559 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1560 case QF_DATE_STORAGE_TIME
:
1561 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1564 case QF_DATE_STORAGE_WAKEUP
:
1565 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1568 case QF_DATE_STORAGE_NORMAL
:
1571 // For date/time without storage
1576 if (EFI_ERROR (Status
)) {
1580 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1581 QuestionValue
->date
.Year
= EfiTime
.Year
;
1582 QuestionValue
->date
.Month
= EfiTime
.Month
;
1583 QuestionValue
->date
.Day
= EfiTime
.Day
;
1585 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1586 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1587 QuestionValue
->time
.Second
= EfiTime
.Second
;
1595 // Question value is provided by EFI variable
1597 StorageWidth
= Question
->StorageWidth
;
1598 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1599 if (Question
->BufferValue
!= NULL
) {
1600 Dst
= Question
->BufferValue
;
1602 Dst
= (UINT8
*) QuestionValue
;
1605 Status
= gRT
->GetVariable (
1606 Question
->VariableName
,
1613 // Always return success, even this EFI variable doesn't exist
1619 // Question Value is provided by Buffer Storage or NameValue Storage
1621 if (Question
->BufferValue
!= NULL
) {
1623 // This Question is password or orderedlist
1625 Dst
= Question
->BufferValue
;
1628 // Other type of Questions
1630 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1633 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1634 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1635 IsBufferStorage
= TRUE
;
1637 IsBufferStorage
= FALSE
;
1639 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1640 if (IsBufferStorage
) {
1641 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1643 // Copy from storage Edit buffer
1645 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1648 // Copy from storage Edit buffer
1650 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1654 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1655 if (EFI_ERROR (Status
)) {
1659 ASSERT (Value
!= NULL
);
1660 Status
= BufferToValue (Question
, Value
);
1665 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1666 // <ConfigHdr> + "&" + <VariableName>
1668 if (IsBufferStorage
) {
1669 Length
= StrLen (Storage
->ConfigHdr
);
1670 Length
+= StrLen (Question
->BlockName
);
1672 Length
= StrLen (Storage
->ConfigHdr
);
1673 Length
+= StrLen (Question
->VariableName
) + 1;
1675 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1676 ASSERT (ConfigRequest
!= NULL
);
1678 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1679 if (IsBufferStorage
) {
1680 StrCat (ConfigRequest
, Question
->BlockName
);
1682 StrCat (ConfigRequest
, L
"&");
1683 StrCat (ConfigRequest
, Question
->VariableName
);
1687 // Request current settings from Configuration Driver
1689 Status
= mHiiConfigRouting
->ExtractConfig (
1695 FreePool (ConfigRequest
);
1696 if (EFI_ERROR (Status
)) {
1701 // Skip <ConfigRequest>
1703 if (IsBufferStorage
) {
1704 Value
= StrStr (Result
, L
"&VALUE");
1705 if (Value
== NULL
) {
1707 return EFI_NOT_FOUND
;
1714 Value
= Result
+ Length
;
1716 if (*Value
!= '=') {
1718 return EFI_NOT_FOUND
;
1721 // Skip '=', point to value
1725 Status
= BufferToValue (Question
, Value
);
1726 if (EFI_ERROR (Status
)) {
1732 // Synchronize Edit Buffer
1734 if (IsBufferStorage
) {
1735 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1737 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1740 if (Result
!= NULL
) {
1750 Save Question Value to edit copy(cached) or Storage(uncached).
1752 @param FormSet FormSet data structure.
1753 @param Form Form data structure.
1754 @param Question Pointer to the Question.
1755 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1757 @retval EFI_SUCCESS The function completed successfully.
1762 IN FORM_BROWSER_FORMSET
*FormSet
,
1763 IN FORM_BROWSER_FORM
*Form
,
1764 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1765 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1775 BROWSER_STORAGE
*Storage
;
1776 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1781 BOOLEAN IsBufferStorage
;
1787 NAME_VALUE_NODE
*Node
;
1789 Status
= EFI_SUCCESS
;
1792 if (SetValueTo
>= GetSetValueWithMax
) {
1793 return EFI_INVALID_PARAMETER
;
1797 // If Question value is provided by an Expression, then it is read only
1799 if (Question
->ValueExpression
!= NULL
) {
1804 // Before set question value, evaluate its write expression.
1806 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1807 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1808 if (EFI_ERROR (Status
)) {
1814 // Question value is provided by RTC
1816 Storage
= Question
->Storage
;
1817 QuestionValue
= &Question
->HiiValue
.Value
;
1818 if (Storage
== NULL
) {
1820 // It's a Question without storage, or RTC date/time
1822 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1824 // Date and time define the same Flags bit
1826 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1827 case QF_DATE_STORAGE_TIME
:
1828 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1831 case QF_DATE_STORAGE_WAKEUP
:
1832 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1835 case QF_DATE_STORAGE_NORMAL
:
1838 // For date/time without storage
1843 if (EFI_ERROR (Status
)) {
1847 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1848 EfiTime
.Year
= QuestionValue
->date
.Year
;
1849 EfiTime
.Month
= QuestionValue
->date
.Month
;
1850 EfiTime
.Day
= QuestionValue
->date
.Day
;
1852 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1853 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1854 EfiTime
.Second
= QuestionValue
->time
.Second
;
1857 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1858 Status
= gRT
->SetTime (&EfiTime
);
1860 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1868 // Question value is provided by EFI variable
1870 StorageWidth
= Question
->StorageWidth
;
1871 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1872 if (Question
->BufferValue
!= NULL
) {
1873 Src
= Question
->BufferValue
;
1875 Src
= (UINT8
*) QuestionValue
;
1878 Status
= gRT
->SetVariable (
1879 Question
->VariableName
,
1881 Storage
->Attributes
,
1889 // Question Value is provided by Buffer Storage or NameValue Storage
1891 if (Question
->BufferValue
!= NULL
) {
1892 Src
= Question
->BufferValue
;
1894 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1897 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1898 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1899 IsBufferStorage
= TRUE
;
1901 IsBufferStorage
= FALSE
;
1903 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1905 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1906 if (IsBufferStorage
) {
1907 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1909 // Copy to storage edit buffer
1911 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1912 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1914 // Copy to storage edit buffer
1916 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1921 // Allocate enough string buffer.
1924 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1925 Value
= AllocateZeroPool (BufferLen
);
1926 ASSERT (Value
!= NULL
);
1928 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1930 TemName
= (CHAR16
*) Src
;
1932 for (; *TemName
!= L
'\0'; TemName
++) {
1933 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1936 BufferLen
= StorageWidth
* 2 + 1;
1937 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1938 ASSERT (Value
!= NULL
);
1940 // Convert Buffer to Hex String
1942 TemBuffer
= Src
+ StorageWidth
- 1;
1944 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1945 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1949 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1951 if (EFI_ERROR (Status
)) {
1955 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1957 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1958 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1960 if (IsBufferStorage
) {
1961 Length
= StrLen (Question
->BlockName
) + 7;
1963 Length
= StrLen (Question
->VariableName
) + 2;
1965 if (!IsBufferStorage
&& IsString
) {
1966 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1968 Length
+= (StorageWidth
* 2);
1970 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1971 ASSERT (ConfigResp
!= NULL
);
1973 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1974 if (IsBufferStorage
) {
1975 StrCat (ConfigResp
, Question
->BlockName
);
1976 StrCat (ConfigResp
, L
"&VALUE=");
1978 StrCat (ConfigResp
, L
"&");
1979 StrCat (ConfigResp
, Question
->VariableName
);
1980 StrCat (ConfigResp
, L
"=");
1983 Value
= ConfigResp
+ StrLen (ConfigResp
);
1985 if (!IsBufferStorage
&& IsString
) {
1987 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1989 TemName
= (CHAR16
*) Src
;
1991 for (; *TemName
!= L
'\0'; TemName
++) {
1992 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1996 // Convert Buffer to Hex String
1998 TemBuffer
= Src
+ StorageWidth
- 1;
2000 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2001 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2006 // Convert to lower char.
2008 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2009 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2010 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2015 // Submit Question Value to Configuration Driver
2017 Status
= mHiiConfigRouting
->RouteConfig (
2022 if (EFI_ERROR (Status
)) {
2023 FreePool (ConfigResp
);
2026 FreePool (ConfigResp
);
2029 // Sync storage, from editbuffer to buffer.
2031 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2039 Perform nosubmitif check for a Form.
2041 @param FormSet FormSet data structure.
2042 @param Form Form data structure.
2043 @param Question The Question to be validated.
2044 @param Type Validation type: NoSubmit
2046 @retval EFI_SUCCESS Form validation pass.
2047 @retval other Form validation failed.
2052 IN FORM_BROWSER_FORMSET
*FormSet
,
2053 IN FORM_BROWSER_FORM
*Form
,
2054 IN FORM_BROWSER_STATEMENT
*Question
,
2060 LIST_ENTRY
*ListHead
;
2061 FORM_EXPRESSION
*Expression
;
2062 UINT32 BrowserStatus
;
2065 BrowserStatus
= BROWSER_SUCCESS
;
2069 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2070 ListHead
= &Question
->InconsistentListHead
;
2073 case EFI_HII_EXPRESSION_WARNING_IF
:
2074 ListHead
= &Question
->WarningListHead
;
2077 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2078 ListHead
= &Question
->NoSubmitListHead
;
2083 return EFI_UNSUPPORTED
;
2086 Link
= GetFirstNode (ListHead
);
2087 while (!IsNull (ListHead
, Link
)) {
2088 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2091 // Evaluate the expression
2093 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2094 if (EFI_ERROR (Status
)) {
2098 if (IsTrue (&Expression
->Result
)) {
2100 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2101 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2104 case EFI_HII_EXPRESSION_WARNING_IF
:
2105 BrowserStatus
= BROWSER_WARNING_IF
;
2108 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2109 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2111 // This code only used to compatible with old display engine,
2112 // New display engine will not use this field.
2114 if (Expression
->Error
!= 0) {
2115 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2124 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2126 // If in system submit process and for no_submit_if check, not popup this error message.
2127 // Will process this fail again later in not system submit process.
2129 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2132 if (ErrorStr
!= NULL
) {
2133 FreePool (ErrorStr
);
2136 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2139 return EFI_NOT_READY
;
2143 Link
= GetNextNode (ListHead
, Link
);
2150 Perform question check.
2152 If one question has more than one check, process form high priority to low.
2153 Only one error info will be popup.
2155 @param FormSet FormSet data structure.
2156 @param Form Form data structure.
2157 @param Question The Question to be validated.
2159 @retval EFI_SUCCESS Form validation pass.
2160 @retval other Form validation failed.
2164 ValueChangedValidation (
2165 IN FORM_BROWSER_FORMSET
*FormSet
,
2166 IN FORM_BROWSER_FORM
*Form
,
2167 IN FORM_BROWSER_STATEMENT
*Question
2172 Status
= EFI_SUCCESS
;
2175 // Do the inconsistentif check.
2177 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2178 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2179 if (EFI_ERROR (Status
)) {
2185 // Do the warningif check.
2187 if (!IsListEmpty (&Question
->WarningListHead
)) {
2188 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2195 Perform NoSubmit check for each Form in FormSet.
2197 @param FormSet FormSet data structure.
2198 @param CurrentForm Current input form data structure.
2199 @param Statement The statement for this check.
2201 @retval EFI_SUCCESS Form validation pass.
2202 @retval other Form validation failed.
2207 IN FORM_BROWSER_FORMSET
*FormSet
,
2208 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2209 OUT FORM_BROWSER_STATEMENT
**Statement
2214 FORM_BROWSER_STATEMENT
*Question
;
2215 FORM_BROWSER_FORM
*Form
;
2216 LIST_ENTRY
*LinkForm
;
2218 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2219 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2220 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2221 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2223 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2227 Link
= GetFirstNode (&Form
->StatementListHead
);
2228 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2229 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2230 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2231 if (EFI_ERROR (Status
)) {
2232 if (*CurrentForm
== NULL
) {
2233 *CurrentForm
= Form
;
2235 if (Statement
!= NULL
) {
2236 *Statement
= Question
;
2241 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2249 Fill storage's edit copy with settings requested from Configuration Driver.
2251 @param Storage The storage which need to sync.
2252 @param ConfigRequest The config request string which used to sync storage.
2253 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2254 editbuffer to buffer
2255 if TRUE, copy the editbuffer to the buffer.
2256 if FALSE, copy the buffer to the editbuffer.
2258 @retval EFI_SUCCESS The function completed successfully.
2262 SynchronizeStorage (
2263 OUT BROWSER_STORAGE
*Storage
,
2264 IN CHAR16
*ConfigRequest
,
2265 IN BOOLEAN SyncOrRestore
2269 EFI_STRING Progress
;
2273 NAME_VALUE_NODE
*Node
;
2277 Status
= EFI_SUCCESS
;
2280 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2281 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2282 BufferSize
= Storage
->Size
;
2284 if (SyncOrRestore
) {
2285 Src
= Storage
->EditBuffer
;
2286 Dst
= Storage
->Buffer
;
2288 Src
= Storage
->Buffer
;
2289 Dst
= Storage
->EditBuffer
;
2292 if (ConfigRequest
!= NULL
) {
2293 Status
= mHiiConfigRouting
->BlockToConfig(
2301 if (EFI_ERROR (Status
)) {
2305 Status
= mHiiConfigRouting
->ConfigToBlock (
2312 if (Result
!= NULL
) {
2316 CopyMem (Dst
, Src
, BufferSize
);
2318 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2319 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2320 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2321 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2323 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2324 (ConfigRequest
== NULL
)) {
2325 if (SyncOrRestore
) {
2326 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2328 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2332 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2340 When discard the question value, call the callback function with Changed type
2341 to inform the hii driver.
2343 @param FormSet FormSet data structure.
2344 @param Form Form data structure.
2348 SendDiscardInfoToDriver (
2349 IN FORM_BROWSER_FORMSET
*FormSet
,
2350 IN FORM_BROWSER_FORM
*Form
2354 FORM_BROWSER_STATEMENT
*Question
;
2355 EFI_IFR_TYPE_VALUE
*TypeValue
;
2356 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2358 if (FormSet
->ConfigAccess
== NULL
) {
2362 Link
= GetFirstNode (&Form
->StatementListHead
);
2363 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2364 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2365 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2367 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2371 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2375 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2379 if (!Question
->ValueChanged
) {
2384 // Restore the question value before call the CHANGED callback type.
2386 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2388 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2389 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2391 TypeValue
= &Question
->HiiValue
.Value
;
2394 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2395 FormSet
->ConfigAccess
->Callback (
2396 FormSet
->ConfigAccess
,
2397 EFI_BROWSER_ACTION_CHANGED
,
2398 Question
->QuestionId
,
2399 Question
->HiiValue
.Type
,
2407 Validate the HiiHandle.
2409 @param HiiHandle The input HiiHandle which need to validate.
2411 @retval TRUE The handle is validate.
2412 @retval FALSE The handle is invalidate.
2417 EFI_HII_HANDLE HiiHandle
2420 EFI_HII_HANDLE
*HiiHandles
;
2424 if (HiiHandle
== NULL
) {
2430 HiiHandles
= HiiGetHiiHandles (NULL
);
2431 ASSERT (HiiHandles
!= NULL
);
2433 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2434 if (HiiHandles
[Index
] == HiiHandle
) {
2440 FreePool (HiiHandles
);
2446 Validate the FormSet. If the formset is not validate, remove it from the list.
2448 @param FormSet The input FormSet which need to validate.
2450 @retval TRUE The handle is validate.
2451 @retval FALSE The handle is invalidate.
2456 FORM_BROWSER_FORMSET
*FormSet
2461 ASSERT (FormSet
!= NULL
);
2463 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2465 // Should not remove the formset which is being used.
2467 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2468 CleanBrowserStorage(FormSet
);
2469 RemoveEntryList (&FormSet
->Link
);
2470 DestroyFormSet (FormSet
);
2476 Check whether need to enable the reset flag in form level.
2477 Also clean all ValueChanged flag in question.
2479 @param SetFlag Whether need to set the Reset Flag.
2480 @param FormSet FormSet data structure.
2481 @param Form Form data structure.
2487 IN FORM_BROWSER_FORMSET
*FormSet
,
2488 IN FORM_BROWSER_FORM
*Form
2492 FORM_BROWSER_STATEMENT
*Question
;
2495 Link
= GetFirstNode (&Form
->StatementListHead
);
2496 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2497 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2498 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2500 if (!Question
->ValueChanged
) {
2504 OldValue
= Question
->ValueChanged
;
2507 // Compare the buffer and editbuffer data to see whether the data has been saved.
2509 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2512 // Only the changed data has been saved, then need to set the reset flag.
2514 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2515 gResetRequired
= TRUE
;
2521 Check whether need to enable the reset flag.
2522 Also clean ValueChanged flag for all statements.
2524 Form level or formset level, only one.
2526 @param SetFlag Whether need to set the Reset Flag.
2527 @param FormSet FormSet data structure.
2528 @param Form Form data structure.
2532 ValueChangeResetFlagUpdate (
2534 IN FORM_BROWSER_FORMSET
*FormSet
,
2535 IN FORM_BROWSER_FORM
*Form
2538 FORM_BROWSER_FORM
*CurrentForm
;
2542 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2546 Link
= GetFirstNode (&FormSet
->FormListHead
);
2547 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2548 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2549 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2551 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2556 Base on the return Progress string to find the form.
2558 Base on the first return Offset/Width (Name) string to find the form
2559 which keep this string.
2561 @param FormSet FormSet data structure.
2562 @param Storage Storage which has this Progress string.
2563 @param Progress The Progress string which has the first fail string.
2564 @param RetForm The return form for this progress string.
2565 @param RetQuestion The return question for the error progress string.
2567 @retval TRUE Find the error form and statement for this error progress string.
2568 @retval FALSE Not find the error form.
2572 FindQuestionFromProgress (
2573 IN FORM_BROWSER_FORMSET
*FormSet
,
2574 IN BROWSER_STORAGE
*Storage
,
2575 IN EFI_STRING Progress
,
2576 OUT FORM_BROWSER_FORM
**RetForm
,
2577 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2581 LIST_ENTRY
*LinkStorage
;
2582 LIST_ENTRY
*LinkStatement
;
2583 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2584 FORM_BROWSER_FORM
*Form
;
2586 FORM_BROWSER_STATEMENT
*Statement
;
2588 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2592 *RetQuestion
= NULL
;
2595 // Skip the first "&" or the ConfigHdr part.
2597 if (*Progress
== '&') {
2601 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2603 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2605 // For Name/Value type, Skip the ConfigHdr part.
2607 EndStr
= StrStr (Progress
, L
"PATH=");
2608 ASSERT (EndStr
!= NULL
);
2609 while (*EndStr
!= '&') {
2616 // For Buffer type, Skip the ConfigHdr part.
2618 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2619 ASSERT (EndStr
!= NULL
);
2623 Progress
= EndStr
+ 1;
2627 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2629 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2631 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2632 // here, just keep the "Fred" string.
2634 EndStr
= StrStr (Progress
, L
"=");
2635 ASSERT (EndStr
!= NULL
);
2639 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2640 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2642 EndStr
= StrStr (Progress
, L
"&VALUE=");
2643 ASSERT (EndStr
!= NULL
);
2648 // Search in the form list.
2650 Link
= GetFirstNode (&FormSet
->FormListHead
);
2651 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2652 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2653 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2656 // Search in the ConfigReqeust list in this form.
2658 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2659 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2660 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2661 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2663 if (Storage
!= ConfigInfo
->Storage
) {
2667 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2669 // Find the OffsetWidth string in this form.
2676 if (*RetForm
!= NULL
) {
2677 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2678 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2679 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2680 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2682 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2683 *RetQuestion
= Statement
;
2689 if (*RetForm
!= NULL
) {
2695 // restore the OffsetWidth string to the original format.
2697 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2703 return (BOOLEAN
) (*RetForm
!= NULL
);
2707 Popup an save error info and get user input.
2709 @param TitleId The form title id.
2710 @param HiiHandle The hii handle for this package.
2712 @retval UINT32 The user select option for the save fail.
2713 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2717 IN EFI_STRING_ID TitleId
,
2718 IN EFI_HII_HANDLE HiiHandle
2722 CHAR16
*StringBuffer
;
2725 FormTitle
= GetToken (TitleId
, HiiHandle
);
2727 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2728 ASSERT (StringBuffer
!= NULL
);
2732 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2733 L
"Submit Fail For Form: %s.",
2737 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2739 FreePool (StringBuffer
);
2740 FreePool (FormTitle
);
2746 Popup an NO_SUBMIT_IF error info and get user input.
2748 @param TitleId The form title id.
2749 @param HiiHandle The hii handle for this package.
2751 @retval UINT32 The user select option for the save fail.
2752 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2755 ConfirmNoSubmitFail (
2756 IN EFI_STRING_ID TitleId
,
2757 IN EFI_HII_HANDLE HiiHandle
2761 CHAR16
*StringBuffer
;
2764 FormTitle
= GetToken (TitleId
, HiiHandle
);
2766 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2767 ASSERT (StringBuffer
!= NULL
);
2771 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2772 L
"NO_SUBMIT_IF error For Form: %s.",
2776 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2778 FreePool (StringBuffer
);
2779 FreePool (FormTitle
);
2785 Discard data based on the input setting scope (Form, FormSet or System).
2787 @param FormSet FormSet data structure.
2788 @param Form Form data structure.
2789 @param SettingScope Setting Scope for Discard action.
2791 @retval EFI_SUCCESS The function completed successfully.
2792 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2797 IN FORM_BROWSER_FORMSET
*FormSet
,
2798 IN FORM_BROWSER_FORM
*Form
,
2799 IN BROWSER_SETTING_SCOPE SettingScope
2803 FORMSET_STORAGE
*Storage
;
2804 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2805 FORM_BROWSER_FORMSET
*LocalFormSet
;
2806 FORM_BROWSER_FORMSET
*OldFormSet
;
2809 // Check the supported setting level.
2811 if (SettingScope
>= MaxLevel
) {
2812 return EFI_UNSUPPORTED
;
2815 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2817 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2818 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2819 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2820 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2822 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2827 // Skip if there is no RequestElement
2829 if (ConfigInfo
->ElementCount
== 0) {
2834 // Prepare <ConfigResp>
2836 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2839 // Call callback with Changed type to inform the driver.
2841 SendDiscardInfoToDriver (FormSet
, Form
);
2844 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2845 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2848 // Discard Buffer storage or Name/Value storage
2850 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2851 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2852 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2853 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2855 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2860 // Skip if there is no RequestElement
2862 if (Storage
->ElementCount
== 0) {
2866 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2869 Link
= GetFirstNode (&FormSet
->FormListHead
);
2870 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2871 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2872 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2875 // Call callback with Changed type to inform the driver.
2877 SendDiscardInfoToDriver (FormSet
, Form
);
2880 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2881 } else if (SettingScope
== SystemLevel
) {
2883 // System Level Discard.
2885 OldFormSet
= mSystemLevelFormSet
;
2888 // Discard changed value for each FormSet in the maintain list.
2890 Link
= GetFirstNode (&gBrowserFormSetList
);
2891 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2892 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2893 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2894 if (!ValidateFormSet(LocalFormSet
)) {
2898 mSystemLevelFormSet
= LocalFormSet
;
2900 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2901 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2903 // Remove maintain backup list after discard except for the current using FormSet.
2905 CleanBrowserStorage(LocalFormSet
);
2906 RemoveEntryList (&LocalFormSet
->Link
);
2907 DestroyFormSet (LocalFormSet
);
2911 mSystemLevelFormSet
= OldFormSet
;
2918 Submit data for a form.
2920 @param FormSet FormSet data structure.
2921 @param Form Form data structure.
2923 @retval EFI_SUCCESS The function completed successfully.
2924 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2929 IN FORM_BROWSER_FORMSET
*FormSet
,
2930 IN FORM_BROWSER_FORM
*Form
2935 EFI_STRING ConfigResp
;
2936 EFI_STRING Progress
;
2937 BROWSER_STORAGE
*Storage
;
2938 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2940 if (!IsNvUpdateRequiredForForm (Form
)) {
2944 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2945 if (EFI_ERROR (Status
)) {
2949 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2950 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2951 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2952 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2954 Storage
= ConfigInfo
->Storage
;
2955 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2960 // Skip if there is no RequestElement
2962 if (ConfigInfo
->ElementCount
== 0) {
2967 // 1. Prepare <ConfigResp>
2969 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2970 if (EFI_ERROR (Status
)) {
2975 // 2. Set value to hii config routine protocol.
2977 Status
= mHiiConfigRouting
->RouteConfig (
2982 FreePool (ConfigResp
);
2984 if (EFI_ERROR (Status
)) {
2985 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2990 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2992 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2996 // 4. Process the save failed storage.
2998 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2999 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3000 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3001 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3002 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3003 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3005 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3007 Status
= EFI_SUCCESS
;
3010 Status
= EFI_UNSUPPORTED
;
3014 // Free Form save fail list.
3016 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3017 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3018 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3019 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3024 // 5. Update the NV flag.
3026 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3032 Submit data for a formset.
3034 @param FormSet FormSet data structure.
3035 @param SkipProcessFail Whether skip to process the save failed storage.
3036 If submit formset is called when do system level save,
3037 set this value to true and process the failed formset
3039 if submit formset is called when do formset level save,
3040 set the value to false and process the failed storage
3041 right after process all storages for this formset.
3043 @retval EFI_SUCCESS The function completed successfully.
3044 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3049 IN FORM_BROWSER_FORMSET
*FormSet
,
3050 IN BOOLEAN SkipProcessFail
3055 EFI_STRING ConfigResp
;
3056 EFI_STRING Progress
;
3057 BROWSER_STORAGE
*Storage
;
3058 FORMSET_STORAGE
*FormSetStorage
;
3059 FORM_BROWSER_FORM
*Form
;
3060 BOOLEAN HasInserted
;
3061 FORM_BROWSER_STATEMENT
*Question
;
3063 HasInserted
= FALSE
;
3065 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3070 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3071 if (EFI_ERROR (Status
)) {
3072 if (SkipProcessFail
) {
3074 // Process NO_SUBMIT check first, so insert it at head.
3076 FormSet
->SaveFailForm
= Form
;
3077 FormSet
->SaveFailStatement
= Question
;
3078 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3087 // Submit Buffer storage or Name/Value storage
3089 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3090 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3091 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3092 Storage
= FormSetStorage
->BrowserStorage
;
3093 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3095 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3100 // Skip if there is no RequestElement
3102 if (FormSetStorage
->ElementCount
== 0) {
3107 // 1. Prepare <ConfigResp>
3109 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3110 if (EFI_ERROR (Status
)) {
3115 // 2. Send <ConfigResp> to Routine config Protocol.
3117 Status
= mHiiConfigRouting
->RouteConfig (
3122 if (EFI_ERROR (Status
)) {
3123 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3126 // Call submit formset for system level, save the formset info
3127 // and process later.
3129 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3130 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3131 FormSet
->SaveFailForm
= Form
;
3132 FormSet
->SaveFailStatement
= Question
;
3133 if (SkipProcessFail
) {
3134 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3139 FreePool (ConfigResp
);
3143 FreePool (ConfigResp
);
3145 // 3. Config success, update storage shadow Buffer
3147 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3151 // 4. Has save fail storage need to handle.
3154 if (!SkipProcessFail
) {
3156 // If not in system level, just handl the save failed storage here.
3158 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3159 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3160 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3161 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3162 Storage
= FormSetStorage
->BrowserStorage
;
3163 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3165 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3167 Status
= EFI_SUCCESS
;
3170 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3172 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3173 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3174 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3175 gCurrentSelection
->FormId
= Form
->FormId
;
3176 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3178 Status
= EFI_UNSUPPORTED
;
3182 // Free FormSet save fail list.
3184 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3185 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3186 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3187 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3191 // If in system level, just return error and handle the failed formset later.
3193 Status
= EFI_UNSUPPORTED
;
3198 // 5. Update the NV flag.
3200 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3206 Submit data for all formsets.
3208 @retval EFI_SUCCESS The function completed successfully.
3209 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3219 LIST_ENTRY
*StorageLink
;
3220 BROWSER_STORAGE
*Storage
;
3221 FORMSET_STORAGE
*FormSetStorage
;
3222 FORM_BROWSER_FORM
*Form
;
3223 FORM_BROWSER_FORMSET
*LocalFormSet
;
3224 UINT32 UserSelection
;
3225 FORM_BROWSER_STATEMENT
*Question
;
3227 mSystemSubmit
= TRUE
;
3228 Link
= GetFirstNode (&gBrowserFormSetList
);
3229 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3230 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3231 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3232 if (!ValidateFormSet(LocalFormSet
)) {
3236 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3237 if (EFI_ERROR (Status
)) {
3242 // Remove maintain backup list after save except for the current using FormSet.
3244 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3245 CleanBrowserStorage(LocalFormSet
);
3246 RemoveEntryList (&LocalFormSet
->Link
);
3247 DestroyFormSet (LocalFormSet
);
3250 mSystemSubmit
= FALSE
;
3252 Status
= EFI_SUCCESS
;
3255 // Process the save failed formsets.
3257 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3258 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3259 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3260 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3262 if (!ValidateFormSet(LocalFormSet
)) {
3266 Form
= LocalFormSet
->SaveFailForm
;
3267 Question
= LocalFormSet
->SaveFailStatement
;
3270 // Confirm with user, get user input.
3272 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3274 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3276 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3278 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3281 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3282 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3283 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3284 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3285 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3286 Storage
= FormSetStorage
->BrowserStorage
;
3287 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3289 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3292 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3293 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3294 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3295 Storage
= FormSetStorage
->BrowserStorage
;
3296 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3298 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3302 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3303 CleanBrowserStorage(LocalFormSet
);
3304 RemoveEntryList (&LocalFormSet
->Link
);
3305 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3306 DestroyFormSet (LocalFormSet
);
3308 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3311 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3312 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3315 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3317 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3318 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3319 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3320 gCurrentSelection
->FormId
= Form
->FormId
;
3321 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3323 Status
= EFI_UNSUPPORTED
;
3329 // Clean the list which will not process.
3331 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3332 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3333 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3334 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3336 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3337 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3338 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3339 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3347 Submit data based on the input Setting level (Form, FormSet or System).
3349 @param FormSet FormSet data structure.
3350 @param Form Form data structure.
3351 @param SettingScope Setting Scope for Submit action.
3353 @retval EFI_SUCCESS The function completed successfully.
3354 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3359 IN FORM_BROWSER_FORMSET
*FormSet
,
3360 IN FORM_BROWSER_FORM
*Form
,
3361 IN BROWSER_SETTING_SCOPE SettingScope
3366 switch (SettingScope
) {
3368 Status
= SubmitForForm(FormSet
, Form
);
3372 Status
= SubmitForFormSet (FormSet
, FALSE
);
3376 Status
= SubmitForSystem ();
3380 Status
= EFI_UNSUPPORTED
;
3388 Converts the unicode character of the string from uppercase to lowercase.
3389 This is a internal function.
3391 @param ConfigString String to be converted
3397 IN EFI_STRING ConfigString
3403 ASSERT (ConfigString
!= NULL
);
3406 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3408 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3409 if (*String
== L
'=') {
3411 } else if (*String
== L
'&') {
3413 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3414 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3420 Find the point in the ConfigResp string for this question.
3422 @param Question The question.
3423 @param ConfigResp Get ConfigResp string.
3425 @retval point to the offset where is for this question.
3429 GetOffsetFromConfigResp (
3430 IN FORM_BROWSER_STATEMENT
*Question
,
3431 IN CHAR16
*ConfigResp
3434 CHAR16
*RequestElement
;
3438 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3440 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3441 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3442 if (RequestElement
!= NULL
) {
3444 // Skip the "VariableName=" field.
3446 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3449 return RequestElement
;
3453 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3457 // 1. Directly use Question->BlockName to find.
3459 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3460 if (RequestElement
!= NULL
) {
3462 // Skip the "Question->BlockName&VALUE=" field.
3464 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3465 return RequestElement
;
3469 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3471 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3472 ASSERT (BlockData
!= NULL
);
3473 HiiToLower (BlockData
);
3474 RequestElement
= StrStr (ConfigResp
, BlockData
);
3475 FreePool (BlockData
);
3477 if (RequestElement
!= NULL
) {
3479 // Skip the "Question->BlockName&VALUE=" field.
3481 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3484 return RequestElement
;
3488 Get Question default value from AltCfg string.
3490 @param FormSet The form set.
3491 @param Form The form
3492 @param Question The question.
3494 @retval EFI_SUCCESS Question is reset to default value.
3498 GetDefaultValueFromAltCfg (
3499 IN FORM_BROWSER_FORMSET
*FormSet
,
3500 IN FORM_BROWSER_FORM
*Form
,
3501 IN OUT FORM_BROWSER_STATEMENT
*Question
3504 BROWSER_STORAGE
*Storage
;
3505 FORMSET_STORAGE
*FormSetStorage
;
3509 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3511 Storage
= Question
->Storage
;
3512 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3513 return EFI_NOT_FOUND
;
3517 // Try to get AltCfg string from form. If not found it, then
3518 // try to get it from formset.
3521 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3522 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3523 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3524 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3526 if (Storage
== ConfigInfo
->Storage
) {
3527 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3532 if (ConfigResp
== NULL
) {
3533 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3534 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3535 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3536 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3538 if (Storage
== FormSetStorage
->BrowserStorage
) {
3539 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3545 if (ConfigResp
== NULL
) {
3546 return EFI_NOT_FOUND
;
3549 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3550 if (Value
== NULL
) {
3551 return EFI_NOT_FOUND
;
3554 return BufferToValue (Question
, Value
);
3558 Get default Id value used for browser.
3560 @param DefaultId The default id value used by hii.
3562 @retval Browser used default value.
3566 GetDefaultIdForCallBack (
3570 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3571 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3572 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3573 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3574 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3575 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3576 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3577 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3578 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3579 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3580 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3581 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3590 Return data element in an Array by its Index.
3592 @param Array The data array.
3593 @param Type Type of the data in this array.
3594 @param Index Zero based index for data in this array.
3596 @retval Value The data to be returned
3608 ASSERT (Array
!= NULL
);
3612 case EFI_IFR_TYPE_NUM_SIZE_8
:
3613 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3616 case EFI_IFR_TYPE_NUM_SIZE_16
:
3617 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3620 case EFI_IFR_TYPE_NUM_SIZE_32
:
3621 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3624 case EFI_IFR_TYPE_NUM_SIZE_64
:
3625 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3637 Set value of a data element in an Array by its Index.
3639 @param Array The data array.
3640 @param Type Type of the data in this array.
3641 @param Index Zero based index for data in this array.
3642 @param Value The value to be set.
3654 ASSERT (Array
!= NULL
);
3657 case EFI_IFR_TYPE_NUM_SIZE_8
:
3658 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3661 case EFI_IFR_TYPE_NUM_SIZE_16
:
3662 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3665 case EFI_IFR_TYPE_NUM_SIZE_32
:
3666 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3669 case EFI_IFR_TYPE_NUM_SIZE_64
:
3670 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3679 Search an Option of a Question by its value.
3681 @param Question The Question
3682 @param OptionValue Value for Option to be searched.
3684 @retval Pointer Pointer to the found Option.
3685 @retval NULL Option not found.
3690 IN FORM_BROWSER_STATEMENT
*Question
,
3691 IN EFI_HII_VALUE
*OptionValue
3695 QUESTION_OPTION
*Option
;
3698 Link
= GetFirstNode (&Question
->OptionListHead
);
3699 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3700 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3702 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3704 // Check the suppressif condition, only a valid option can be return.
3706 if ((Option
->SuppressExpression
== NULL
) ||
3707 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3712 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3720 Reset Question to its default value.
3722 @param FormSet The form set.
3723 @param Form The form.
3724 @param Question The question.
3725 @param DefaultId The Class of the default.
3727 @retval EFI_SUCCESS Question is reset to default value.
3731 GetQuestionDefault (
3732 IN FORM_BROWSER_FORMSET
*FormSet
,
3733 IN FORM_BROWSER_FORM
*Form
,
3734 IN FORM_BROWSER_STATEMENT
*Question
,
3740 QUESTION_DEFAULT
*Default
;
3741 QUESTION_OPTION
*Option
;
3742 EFI_HII_VALUE
*HiiValue
;
3744 EFI_STRING StrValue
;
3745 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3746 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3750 Status
= EFI_NOT_FOUND
;
3754 // Statement don't have storage, skip them
3756 if (Question
->QuestionId
== 0) {
3761 // There are Five ways to specify default value for a Question:
3762 // 1, use call back function (highest priority)
3763 // 2, use ExtractConfig function
3764 // 3, use nested EFI_IFR_DEFAULT
3765 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3766 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3768 HiiValue
= &Question
->HiiValue
;
3771 // Get Question defaut value from call back function.
3773 ConfigAccess
= FormSet
->ConfigAccess
;
3774 Action
= GetDefaultIdForCallBack (DefaultId
);
3775 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3776 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3777 Status
= ConfigAccess
->Callback (
3780 Question
->QuestionId
,
3785 if (!EFI_ERROR (Status
)) {
3786 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3787 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3788 ASSERT (NewString
!= NULL
);
3790 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3791 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3792 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3794 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3797 FreePool (NewString
);
3804 // Get default value from altcfg string.
3806 if (ConfigAccess
!= NULL
) {
3807 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
3808 if (!EFI_ERROR (Status
)) {
3814 // EFI_IFR_DEFAULT has highest priority
3816 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3817 Link
= GetFirstNode (&Question
->DefaultListHead
);
3818 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3819 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3821 if (Default
->DefaultId
== DefaultId
) {
3822 if (Default
->ValueExpression
!= NULL
) {
3824 // Default is provided by an Expression, evaluate it
3826 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3827 if (EFI_ERROR (Status
)) {
3831 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3832 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3833 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3834 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3835 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3837 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3838 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3840 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3842 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3843 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3846 // Default value is embedded in EFI_IFR_DEFAULT
3848 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3851 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3852 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3853 if (StrValue
== NULL
) {
3854 return EFI_NOT_FOUND
;
3856 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3857 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3859 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3866 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3871 // EFI_ONE_OF_OPTION
3873 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3874 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3876 // OneOfOption could only provide Standard and Manufacturing default
3878 Link
= GetFirstNode (&Question
->OptionListHead
);
3879 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3880 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3881 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3883 if ((Option
->SuppressExpression
!= NULL
) &&
3884 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3888 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3889 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3891 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3900 // EFI_IFR_CHECKBOX - lowest priority
3902 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3903 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3905 // Checkbox could only provide Standard and Manufacturing default
3907 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3908 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3910 HiiValue
->Value
.b
= TRUE
;
3912 HiiValue
->Value
.b
= FALSE
;
3920 // For Questions without default
3922 Status
= EFI_NOT_FOUND
;
3923 switch (Question
->Operand
) {
3924 case EFI_IFR_NUMERIC_OP
:
3926 // Take minimum value as numeric default value
3928 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3929 HiiValue
->Value
.u64
= Question
->Minimum
;
3930 Status
= EFI_SUCCESS
;
3934 case EFI_IFR_ONE_OF_OP
:
3936 // Take first oneof option as oneof's default value
3938 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3939 Link
= GetFirstNode (&Question
->OptionListHead
);
3940 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3941 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3942 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3944 if ((Option
->SuppressExpression
!= NULL
) &&
3945 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3949 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3950 Status
= EFI_SUCCESS
;
3956 case EFI_IFR_ORDERED_LIST_OP
:
3958 // Take option sequence in IFR as ordered list's default value
3961 Link
= GetFirstNode (&Question
->OptionListHead
);
3962 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3963 Status
= EFI_SUCCESS
;
3964 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3965 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3967 if ((Option
->SuppressExpression
!= NULL
) &&
3968 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3972 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3975 if (Index
>= Question
->MaxContainers
) {
3989 Get AltCfg string for current form.
3991 @param FormSet Form data structure.
3992 @param Form Form data structure.
3993 @param DefaultId The Class of the default.
3997 ExtractAltCfgForForm (
3998 IN FORM_BROWSER_FORMSET
*FormSet
,
3999 IN FORM_BROWSER_FORM
*Form
,
4008 BROWSER_STORAGE
*Storage
;
4009 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4010 FORMSET_STORAGE
*FormSetStorage
;
4013 // Check whether has get AltCfg string for this formset.
4014 // If yes, no need to get AltCfg for form.
4016 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4017 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4018 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4019 Storage
= FormSetStorage
->BrowserStorage
;
4020 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4022 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4023 FormSetStorage
->ElementCount
!= 0 &&
4024 FormSetStorage
->ConfigAltResp
!= NULL
) {
4030 // Get AltCfg string for each form.
4032 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4033 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4034 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4035 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4037 Storage
= ConfigInfo
->Storage
;
4038 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4043 // 1. Skip if there is no RequestElement
4045 if (ConfigInfo
->ElementCount
== 0) {
4050 // 2. Get value through hii config routine protocol.
4052 Status
= mHiiConfigRouting
->ExtractConfig (
4054 ConfigInfo
->ConfigRequest
,
4058 if (EFI_ERROR (Status
)) {
4063 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4064 // Get the default configuration string according to the default ID.
4066 Status
= mHiiConfigRouting
->GetAltConfig (
4072 &DefaultId
, // it can be NULL to get the current setting.
4076 if (EFI_ERROR (Status
)) {
4080 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4085 Clean AltCfg string for current form.
4087 @param Form Form data structure.
4091 CleanAltCfgForForm (
4092 IN FORM_BROWSER_FORM
*Form
4096 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4098 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4099 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4100 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4101 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4103 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4104 FreePool (ConfigInfo
->ConfigAltResp
);
4105 ConfigInfo
->ConfigAltResp
= NULL
;
4111 Get AltCfg string for current formset.
4113 @param FormSet Form data structure.
4114 @param DefaultId The Class of the default.
4118 ExtractAltCfgForFormSet (
4119 IN FORM_BROWSER_FORMSET
*FormSet
,
4128 BROWSER_STORAGE
*Storage
;
4129 FORMSET_STORAGE
*FormSetStorage
;
4131 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4132 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4133 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4134 Storage
= FormSetStorage
->BrowserStorage
;
4135 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4137 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4142 // 1. Skip if there is no RequestElement
4144 if (FormSetStorage
->ElementCount
== 0) {
4149 // 2. Get value through hii config routine protocol.
4151 Status
= mHiiConfigRouting
->ExtractConfig (
4153 FormSetStorage
->ConfigRequest
,
4157 if (EFI_ERROR (Status
)) {
4162 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4163 // Get the default configuration string according to the default ID.
4165 Status
= mHiiConfigRouting
->GetAltConfig (
4171 &DefaultId
, // it can be NULL to get the current setting.
4176 if (EFI_ERROR (Status
)) {
4180 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4186 Clean AltCfg string for current formset.
4188 @param FormSet Form data structure.
4192 CleanAltCfgForFormSet (
4193 IN FORM_BROWSER_FORMSET
*FormSet
4197 FORMSET_STORAGE
*FormSetStorage
;
4199 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4200 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4201 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4202 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4204 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4205 FreePool (FormSetStorage
->ConfigAltResp
);
4206 FormSetStorage
->ConfigAltResp
= NULL
;
4212 Reset Questions to their initial value or default value in a Form, Formset or System.
4214 GetDefaultValueScope parameter decides which questions will reset
4215 to its default value.
4217 @param FormSet FormSet data structure.
4218 @param Form Form data structure.
4219 @param DefaultId The Class of the default.
4220 @param SettingScope Setting Scope for Default action.
4221 @param GetDefaultValueScope Get default value scope.
4222 @param Storage Get default value only for this storage.
4223 @param RetrieveValueFirst Whether call the retrieve call back to
4224 get the initial value before get default
4227 @retval EFI_SUCCESS The function completed successfully.
4228 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4233 IN FORM_BROWSER_FORMSET
*FormSet
,
4234 IN FORM_BROWSER_FORM
*Form
,
4235 IN UINT16 DefaultId
,
4236 IN BROWSER_SETTING_SCOPE SettingScope
,
4237 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4238 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4239 IN BOOLEAN RetrieveValueFirst
4243 LIST_ENTRY
*FormLink
;
4245 FORM_BROWSER_STATEMENT
*Question
;
4246 FORM_BROWSER_FORMSET
*LocalFormSet
;
4247 FORM_BROWSER_FORMSET
*OldFormSet
;
4249 Status
= EFI_SUCCESS
;
4252 // Check the supported setting level.
4254 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4255 return EFI_UNSUPPORTED
;
4258 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4259 return EFI_UNSUPPORTED
;
4262 if (SettingScope
== FormLevel
) {
4264 // Prepare the AltCfg String for form.
4266 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
);
4269 // Extract Form default
4271 Link
= GetFirstNode (&Form
->StatementListHead
);
4272 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4273 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4274 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4277 // If get default value only for this storage, check the storage first.
4279 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4284 // If get default value only for no storage question, just skip the question which has storage.
4286 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4291 // If Question is disabled, don't reset it to default
4293 if (Question
->Expression
!= NULL
) {
4294 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4299 if (RetrieveValueFirst
) {
4301 // Call the Retrieve call back to get the initial question value.
4303 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4307 // If not request to get the initial value or get initial value fail, then get default value.
4309 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4310 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4311 if (EFI_ERROR (Status
)) {
4317 // Synchronize Buffer storage's Edit buffer
4319 if ((Question
->Storage
!= NULL
) &&
4320 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4321 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4326 // Clean the AltCfg String.
4328 CleanAltCfgForForm(Form
);
4329 } else if (SettingScope
== FormSetLevel
) {
4331 // Prepare the AltCfg String for formset.
4333 ExtractAltCfgForFormSet (FormSet
, DefaultId
);
4335 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4336 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4337 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4338 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4339 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4343 // Clean the AltCfg String.
4345 CleanAltCfgForFormSet (FormSet
);
4346 } else if (SettingScope
== SystemLevel
) {
4348 // Preload all Hii formset.
4350 LoadAllHiiFormset();
4352 OldFormSet
= mSystemLevelFormSet
;
4355 // Set Default Value for each FormSet in the maintain list.
4357 Link
= GetFirstNode (&gBrowserFormSetList
);
4358 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4359 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4360 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4361 if (!ValidateFormSet(LocalFormSet
)) {
4365 mSystemLevelFormSet
= LocalFormSet
;
4367 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4370 mSystemLevelFormSet
= OldFormSet
;
4378 Validate whether this question's value has changed.
4380 @param FormSet FormSet data structure.
4381 @param Form Form data structure.
4382 @param Question Question to be initialized.
4383 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4385 @retval TRUE Question's value has changed.
4386 @retval FALSE Question's value has not changed
4390 IsQuestionValueChanged (
4391 IN FORM_BROWSER_FORMSET
*FormSet
,
4392 IN FORM_BROWSER_FORM
*Form
,
4393 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4394 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4397 EFI_HII_VALUE BackUpValue
;
4398 CHAR8
*BackUpBuffer
;
4399 EFI_HII_VALUE BackUpValue2
;
4400 CHAR8
*BackUpBuffer2
;
4402 BOOLEAN ValueChanged
;
4406 // For quetion without storage, always mark it as data not changed.
4408 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4412 BackUpBuffer
= NULL
;
4413 BackUpBuffer2
= NULL
;
4414 ValueChanged
= FALSE
;
4416 switch (Question
->Operand
) {
4417 case EFI_IFR_ORDERED_LIST_OP
:
4418 BufferWidth
= Question
->StorageWidth
;
4419 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4420 ASSERT (BackUpBuffer
!= NULL
);
4423 case EFI_IFR_STRING_OP
:
4424 case EFI_IFR_PASSWORD_OP
:
4425 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4426 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4427 ASSERT (BackUpBuffer
!= NULL
);
4434 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4436 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4437 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4438 ASSERT_EFI_ERROR(Status
);
4440 switch (Question
->Operand
) {
4441 case EFI_IFR_ORDERED_LIST_OP
:
4442 BufferWidth
= Question
->StorageWidth
;
4443 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4444 ASSERT (BackUpBuffer2
!= NULL
);
4447 case EFI_IFR_STRING_OP
:
4448 case EFI_IFR_PASSWORD_OP
:
4449 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4450 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4451 ASSERT (BackUpBuffer2
!= NULL
);
4458 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4460 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4461 ASSERT_EFI_ERROR(Status
);
4463 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4464 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4465 ValueChanged
= TRUE
;
4468 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4469 ASSERT_EFI_ERROR(Status
);
4471 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4472 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4473 ValueChanged
= TRUE
;
4477 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4478 if (BackUpBuffer
!= NULL
) {
4479 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4480 FreePool (BackUpBuffer
);
4483 if (BackUpBuffer2
!= NULL
) {
4484 FreePool (BackUpBuffer2
);
4487 Question
->ValueChanged
= ValueChanged
;
4489 return ValueChanged
;
4493 Initialize Question's Edit copy from Storage.
4495 @param Selection Selection contains the information about
4496 the Selection, form and formset to be displayed.
4497 Selection action may be updated in retrieve callback.
4498 If Selection is NULL, only initialize Question value.
4499 @param FormSet FormSet data structure.
4500 @param Form Form data structure.
4502 @retval EFI_SUCCESS The function completed successfully.
4507 IN OUT UI_MENU_SELECTION
*Selection
,
4508 IN FORM_BROWSER_FORMSET
*FormSet
,
4509 IN FORM_BROWSER_FORM
*Form
4514 FORM_BROWSER_STATEMENT
*Question
;
4516 Link
= GetFirstNode (&Form
->StatementListHead
);
4517 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4518 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4521 // Initialize local copy of Value for each Question
4523 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4524 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4526 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4528 if (EFI_ERROR (Status
)) {
4532 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4533 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4536 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4543 Initialize Question's Edit copy from Storage for the whole Formset.
4545 @param Selection Selection contains the information about
4546 the Selection, form and formset to be displayed.
4547 Selection action may be updated in retrieve callback.
4548 If Selection is NULL, only initialize Question value.
4549 @param FormSet FormSet data structure.
4551 @retval EFI_SUCCESS The function completed successfully.
4556 IN OUT UI_MENU_SELECTION
*Selection
,
4557 IN FORM_BROWSER_FORMSET
*FormSet
4562 FORM_BROWSER_FORM
*Form
;
4564 Link
= GetFirstNode (&FormSet
->FormListHead
);
4565 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4566 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4569 // Initialize local copy of Value for each Form
4571 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4572 if (EFI_ERROR (Status
)) {
4576 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4580 // Finished question initialization.
4582 FormSet
->QuestionInited
= TRUE
;
4588 Remove the Request element from the Config Request.
4590 @param Storage Pointer to the browser storage.
4591 @param RequestElement The pointer to the Request element.
4596 IN OUT BROWSER_STORAGE
*Storage
,
4597 IN CHAR16
*RequestElement
4603 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4605 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4607 if (NewStr
== NULL
) {
4612 // Remove this element from this ConfigRequest.
4615 NewStr
+= StrLen (RequestElement
);
4616 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4618 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4622 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4624 @param Storage Pointer to the browser storage.
4625 @param ConfigRequest The pointer to the Request element.
4629 RemoveConfigRequest (
4630 BROWSER_STORAGE
*Storage
,
4631 CHAR16
*ConfigRequest
4634 CHAR16
*RequestElement
;
4635 CHAR16
*NextRequestElement
;
4639 // No request element in it, just return.
4641 if (ConfigRequest
== NULL
) {
4645 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4647 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4652 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4654 SearchKey
= L
"&OFFSET";
4658 // Find SearchKey storage
4660 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4661 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4662 ASSERT (RequestElement
!= NULL
);
4663 RequestElement
= StrStr (RequestElement
, SearchKey
);
4665 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4668 while (RequestElement
!= NULL
) {
4670 // +1 to avoid find header itself.
4672 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4675 // The last Request element in configRequest string.
4677 if (NextRequestElement
!= NULL
) {
4679 // Replace "&" with '\0'.
4681 *NextRequestElement
= L
'\0';
4684 RemoveElement (Storage
, RequestElement
);
4686 if (NextRequestElement
!= NULL
) {
4688 // Restore '&' with '\0' for later used.
4690 *NextRequestElement
= L
'&';
4693 RequestElement
= NextRequestElement
;
4697 // If no request element remain, just remove the ConfigRequest string.
4699 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4700 FreePool (Storage
->ConfigRequest
);
4701 Storage
->ConfigRequest
= NULL
;
4702 Storage
->SpareStrLen
= 0;
4707 Base on the current formset info, clean the ConfigRequest string in browser storage.
4709 @param FormSet Pointer of the FormSet
4713 CleanBrowserStorage (
4714 IN OUT FORM_BROWSER_FORMSET
*FormSet
4718 FORMSET_STORAGE
*Storage
;
4720 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4721 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4722 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4723 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4725 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4726 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4730 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4731 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4732 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4733 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4734 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4735 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4737 Storage
->BrowserStorage
->Initialized
= FALSE
;
4743 Check whether current element in the ConfigReqeust string.
4745 @param BrowserStorage Storage which includes ConfigReqeust.
4746 @param RequestElement New element need to check.
4748 @retval TRUE The Element is in the ConfigReqeust string.
4749 @retval FALSE The Element not in the configReqeust String.
4754 BROWSER_STORAGE
*BrowserStorage
,
4755 CHAR16
*RequestElement
4758 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4762 Append the Request element to the Config Request.
4764 @param ConfigRequest Current ConfigRequest info.
4765 @param SpareStrLen Current remain free buffer for config reqeust.
4766 @param RequestElement New Request element.
4770 AppendConfigRequest (
4771 IN OUT CHAR16
**ConfigRequest
,
4772 IN OUT UINTN
*SpareStrLen
,
4773 IN CHAR16
*RequestElement
4780 StrLength
= StrLen (RequestElement
);
4783 // Append <RequestElement> to <ConfigRequest>
4785 if (StrLength
> *SpareStrLen
) {
4787 // Old String buffer is not sufficient for RequestElement, allocate a new one
4789 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4790 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4791 ASSERT (NewStr
!= NULL
);
4793 if (*ConfigRequest
!= NULL
) {
4794 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4795 FreePool (*ConfigRequest
);
4797 *ConfigRequest
= NewStr
;
4798 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4801 StrCat (*ConfigRequest
, RequestElement
);
4802 *SpareStrLen
-= StrLength
;
4806 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4808 @param Storage Form set Storage.
4809 @param Request The input request string.
4810 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4812 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4813 @retval FALSE All elements covered by current used elements.
4817 ConfigRequestAdjust (
4818 IN BROWSER_STORAGE
*Storage
,
4820 IN BOOLEAN RespString
4823 CHAR16
*RequestElement
;
4824 CHAR16
*NextRequestElement
;
4825 CHAR16
*NextElementBakup
;
4830 CHAR16
*ConfigRequest
;
4834 NextElementBakup
= NULL
;
4837 if (Request
!= NULL
) {
4838 ConfigRequest
= Request
;
4840 ConfigRequest
= Storage
->ConfigRequest
;
4843 if (Storage
->ConfigRequest
== NULL
) {
4844 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4848 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4850 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4855 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4857 SearchKey
= L
"&OFFSET";
4858 ValueKey
= L
"&VALUE";
4862 // Find SearchKey storage
4864 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4865 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4866 ASSERT (RequestElement
!= NULL
);
4867 RequestElement
= StrStr (RequestElement
, SearchKey
);
4869 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4872 while (RequestElement
!= NULL
) {
4875 // +1 to avoid find header itself.
4877 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4880 // The last Request element in configRequest string.
4882 if (NextRequestElement
!= NULL
) {
4883 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4884 NextElementBakup
= NextRequestElement
;
4885 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4886 ASSERT (NextRequestElement
!= NULL
);
4889 // Replace "&" with '\0'.
4891 *NextRequestElement
= L
'\0';
4893 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4894 NextElementBakup
= NextRequestElement
;
4895 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4896 ASSERT (NextRequestElement
!= NULL
);
4898 // Replace "&" with '\0'.
4900 *NextRequestElement
= L
'\0';
4904 if (!ElementValidation (Storage
, RequestElement
)) {
4906 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4908 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4912 if (NextRequestElement
!= NULL
) {
4914 // Restore '&' with '\0' for later used.
4916 *NextRequestElement
= L
'&';
4919 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4920 RequestElement
= NextElementBakup
;
4922 RequestElement
= NextRequestElement
;
4931 Base on ConfigRequest info to get default value for current formset.
4933 ConfigRequest info include the info about which questions in current formset need to
4934 get default value. This function only get these questions default value.
4936 @param FormSet FormSet data structure.
4937 @param Storage Storage need to update value.
4938 @param ConfigRequest The config request string.
4942 GetDefaultForFormset (
4943 IN FORM_BROWSER_FORMSET
*FormSet
,
4944 IN BROWSER_STORAGE
*Storage
,
4945 IN CHAR16
*ConfigRequest
4950 LIST_ENTRY BackUpList
;
4951 NAME_VALUE_NODE
*Node
;
4953 LIST_ENTRY
*NodeLink
;
4954 NAME_VALUE_NODE
*TmpNode
;
4956 EFI_STRING Progress
;
4960 InitializeListHead(&BackUpList
);
4963 // Back update the edit buffer.
4965 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4966 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4967 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4968 ASSERT (BackUpBuf
!= NULL
);
4969 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4970 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4971 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4972 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4973 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4976 // Only back Node belong to this formset.
4978 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4982 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4983 ASSERT (TmpNode
!= NULL
);
4984 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4985 ASSERT (TmpNode
->Name
!= NULL
);
4986 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4987 ASSERT (TmpNode
->EditValue
!= NULL
);
4989 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4994 // Get default value.
4996 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4999 // Update the question value based on the input ConfigRequest.
5001 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5002 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5003 ASSERT (BackUpBuf
!= NULL
);
5004 BufferSize
= Storage
->Size
;
5005 Status
= mHiiConfigRouting
->BlockToConfig(
5008 Storage
->EditBuffer
,
5013 ASSERT_EFI_ERROR (Status
);
5015 Status
= mHiiConfigRouting
->ConfigToBlock (
5022 ASSERT_EFI_ERROR (Status
);
5024 if (Result
!= NULL
) {
5028 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
5029 FreePool (BackUpBuf
);
5030 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5032 // Update question value, only element in ConfigReqeust will be update.
5034 Link
= GetFirstNode (&BackUpList
);
5035 while (!IsNull (&BackUpList
, Link
)) {
5036 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
5037 Link
= GetNextNode (&BackUpList
, Link
);
5039 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
5043 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
5044 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
5045 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
5046 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
5048 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
5052 FreePool (TmpNode
->EditValue
);
5053 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
5055 RemoveEntryList (&Node
->Link
);
5056 FreePool (Node
->EditValue
);
5057 FreePool (Node
->Name
);
5063 // Restore the Name/Value node.
5065 Link
= GetFirstNode (&BackUpList
);
5066 while (!IsNull (&BackUpList
, Link
)) {
5067 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
5068 Link
= GetNextNode (&BackUpList
, Link
);
5073 RemoveEntryList (&Node
->Link
);
5074 FreePool (Node
->EditValue
);
5075 FreePool (Node
->Name
);
5082 Fill storage's edit copy with settings requested from Configuration Driver.
5084 @param FormSet FormSet data structure.
5085 @param Storage Buffer Storage.
5090 IN FORM_BROWSER_FORMSET
*FormSet
,
5091 IN FORMSET_STORAGE
*Storage
5095 EFI_STRING Progress
;
5098 EFI_STRING ConfigRequest
;
5101 ConfigRequest
= NULL
;
5103 switch (Storage
->BrowserStorage
->Type
) {
5104 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5107 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5108 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5109 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5114 case EFI_HII_VARSTORE_BUFFER
:
5115 case EFI_HII_VARSTORE_NAME_VALUE
:
5117 // Skip if there is no RequestElement.
5119 if (Storage
->ElementCount
== 0) {
5124 // Just update the ConfigRequest, if storage already initialized.
5126 if (Storage
->BrowserStorage
->Initialized
) {
5127 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5131 Storage
->BrowserStorage
->Initialized
= TRUE
;
5138 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5140 // Create the config request string to get all fields for this storage.
5141 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5142 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5144 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5145 ConfigRequest
= AllocateZeroPool (StrLen
);
5146 ASSERT (ConfigRequest
!= NULL
);
5150 L
"%s&OFFSET=0&WIDTH=%04x",
5151 Storage
->BrowserStorage
->ConfigHdr
,
5152 Storage
->BrowserStorage
->Size
);
5154 ConfigRequest
= Storage
->ConfigRequest
;
5158 // Request current settings from Configuration Driver
5160 Status
= mHiiConfigRouting
->ExtractConfig (
5168 // If get value fail, extract default from IFR binary
5170 if (EFI_ERROR (Status
)) {
5171 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
5174 // Convert Result from <ConfigAltResp> to <ConfigResp>
5176 StrPtr
= StrStr (Result
, L
"&GUID=");
5177 if (StrPtr
!= NULL
) {
5181 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5185 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5188 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5190 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5192 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5193 if (ConfigRequest
!= NULL
) {
5194 FreePool (ConfigRequest
);
5200 Get Value changed status from old question.
5202 @param NewFormSet FormSet data structure.
5203 @param OldQuestion Old question which has value changed.
5207 SyncStatusForQuestion (
5208 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5209 IN FORM_BROWSER_STATEMENT
*OldQuestion
5213 LIST_ENTRY
*QuestionLink
;
5214 FORM_BROWSER_FORM
*Form
;
5215 FORM_BROWSER_STATEMENT
*Question
;
5218 // For each form in one formset.
5220 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5221 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5222 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5223 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5226 // for each question in one form.
5228 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5229 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5230 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5231 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5233 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5234 Question
->ValueChanged
= TRUE
;
5242 Get Value changed status from old formset.
5244 @param NewFormSet FormSet data structure.
5245 @param OldFormSet FormSet data structure.
5249 SyncStatusForFormSet (
5250 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5251 IN FORM_BROWSER_FORMSET
*OldFormSet
5255 LIST_ENTRY
*QuestionLink
;
5256 FORM_BROWSER_FORM
*Form
;
5257 FORM_BROWSER_STATEMENT
*Question
;
5260 // For each form in one formset.
5262 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5263 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5264 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5265 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5268 // for each question in one form.
5270 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5271 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5272 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5273 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5275 if (!Question
->ValueChanged
) {
5280 // Find the same question in new formset and update the value changed flag.
5282 SyncStatusForQuestion (NewFormSet
, Question
);
5288 Get current setting of Questions.
5290 @param FormSet FormSet data structure.
5294 InitializeCurrentSetting (
5295 IN OUT FORM_BROWSER_FORMSET
*FormSet
5299 FORMSET_STORAGE
*Storage
;
5300 FORM_BROWSER_FORMSET
*OldFormSet
;
5303 // Try to find pre FormSet in the maintain backup list.
5304 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5306 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5307 if (OldFormSet
!= NULL
) {
5308 SyncStatusForFormSet (FormSet
, OldFormSet
);
5309 RemoveEntryList (&OldFormSet
->Link
);
5310 DestroyFormSet (OldFormSet
);
5312 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5315 // Extract default from IFR binary for no storage questions.
5317 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
5320 // Request current settings from Configuration Driver
5322 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5323 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5324 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5326 LoadStorage (FormSet
, Storage
);
5328 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5334 Fetch the Ifr binary data of a FormSet.
5336 @param Handle PackageList Handle
5337 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5338 specified (NULL or zero GUID), take the first
5339 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5340 found in package list.
5341 On output, GUID of the formset found(if not NULL).
5342 @param BinaryLength The length of the FormSet IFR binary.
5343 @param BinaryData The buffer designed to receive the FormSet.
5345 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5346 BufferLength was updated.
5347 @retval EFI_INVALID_PARAMETER The handle is unknown.
5348 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5349 be found with the requested FormId.
5354 IN EFI_HII_HANDLE Handle
,
5355 IN OUT EFI_GUID
*FormSetGuid
,
5356 OUT UINTN
*BinaryLength
,
5357 OUT UINT8
**BinaryData
5361 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5367 UINT32 PackageListLength
;
5368 EFI_HII_PACKAGE_HEADER PackageHeader
;
5370 UINT8 NumberOfClassGuid
;
5371 BOOLEAN ClassGuidMatch
;
5372 EFI_GUID
*ClassGuid
;
5373 EFI_GUID
*ComparingGuid
;
5377 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5380 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5382 if (FormSetGuid
== NULL
) {
5383 ComparingGuid
= &gZeroGuid
;
5385 ComparingGuid
= FormSetGuid
;
5389 // Get HII PackageList
5392 HiiPackageList
= NULL
;
5393 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5394 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5395 HiiPackageList
= AllocatePool (BufferSize
);
5396 ASSERT (HiiPackageList
!= NULL
);
5398 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5400 if (EFI_ERROR (Status
)) {
5403 ASSERT (HiiPackageList
!= NULL
);
5406 // Get Form package from this HII package List
5408 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5410 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5412 ClassGuidMatch
= FALSE
;
5413 while (Offset
< PackageListLength
) {
5414 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5415 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5417 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5419 // Search FormSet in this Form Package
5421 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5422 while (Offset2
< PackageHeader
.Length
) {
5423 OpCodeData
= Package
+ Offset2
;
5425 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5427 // Try to compare against formset GUID
5429 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5430 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5434 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5436 // Try to compare against formset class GUID
5438 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5439 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5440 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5441 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5442 ClassGuidMatch
= TRUE
;
5446 if (ClassGuidMatch
) {
5449 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5450 ClassGuidMatch
= TRUE
;
5455 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5458 if (Offset2
< PackageHeader
.Length
) {
5460 // Target formset found
5466 Offset
+= PackageHeader
.Length
;
5469 if (Offset
>= PackageListLength
) {
5471 // Form package not found in this Package List
5473 FreePool (HiiPackageList
);
5474 return EFI_NOT_FOUND
;
5477 if (FormSetGuid
!= NULL
) {
5479 // Return the FormSet GUID
5481 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5485 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5486 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5487 // of the Form Package.
5489 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5490 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5492 FreePool (HiiPackageList
);
5494 if (*BinaryData
== NULL
) {
5495 return EFI_OUT_OF_RESOURCES
;
5503 Initialize the internal data structure of a FormSet.
5505 @param Handle PackageList Handle
5506 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5507 specified (NULL or zero GUID), take the first
5508 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5509 found in package list.
5510 On output, GUID of the formset found(if not NULL).
5511 @param FormSet FormSet data structure.
5513 @retval EFI_SUCCESS The function completed successfully.
5514 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5519 IN EFI_HII_HANDLE Handle
,
5520 IN OUT EFI_GUID
*FormSetGuid
,
5521 OUT FORM_BROWSER_FORMSET
*FormSet
5525 EFI_HANDLE DriverHandle
;
5527 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5528 if (EFI_ERROR (Status
)) {
5532 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5533 FormSet
->HiiHandle
= Handle
;
5534 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5535 FormSet
->QuestionInited
= FALSE
;
5538 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5540 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5541 if (EFI_ERROR (Status
)) {
5544 FormSet
->DriverHandle
= DriverHandle
;
5545 Status
= gBS
->HandleProtocol (
5547 &gEfiHiiConfigAccessProtocolGuid
,
5548 (VOID
**) &FormSet
->ConfigAccess
5550 if (EFI_ERROR (Status
)) {
5552 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5553 // list, then there will be no configuration action required
5555 FormSet
->ConfigAccess
= NULL
;
5559 // Parse the IFR binary OpCodes
5561 Status
= ParseOpCodes (FormSet
);
5568 Save globals used by previous call to SendForm(). SendForm() may be called from
5569 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5570 So, save globals of previous call to SendForm() and restore them upon exit.
5574 SaveBrowserContext (
5578 BROWSER_CONTEXT
*Context
;
5579 FORM_ENTRY_INFO
*MenuList
;
5581 gBrowserContextCount
++;
5582 if (gBrowserContextCount
== 1) {
5584 // This is not reentry of SendForm(), no context to save
5589 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5590 ASSERT (Context
!= NULL
);
5592 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5595 // Save FormBrowser context
5597 Context
->Selection
= gCurrentSelection
;
5598 Context
->ResetRequired
= gResetRequired
;
5599 Context
->ExitRequired
= gExitRequired
;
5600 Context
->HiiHandle
= mCurrentHiiHandle
;
5601 Context
->FormId
= mCurrentFormId
;
5602 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5605 // Save the menu history data.
5607 InitializeListHead(&Context
->FormHistoryList
);
5608 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5609 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5610 RemoveEntryList (&MenuList
->Link
);
5612 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5616 // Insert to FormBrowser context list
5618 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5623 Restore globals used by previous call to SendForm().
5627 RestoreBrowserContext (
5632 BROWSER_CONTEXT
*Context
;
5633 FORM_ENTRY_INFO
*MenuList
;
5635 ASSERT (gBrowserContextCount
!= 0);
5636 gBrowserContextCount
--;
5637 if (gBrowserContextCount
== 0) {
5639 // This is not reentry of SendForm(), no context to restore
5644 ASSERT (!IsListEmpty (&gBrowserContextList
));
5646 Link
= GetFirstNode (&gBrowserContextList
);
5647 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5650 // Restore FormBrowser context
5652 gCurrentSelection
= Context
->Selection
;
5653 gResetRequired
= Context
->ResetRequired
;
5654 gExitRequired
= Context
->ExitRequired
;
5655 mCurrentHiiHandle
= Context
->HiiHandle
;
5656 mCurrentFormId
= Context
->FormId
;
5657 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5660 // Restore the menu history data.
5662 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5663 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5664 RemoveEntryList (&MenuList
->Link
);
5666 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5670 // Remove from FormBrowser context list
5672 RemoveEntryList (&Context
->Link
);
5673 gBS
->FreePool (Context
);
5677 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5679 @param Handle The Hii Handle.
5681 @return the found FormSet context. If no found, NULL will return.
5684 FORM_BROWSER_FORMSET
*
5685 GetFormSetFromHiiHandle (
5686 EFI_HII_HANDLE Handle
5690 FORM_BROWSER_FORMSET
*FormSet
;
5692 Link
= GetFirstNode (&gBrowserFormSetList
);
5693 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5694 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5695 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5696 if (!ValidateFormSet(FormSet
)) {
5699 if (FormSet
->HiiHandle
== Handle
) {
5708 Check whether the input HII handle is the FormSet that is being used.
5710 @param Handle The Hii Handle.
5712 @retval TRUE HII handle is being used.
5713 @retval FALSE HII handle is not being used.
5717 IsHiiHandleInBrowserContext (
5718 EFI_HII_HANDLE Handle
5722 BROWSER_CONTEXT
*Context
;
5725 // HiiHandle is Current FormSet.
5727 if (mCurrentHiiHandle
== Handle
) {
5732 // Check whether HiiHandle is in BrowserContext.
5734 Link
= GetFirstNode (&gBrowserContextList
);
5735 while (!IsNull (&gBrowserContextList
, Link
)) {
5736 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5737 if (Context
->HiiHandle
== Handle
) {
5739 // HiiHandle is in BrowserContext
5743 Link
= GetNextNode (&gBrowserContextList
, Link
);
5750 Perform Password check.
5751 Passwork may be encrypted by driver that requires the specific check.
5753 @param Form Form where Password Statement is in.
5754 @param Statement Password statement
5755 @param PasswordString Password string to be checked. It may be NULL.
5756 NULL means to restore password.
5757 "" string can be used to checked whether old password does exist.
5759 @return Status Status of Password check.
5764 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5765 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5766 IN EFI_STRING PasswordString OPTIONAL
5770 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5771 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5772 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5773 FORM_BROWSER_STATEMENT
*Question
;
5775 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5776 Question
= GetBrowserStatement(Statement
);
5777 ASSERT (Question
!= NULL
);
5779 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5780 if (ConfigAccess
== NULL
) {
5781 return EFI_UNSUPPORTED
;
5784 if (PasswordString
== NULL
) {
5789 // Check whether has preexisted password.
5791 if (PasswordString
[0] == 0) {
5792 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5795 return EFI_NOT_READY
;
5800 // Check whether the input password is same as preexisted password.
5802 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5805 return EFI_NOT_READY
;
5810 // Prepare password string in HII database
5812 if (PasswordString
!= NULL
) {
5813 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5815 IfrTypeValue
.string
= 0;
5819 // Send password to Configuration Driver for validation
5821 Status
= ConfigAccess
->Callback (
5823 EFI_BROWSER_ACTION_CHANGING
,
5824 Question
->QuestionId
,
5825 Question
->HiiValue
.Type
,
5831 // Remove password string from HII database
5833 if (PasswordString
!= NULL
) {
5834 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5841 Find the registered HotKey based on KeyData.
5843 @param[in] KeyData A pointer to a buffer that describes the keystroke
5844 information for the hot key.
5846 @return The registered HotKey context. If no found, NULL will return.
5849 GetHotKeyFromRegisterList (
5850 IN EFI_INPUT_KEY
*KeyData
5854 BROWSER_HOT_KEY
*HotKey
;
5856 Link
= GetFirstNode (&gBrowserHotKeyList
);
5857 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5858 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5859 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5862 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5869 Configure what scope the hot key will impact.
5870 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5871 If no scope is set, the default scope will be FormSet level.
5872 After all registered hot keys are removed, previous Scope can reset to another level.
5874 @param[in] Scope Scope level to be set.
5876 @retval EFI_SUCCESS Scope is set correctly.
5877 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5878 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5884 IN BROWSER_SETTING_SCOPE Scope
5887 if (Scope
>= MaxLevel
) {
5888 return EFI_INVALID_PARAMETER
;
5892 // When no hot key registered in system or on the first setting,
5893 // Scope can be set.
5895 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5896 gBrowserSettingScope
= Scope
;
5897 mBrowserScopeFirstSet
= FALSE
;
5898 } else if (Scope
!= gBrowserSettingScope
) {
5899 return EFI_UNSUPPORTED
;
5906 Register the hot key with its browser action, or unregistered the hot key.
5907 Only support hot key that is not printable character (control key, function key, etc.).
5908 If the action value is zero, the hot key will be unregistered if it has been registered.
5909 If the same hot key has been registered, the new action and help string will override the previous ones.
5911 @param[in] KeyData A pointer to a buffer that describes the keystroke
5912 information for the hot key. Its type is EFI_INPUT_KEY to
5913 be supported by all ConsoleIn devices.
5914 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5915 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5916 @param[in] HelpString Help string that describes the hot key information.
5917 Its value may be NULL for the unregistered hot key.
5919 @retval EFI_SUCCESS Hot key is registered or unregistered.
5920 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5921 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5922 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5927 IN EFI_INPUT_KEY
*KeyData
,
5929 IN UINT16 DefaultId
,
5930 IN EFI_STRING HelpString OPTIONAL
5933 BROWSER_HOT_KEY
*HotKey
;
5936 // Check input parameters.
5938 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5939 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5940 return EFI_INVALID_PARAMETER
;
5944 // Check whether the input KeyData is in BrowserHotKeyList.
5946 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5949 // Unregister HotKey
5951 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5952 if (HotKey
!= NULL
) {
5954 // The registered HotKey is found.
5955 // Remove it from List, and free its resource.
5957 RemoveEntryList (&HotKey
->Link
);
5958 FreePool (HotKey
->KeyData
);
5959 FreePool (HotKey
->HelpString
);
5963 // The registered HotKey is not found.
5965 return EFI_NOT_FOUND
;
5970 // Register HotKey into List.
5972 if (HotKey
== NULL
) {
5974 // Create new Key, and add it into List.
5976 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5977 ASSERT (HotKey
!= NULL
);
5978 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5979 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5980 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5984 // Fill HotKey information.
5986 HotKey
->Action
= Action
;
5987 HotKey
->DefaultId
= DefaultId
;
5988 if (HotKey
->HelpString
!= NULL
) {
5989 FreePool (HotKey
->HelpString
);
5991 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5997 Register Exit handler function.
5998 When more than one handler function is registered, the latter one will override the previous one.
5999 When NULL handler is specified, the previous Exit handler will be unregistered.
6001 @param[in] Handler Pointer to handler function.
6006 RegiserExitHandler (
6007 IN EXIT_HANDLER Handler
6010 ExitHandlerFunction
= Handler
;
6015 Check whether the browser data has been modified.
6017 @retval TRUE Browser data is modified.
6018 @retval FALSE No browser data is modified.
6023 IsBrowserDataModified (
6028 FORM_BROWSER_FORMSET
*FormSet
;
6030 switch (gBrowserSettingScope
) {
6032 if (gCurrentSelection
== NULL
) {
6035 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6038 if (gCurrentSelection
== NULL
) {
6041 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6044 Link
= GetFirstNode (&gBrowserFormSetList
);
6045 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6046 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6047 if (!ValidateFormSet(FormSet
)) {
6051 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6054 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6064 Execute the action requested by the Action parameter.
6066 @param[in] Action Execute the request action.
6067 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6069 @retval EFI_SUCCESS Execute the request action succss.
6070 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6081 FORM_BROWSER_FORMSET
*FormSet
;
6082 FORM_BROWSER_FORM
*Form
;
6084 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6085 return EFI_NOT_READY
;
6088 Status
= EFI_SUCCESS
;
6091 if (gBrowserSettingScope
< SystemLevel
) {
6092 FormSet
= gCurrentSelection
->FormSet
;
6093 Form
= gCurrentSelection
->Form
;
6097 // Executet the discard action.
6099 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6100 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6101 if (EFI_ERROR (Status
)) {
6107 // Executet the difault action.
6109 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6110 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
6111 if (EFI_ERROR (Status
)) {
6114 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6118 // Executet the submit action.
6120 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6121 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6122 if (EFI_ERROR (Status
)) {
6128 // Executet the reset action.
6130 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6131 gResetRequired
= TRUE
;
6135 // Executet the exit action.
6137 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6138 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6139 if (gBrowserSettingScope
== SystemLevel
) {
6140 if (ExitHandlerFunction
!= NULL
) {
6141 ExitHandlerFunction ();
6145 gExitRequired
= TRUE
;
6152 Create reminder to let user to choose save or discard the changed browser data.
6153 Caller can use it to actively check the changed browser data.
6155 @retval BROWSER_NO_CHANGES No browser data is changed.
6156 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6157 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6158 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6168 FORM_BROWSER_FORMSET
*FormSet
;
6169 BOOLEAN IsDataChanged
;
6170 UINT32 DataSavedAction
;
6173 DataSavedAction
= BROWSER_NO_CHANGES
;
6174 IsDataChanged
= FALSE
;
6175 Link
= GetFirstNode (&gBrowserFormSetList
);
6176 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6177 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6178 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6179 if (!ValidateFormSet(FormSet
)) {
6182 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6183 IsDataChanged
= TRUE
;
6189 // No data is changed. No save is required.
6191 if (!IsDataChanged
) {
6192 return DataSavedAction
;
6196 // If data is changed, prompt user to save or discard it.
6199 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6201 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6202 SubmitForm (NULL
, NULL
, SystemLevel
);
6203 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6205 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6206 DiscardForm (NULL
, NULL
, SystemLevel
);
6207 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6209 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6210 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6215 return DataSavedAction
;
6219 Check whether the Reset Required for the browser
6221 @retval TRUE Browser required to reset after exit.
6222 @retval FALSE Browser not need to reset after exit.
6231 return gResetRequired
;