2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2016, 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 BOOLEAN gFlagReconnect
;
59 BOOLEAN gCallbackReconnect
;
60 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
61 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
62 EXIT_HANDLER ExitHandlerFunction
= NULL
;
63 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
66 // Browser Global Strings
69 CHAR16
*mUnknownString
= L
"!";
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
;
489 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
491 if (mFormDisplay
== NULL
) {
492 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
493 return EFI_UNSUPPORTED
;
497 // Save globals used by SendForm()
499 SaveBrowserContext ();
501 gFlagReconnect
= FALSE
;
502 gResetRequired
= FALSE
;
503 gExitRequired
= FALSE
;
504 gCallbackReconnect
= FALSE
;
505 Status
= EFI_SUCCESS
;
507 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
509 for (Index
= 0; Index
< HandleCount
; Index
++) {
510 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
511 ASSERT (Selection
!= NULL
);
513 Selection
->Handle
= Handles
[Index
];
514 if (FormSetGuid
!= NULL
) {
515 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
516 Selection
->FormId
= FormId
;
518 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
522 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
523 ASSERT (FormSet
!= NULL
);
526 // Validate the HiiHandle
527 // if validate failed, find the first validate parent HiiHandle.
529 if (!ValidateHiiHandle(Selection
->Handle
)) {
530 FindNextMenu (Selection
, FormSetLevel
);
534 // Initialize internal data structures of FormSet
536 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
537 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
538 DestroyFormSet (FormSet
);
541 Selection
->FormSet
= FormSet
;
542 mSystemLevelFormSet
= FormSet
;
545 // Display this formset
547 gCurrentSelection
= Selection
;
549 Status
= SetupBrowser (Selection
);
551 gCurrentSelection
= NULL
;
552 mSystemLevelFormSet
= NULL
;
554 if (gFlagReconnect
|| gCallbackReconnect
) {
555 RetVal
= ReconnectController (FormSet
->DriverHandle
);
557 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
559 gFlagReconnect
= FALSE
;
560 gCallbackReconnect
= FALSE
;
564 // If no data is changed, don't need to save current FormSet into the maintain list.
566 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
567 CleanBrowserStorage(FormSet
);
568 RemoveEntryList (&FormSet
->Link
);
569 DestroyFormSet (FormSet
);
572 if (EFI_ERROR (Status
)) {
575 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
577 FreePool (Selection
);
580 if (ActionRequest
!= NULL
) {
581 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
582 if (gResetRequired
) {
583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
587 mFormDisplay
->ExitDisplay();
590 // Clear the menu history data.
592 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
593 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
594 RemoveEntryList (&MenuList
->Link
);
599 // Restore globals used by SendForm()
601 RestoreBrowserContext ();
607 Get or set data to the storage.
609 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
610 @param ResultsData A string returned from an IFR browser or
611 equivalent. The results string will have no
612 routing information in them.
613 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
614 (if RetrieveData = TRUE) data from the uncommitted
615 browser state information or set (if RetrieveData
616 = FALSE) data in the uncommitted browser state
618 @param Storage The pointer to the storage.
620 @retval EFI_SUCCESS The results have been distributed or are awaiting
626 IN OUT UINTN
*ResultsDataSize
,
627 IN OUT EFI_STRING
*ResultsData
,
628 IN BOOLEAN RetrieveData
,
629 IN BROWSER_STORAGE
*Storage
638 FORMSET_STORAGE
*BrowserStorage
;
642 // Generate <ConfigResp>
644 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
645 if (EFI_ERROR (Status
)) {
650 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
651 // Also need to consider add "\0" at first time.
653 StrPtr
= StrStr (ConfigResp
, L
"PATH");
654 ASSERT (StrPtr
!= NULL
);
655 StrPtr
= StrStr (StrPtr
, L
"&");
657 BufferSize
= StrSize (StrPtr
);
660 // Copy the data if the input buffer is bigger enough.
662 if (*ResultsDataSize
>= BufferSize
) {
663 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
666 *ResultsDataSize
= BufferSize
;
667 FreePool (ConfigResp
);
670 // Prepare <ConfigResp>
672 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
673 ASSERT (BrowserStorage
!= NULL
);
674 TmpSize
= StrLen (*ResultsData
);
675 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
676 MaxLen
= BufferSize
/ sizeof (CHAR16
);
677 ConfigResp
= AllocateZeroPool (BufferSize
);
678 ASSERT (ConfigResp
!= NULL
);
680 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
681 StrCatS (ConfigResp
, MaxLen
, L
"&");
682 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
685 // Update Browser uncommited data
687 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
688 FreePool (ConfigResp
);
689 if (EFI_ERROR (Status
)) {
698 This routine called this service in the browser to retrieve or set certain uncommitted
699 state information that resides in the open formsets.
701 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
703 @param ResultsDataSize A pointer to the size of the buffer associated
705 @param ResultsData A string returned from an IFR browser or
706 equivalent. The results string will have no
707 routing information in them.
708 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
709 (if RetrieveData = TRUE) data from the uncommitted
710 browser state information or set (if RetrieveData
711 = FALSE) data in the uncommitted browser state
713 @param VariableGuid An optional field to indicate the target variable
715 @param VariableName An optional field to indicate the target
716 human-readable variable name.
718 @retval EFI_SUCCESS The results have been distributed or are awaiting
720 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
721 contain the results data.
727 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
728 IN OUT UINTN
*ResultsDataSize
,
729 IN OUT EFI_STRING ResultsData
,
730 IN BOOLEAN RetrieveData
,
731 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
732 IN CONST CHAR16
*VariableName OPTIONAL
737 BROWSER_STORAGE
*Storage
;
738 FORMSET_STORAGE
*FormsetStorage
;
742 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
743 return EFI_INVALID_PARAMETER
;
746 TotalSize
= *ResultsDataSize
;
749 Status
= EFI_SUCCESS
;
751 if (VariableGuid
!= NULL
) {
753 // Try to find target storage in the current formset.
755 Link
= GetFirstNode (&gBrowserStorageList
);
756 while (!IsNull (&gBrowserStorageList
, Link
)) {
757 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
758 Link
= GetNextNode (&gBrowserStorageList
, Link
);
760 // Check the current storage.
762 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
766 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
767 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
769 // Buffer storage require both GUID and Name
771 if (VariableName
== NULL
) {
772 return EFI_NOT_FOUND
;
775 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
780 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
781 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
782 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
783 return EFI_NOT_FOUND
;
786 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
791 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
792 if (EFI_ERROR (Status
)) {
796 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
797 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
801 // Different formsets may have same varstore, so here just set the flag
802 // not exit the circle.
809 return EFI_NOT_FOUND
;
813 // GUID/Name is not specified, take the first storage in FormSet
815 if (mSystemLevelFormSet
== NULL
) {
816 return EFI_NOT_READY
;
820 // Generate <ConfigResp>
822 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
823 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
824 return EFI_UNSUPPORTED
;
827 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
829 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
830 if (EFI_ERROR (Status
)) {
836 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
837 *ResultsDataSize
= TotalSize
;
846 Callback function for SimpleTextInEx protocol install events
848 @param Event the event that is signaled.
849 @param Context not used here.
854 FormDisplayCallback (
859 if (mFormDisplay
!= NULL
) {
863 gBS
->LocateProtocol (
864 &gEdkiiFormDisplayEngineProtocolGuid
,
866 (VOID
**) &mFormDisplay
871 Initialize Setup Browser driver.
873 @param ImageHandle The image handle.
874 @param SystemTable The system table.
876 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
877 @return Other value if failed to initialize the Setup Browser module.
883 IN EFI_HANDLE ImageHandle
,
884 IN EFI_SYSTEM_TABLE
*SystemTable
891 // Locate required Hii relative protocols
893 Status
= gBS
->LocateProtocol (
894 &gEfiHiiDatabaseProtocolGuid
,
896 (VOID
**) &mHiiDatabase
898 ASSERT_EFI_ERROR (Status
);
900 Status
= gBS
->LocateProtocol (
901 &gEfiHiiConfigRoutingProtocolGuid
,
903 (VOID
**) &mHiiConfigRouting
905 ASSERT_EFI_ERROR (Status
);
907 Status
= gBS
->LocateProtocol (
908 &gEfiDevicePathFromTextProtocolGuid
,
910 (VOID
**) &mPathFromText
914 // Install FormBrowser2 protocol
916 mPrivateData
.Handle
= NULL
;
917 Status
= gBS
->InstallProtocolInterface (
918 &mPrivateData
.Handle
,
919 &gEfiFormBrowser2ProtocolGuid
,
920 EFI_NATIVE_INTERFACE
,
921 &mPrivateData
.FormBrowser2
923 ASSERT_EFI_ERROR (Status
);
926 // Install FormBrowserEx2 protocol
928 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
929 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
930 mPrivateData
.Handle
= NULL
;
931 Status
= gBS
->InstallProtocolInterface (
932 &mPrivateData
.Handle
,
933 &gEdkiiFormBrowserEx2ProtocolGuid
,
934 EFI_NATIVE_INTERFACE
,
935 &mPrivateData
.FormBrowserEx2
937 ASSERT_EFI_ERROR (Status
);
939 Status
= gBS
->InstallProtocolInterface (
940 &mPrivateData
.Handle
,
941 &gEfiFormBrowserExProtocolGuid
,
942 EFI_NATIVE_INTERFACE
,
943 &mPrivateData
.FormBrowserEx
945 ASSERT_EFI_ERROR (Status
);
947 InitializeDisplayFormData ();
949 Status
= gBS
->LocateProtocol (
950 &gEdkiiFormDisplayEngineProtocolGuid
,
952 (VOID
**) &mFormDisplay
955 if (EFI_ERROR (Status
)) {
956 EfiCreateProtocolNotifyEvent (
957 &gEdkiiFormDisplayEngineProtocolGuid
,
970 Create a new string in HII Package List.
972 @param String The String to be added
973 @param HiiHandle The package list in the HII database to insert the
976 @return The output string.
982 IN EFI_HII_HANDLE HiiHandle
985 EFI_STRING_ID StringId
;
987 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
988 ASSERT (StringId
!= 0);
995 Delete a string from HII Package List.
997 @param StringId Id of the string in HII database.
998 @param HiiHandle The HII package list handle.
1000 @retval EFI_SUCCESS The string was deleted successfully.
1005 IN EFI_STRING_ID StringId
,
1006 IN EFI_HII_HANDLE HiiHandle
1011 NullChar
= CHAR_NULL
;
1012 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1018 Get the string based on the StringId and HII Package List Handle.
1020 @param Token The String's ID.
1021 @param HiiHandle The package list in the HII database to search for
1022 the specified string.
1024 @return The output string.
1029 IN EFI_STRING_ID Token
,
1030 IN EFI_HII_HANDLE HiiHandle
1035 if (HiiHandle
== NULL
) {
1039 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1040 if (String
== NULL
) {
1041 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1042 ASSERT (String
!= NULL
);
1044 return (CHAR16
*) String
;
1049 Allocate new memory and then copy the Unicode string Source to Destination.
1051 @param Dest Location to copy string
1052 @param Src String to copy
1057 IN OUT CHAR16
**Dest
,
1061 if (*Dest
!= NULL
) {
1064 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1065 ASSERT (*Dest
!= NULL
);
1070 Allocate new memory and concatinate Source on the end of Destination.
1072 @param Dest String to added to the end of.
1073 @param Src String to concatinate.
1078 IN OUT CHAR16
**Dest
,
1085 if (*Dest
== NULL
) {
1086 NewStringCpy (Dest
, Src
);
1090 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1091 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1092 ASSERT (NewString
!= NULL
);
1094 StrCpyS (NewString
, MaxLen
, *Dest
);
1095 StrCatS (NewString
, MaxLen
, Src
);
1102 Get Value for given Name from a NameValue Storage.
1104 @param Storage The NameValue Storage.
1105 @param Name The Name.
1106 @param Value The retured Value.
1107 @param GetValueFrom Where to get source value, from EditValue or Value.
1109 @retval EFI_SUCCESS Value found for given Name.
1110 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1115 IN BROWSER_STORAGE
*Storage
,
1117 IN OUT CHAR16
**Value
,
1118 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1122 NAME_VALUE_NODE
*Node
;
1124 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1125 return EFI_INVALID_PARAMETER
;
1130 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1131 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1132 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1134 if (StrCmp (Name
, Node
->Name
) == 0) {
1135 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1136 NewStringCpy (Value
, Node
->EditValue
);
1138 NewStringCpy (Value
, Node
->Value
);
1143 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1146 return EFI_NOT_FOUND
;
1151 Set Value of given Name in a NameValue Storage.
1153 @param Storage The NameValue Storage.
1154 @param Name The Name.
1155 @param Value The Value to set.
1156 @param SetValueTo Whether update editValue or Value.
1157 @param ReturnNode The node use the input name.
1159 @retval EFI_SUCCESS Value found for given Name.
1160 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1165 IN BROWSER_STORAGE
*Storage
,
1168 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1169 OUT NAME_VALUE_NODE
**ReturnNode
1173 NAME_VALUE_NODE
*Node
;
1176 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1177 return EFI_INVALID_PARAMETER
;
1180 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1181 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1182 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1184 if (StrCmp (Name
, Node
->Name
) == 0) {
1185 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1186 Buffer
= Node
->EditValue
;
1188 Buffer
= Node
->Value
;
1190 if (Buffer
!= NULL
) {
1193 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1194 ASSERT (Buffer
!= NULL
);
1195 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1196 Node
->EditValue
= Buffer
;
1198 Node
->Value
= Buffer
;
1201 if (ReturnNode
!= NULL
) {
1208 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1211 return EFI_NOT_FOUND
;
1216 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1218 @param Storage The Storage to be conveted.
1219 @param ConfigResp The returned <ConfigResp>.
1220 @param ConfigRequest The ConfigRequest string.
1221 @param GetEditBuf Get the data from editbuffer or buffer.
1223 @retval EFI_SUCCESS Convert success.
1224 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1228 StorageToConfigResp (
1229 IN BROWSER_STORAGE
*Storage
,
1230 IN CHAR16
**ConfigResp
,
1231 IN CHAR16
*ConfigRequest
,
1232 IN BOOLEAN GetEditBuf
1236 EFI_STRING Progress
;
1238 NAME_VALUE_NODE
*Node
;
1240 FORMSET_STORAGE
*FormsetStorage
;
1242 Status
= EFI_SUCCESS
;
1244 switch (Storage
->Type
) {
1245 case EFI_HII_VARSTORE_BUFFER
:
1246 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1247 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1248 Status
= mHiiConfigRouting
->BlockToConfig (
1258 case EFI_HII_VARSTORE_NAME_VALUE
:
1260 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1261 ASSERT (FormsetStorage
!= NULL
);
1262 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1264 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1265 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1266 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1268 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1269 NewStringCat (ConfigResp
, L
"&");
1270 NewStringCat (ConfigResp
, Node
->Name
);
1271 NewStringCat (ConfigResp
, L
"=");
1273 NewStringCat (ConfigResp
, Node
->EditValue
);
1275 NewStringCat (ConfigResp
, Node
->Value
);
1278 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1282 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1284 Status
= EFI_INVALID_PARAMETER
;
1293 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1295 @param Storage The Storage to receive the settings.
1296 @param ConfigResp The <ConfigResp> to be converted.
1298 @retval EFI_SUCCESS Convert success.
1299 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1303 ConfigRespToStorage (
1304 IN BROWSER_STORAGE
*Storage
,
1305 IN CHAR16
*ConfigResp
1309 EFI_STRING Progress
;
1315 Status
= EFI_SUCCESS
;
1317 switch (Storage
->Type
) {
1318 case EFI_HII_VARSTORE_BUFFER
:
1319 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1320 BufferSize
= Storage
->Size
;
1321 Status
= mHiiConfigRouting
->ConfigToBlock (
1324 Storage
->EditBuffer
,
1330 case EFI_HII_VARSTORE_NAME_VALUE
:
1331 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1332 if (StrPtr
== NULL
) {
1335 StrPtr
= StrStr (ConfigResp
, L
"&");
1336 while (StrPtr
!= NULL
) {
1340 StrPtr
= StrPtr
+ 1;
1342 StrPtr
= StrStr (StrPtr
, L
"=");
1343 if (StrPtr
== NULL
) {
1351 StrPtr
= StrPtr
+ 1;
1353 StrPtr
= StrStr (StrPtr
, L
"&");
1354 if (StrPtr
!= NULL
) {
1357 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1361 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1363 Status
= EFI_INVALID_PARAMETER
;
1371 Convert the buffer value to HiiValue.
1373 @param Question The question.
1374 @param Value Unicode buffer save the question value.
1376 @retval Status whether convert the value success.
1381 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1386 BOOLEAN IsBufferStorage
;
1398 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1399 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1400 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1401 IsBufferStorage
= TRUE
;
1403 IsBufferStorage
= FALSE
;
1407 // Question Value is provided by Buffer Storage or NameValue Storage
1409 if (Question
->BufferValue
!= NULL
) {
1411 // This Question is password or orderedlist
1413 Dst
= Question
->BufferValue
;
1416 // Other type of Questions
1418 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1422 // Temp cut at the end of this section, end with '\0' or '&'.
1425 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1428 TempChar
= *StringPtr
;
1431 LengthStr
= StrLen (Value
);
1432 Status
= EFI_SUCCESS
;
1433 if (!IsBufferStorage
&& IsString
) {
1435 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1436 // Add string tail char L'\0' into Length
1438 Length
= Question
->StorageWidth
+ sizeof (CHAR16
);
1439 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1440 Status
= EFI_BUFFER_TOO_SMALL
;
1442 DstBuf
= (CHAR16
*) Dst
;
1443 ZeroMem (TemStr
, sizeof (TemStr
));
1444 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1445 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1446 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1449 // Add tailing L'\0' character
1451 DstBuf
[Index
/4] = L
'\0';
1454 if (Question
->StorageWidth
< ((LengthStr
+ 1) / 2)) {
1455 Status
= EFI_BUFFER_TOO_SMALL
;
1457 ZeroMem (TemStr
, sizeof (TemStr
));
1458 for (Index
= 0; Index
< LengthStr
; Index
++) {
1459 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1460 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1461 if ((Index
& 1) == 0) {
1462 Dst
[Index
/2] = DigitUint8
;
1464 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1470 *StringPtr
= TempChar
;
1476 Get Question's current Value.
1478 @param FormSet FormSet data structure.
1479 @param Form Form data structure.
1480 @param Question Question to be initialized.
1481 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1483 @retval EFI_SUCCESS The function completed successfully.
1488 IN FORM_BROWSER_FORMSET
*FormSet
,
1489 IN FORM_BROWSER_FORM
*Form
,
1490 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1491 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1500 BROWSER_STORAGE
*Storage
;
1501 FORMSET_STORAGE
*FormsetStorage
;
1502 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1503 CHAR16
*ConfigRequest
;
1508 BOOLEAN IsBufferStorage
;
1511 Status
= EFI_SUCCESS
;
1515 if (GetValueFrom
>= GetSetValueWithMax
) {
1516 return EFI_INVALID_PARAMETER
;
1520 // Question value is provided by an Expression, evaluate it
1522 if (Question
->ValueExpression
!= NULL
) {
1523 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1524 if (!EFI_ERROR (Status
)) {
1525 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1526 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1527 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1528 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1529 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1531 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1532 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1534 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1536 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1537 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1543 // Get question value by read expression.
1545 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1546 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1547 if (!EFI_ERROR (Status
) &&
1548 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1550 // Only update question value to the valid result.
1552 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1553 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1554 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1555 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1556 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1558 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1559 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1561 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1563 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1564 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1570 // Question value is provided by RTC
1572 Storage
= Question
->Storage
;
1573 QuestionValue
= &Question
->HiiValue
.Value
;
1574 if (Storage
== NULL
) {
1576 // It's a Question without storage, or RTC date/time
1578 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1580 // Date and time define the same Flags bit
1582 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1583 case QF_DATE_STORAGE_TIME
:
1584 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1587 case QF_DATE_STORAGE_WAKEUP
:
1588 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1591 case QF_DATE_STORAGE_NORMAL
:
1594 // For date/time without storage
1599 if (EFI_ERROR (Status
)) {
1600 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1601 QuestionValue
->date
.Year
= 0xff;
1602 QuestionValue
->date
.Month
= 0xff;
1603 QuestionValue
->date
.Day
= 0xff;
1605 QuestionValue
->time
.Hour
= 0xff;
1606 QuestionValue
->time
.Minute
= 0xff;
1607 QuestionValue
->time
.Second
= 0xff;
1612 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1613 QuestionValue
->date
.Year
= EfiTime
.Year
;
1614 QuestionValue
->date
.Month
= EfiTime
.Month
;
1615 QuestionValue
->date
.Day
= EfiTime
.Day
;
1617 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1618 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1619 QuestionValue
->time
.Second
= EfiTime
.Second
;
1627 // Question value is provided by EFI variable
1629 StorageWidth
= Question
->StorageWidth
;
1630 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1631 if (Question
->BufferValue
!= NULL
) {
1632 Dst
= Question
->BufferValue
;
1634 Dst
= (UINT8
*) QuestionValue
;
1637 Status
= gRT
->GetVariable (
1638 Question
->VariableName
,
1645 // Always return success, even this EFI variable doesn't exist
1651 // Question Value is provided by Buffer Storage or NameValue Storage
1653 if (Question
->BufferValue
!= NULL
) {
1655 // This Question is password or orderedlist
1657 Dst
= Question
->BufferValue
;
1660 // Other type of Questions
1662 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1665 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1666 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1667 IsBufferStorage
= TRUE
;
1669 IsBufferStorage
= FALSE
;
1671 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1672 if (IsBufferStorage
) {
1673 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1675 // Copy from storage Edit buffer
1677 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1680 // Copy from storage Edit buffer
1682 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1686 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1687 if (EFI_ERROR (Status
)) {
1691 ASSERT (Value
!= NULL
);
1692 Status
= BufferToValue (Question
, Value
);
1696 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1697 ASSERT (FormsetStorage
!= NULL
);
1699 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1700 // <ConfigHdr> + "&" + <VariableName>
1702 if (IsBufferStorage
) {
1703 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1704 Length
+= StrLen (Question
->BlockName
);
1706 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1707 Length
+= StrLen (Question
->VariableName
) + 1;
1709 // Allocate buffer include '\0'
1710 MaxLen
= Length
+ 1;
1711 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1712 ASSERT (ConfigRequest
!= NULL
);
1714 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1715 if (IsBufferStorage
) {
1716 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1718 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1719 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1723 // Request current settings from Configuration Driver
1725 Status
= mHiiConfigRouting
->ExtractConfig (
1731 FreePool (ConfigRequest
);
1732 if (EFI_ERROR (Status
)) {
1737 // Skip <ConfigRequest>
1739 if (IsBufferStorage
) {
1740 Value
= StrStr (Result
, L
"&VALUE");
1741 if (Value
== NULL
) {
1743 return EFI_NOT_FOUND
;
1750 Value
= Result
+ Length
;
1752 if (*Value
!= '=') {
1754 return EFI_NOT_FOUND
;
1757 // Skip '=', point to value
1761 Status
= BufferToValue (Question
, Value
);
1762 if (EFI_ERROR (Status
)) {
1768 // Synchronize Edit Buffer
1770 if (IsBufferStorage
) {
1771 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1773 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1776 if (Result
!= NULL
) {
1786 Save Question Value to edit copy(cached) or Storage(uncached).
1788 @param FormSet FormSet data structure.
1789 @param Form Form data structure.
1790 @param Question Pointer to the Question.
1791 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1793 @retval EFI_SUCCESS The function completed successfully.
1798 IN FORM_BROWSER_FORMSET
*FormSet
,
1799 IN FORM_BROWSER_FORM
*Form
,
1800 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1801 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1811 BROWSER_STORAGE
*Storage
;
1812 FORMSET_STORAGE
*FormsetStorage
;
1813 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1818 BOOLEAN IsBufferStorage
;
1824 NAME_VALUE_NODE
*Node
;
1827 Status
= EFI_SUCCESS
;
1830 if (SetValueTo
>= GetSetValueWithMax
) {
1831 return EFI_INVALID_PARAMETER
;
1835 // If Question value is provided by an Expression, then it is read only
1837 if (Question
->ValueExpression
!= NULL
) {
1842 // Before set question value, evaluate its write expression.
1844 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1845 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1846 if (EFI_ERROR (Status
)) {
1852 // Question value is provided by RTC
1854 Storage
= Question
->Storage
;
1855 QuestionValue
= &Question
->HiiValue
.Value
;
1856 if (Storage
== NULL
) {
1858 // It's a Question without storage, or RTC date/time
1860 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1862 // Date and time define the same Flags bit
1864 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1865 case QF_DATE_STORAGE_TIME
:
1866 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1869 case QF_DATE_STORAGE_WAKEUP
:
1870 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1873 case QF_DATE_STORAGE_NORMAL
:
1876 // For date/time without storage
1881 if (EFI_ERROR (Status
)) {
1885 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1886 EfiTime
.Year
= QuestionValue
->date
.Year
;
1887 EfiTime
.Month
= QuestionValue
->date
.Month
;
1888 EfiTime
.Day
= QuestionValue
->date
.Day
;
1890 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1891 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1892 EfiTime
.Second
= QuestionValue
->time
.Second
;
1895 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1896 Status
= gRT
->SetTime (&EfiTime
);
1898 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1906 // Question value is provided by EFI variable
1908 StorageWidth
= Question
->StorageWidth
;
1909 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1910 if (Question
->BufferValue
!= NULL
) {
1911 Src
= Question
->BufferValue
;
1913 Src
= (UINT8
*) QuestionValue
;
1916 Status
= gRT
->SetVariable (
1917 Question
->VariableName
,
1919 Storage
->Attributes
,
1927 // Question Value is provided by Buffer Storage or NameValue Storage
1929 if (Question
->BufferValue
!= NULL
) {
1930 Src
= Question
->BufferValue
;
1932 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1935 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1936 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1937 IsBufferStorage
= TRUE
;
1939 IsBufferStorage
= FALSE
;
1941 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1943 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1944 if (IsBufferStorage
) {
1945 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1947 // Copy to storage edit buffer
1949 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1950 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1952 // Copy to storage edit buffer
1954 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1959 // Allocate enough string buffer.
1962 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1963 Value
= AllocateZeroPool (BufferLen
);
1964 ASSERT (Value
!= NULL
);
1966 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1968 TemName
= (CHAR16
*) Src
;
1970 for (; *TemName
!= L
'\0'; TemName
++) {
1971 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1974 BufferLen
= StorageWidth
* 2 + 1;
1975 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1976 ASSERT (Value
!= NULL
);
1978 // Convert Buffer to Hex String
1980 TemBuffer
= Src
+ StorageWidth
- 1;
1982 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1983 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1987 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1989 if (EFI_ERROR (Status
)) {
1993 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1995 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1996 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1998 if (IsBufferStorage
) {
1999 Length
= StrLen (Question
->BlockName
) + 7;
2001 Length
= StrLen (Question
->VariableName
) + 2;
2003 if (!IsBufferStorage
&& IsString
) {
2004 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2006 Length
+= (StorageWidth
* 2);
2008 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2009 ASSERT (FormsetStorage
!= NULL
);
2010 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2011 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2012 ASSERT (ConfigResp
!= NULL
);
2014 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2015 if (IsBufferStorage
) {
2016 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2017 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2019 StrCatS (ConfigResp
, MaxLen
, L
"&");
2020 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2021 StrCatS (ConfigResp
, MaxLen
, L
"=");
2024 Value
= ConfigResp
+ StrLen (ConfigResp
);
2026 if (!IsBufferStorage
&& IsString
) {
2028 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2030 TemName
= (CHAR16
*) Src
;
2032 for (; *TemName
!= L
'\0'; TemName
++) {
2033 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
2037 // Convert Buffer to Hex String
2039 TemBuffer
= Src
+ StorageWidth
- 1;
2041 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2042 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2047 // Convert to lower char.
2049 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2050 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2051 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2056 // Submit Question Value to Configuration Driver
2058 Status
= mHiiConfigRouting
->RouteConfig (
2063 if (EFI_ERROR (Status
)) {
2064 FreePool (ConfigResp
);
2067 FreePool (ConfigResp
);
2070 // Sync storage, from editbuffer to buffer.
2072 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2080 Perform nosubmitif check for a Form.
2082 @param FormSet FormSet data structure.
2083 @param Form Form data structure.
2084 @param Question The Question to be validated.
2085 @param Type Validation type: NoSubmit
2087 @retval EFI_SUCCESS Form validation pass.
2088 @retval other Form validation failed.
2093 IN FORM_BROWSER_FORMSET
*FormSet
,
2094 IN FORM_BROWSER_FORM
*Form
,
2095 IN FORM_BROWSER_STATEMENT
*Question
,
2101 LIST_ENTRY
*ListHead
;
2102 FORM_EXPRESSION
*Expression
;
2103 UINT32 BrowserStatus
;
2106 BrowserStatus
= BROWSER_SUCCESS
;
2110 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2111 ListHead
= &Question
->InconsistentListHead
;
2114 case EFI_HII_EXPRESSION_WARNING_IF
:
2115 ListHead
= &Question
->WarningListHead
;
2118 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2119 ListHead
= &Question
->NoSubmitListHead
;
2124 return EFI_UNSUPPORTED
;
2127 Link
= GetFirstNode (ListHead
);
2128 while (!IsNull (ListHead
, Link
)) {
2129 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2132 // Evaluate the expression
2134 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2135 if (EFI_ERROR (Status
)) {
2139 if (IsTrue (&Expression
->Result
)) {
2141 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2142 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2145 case EFI_HII_EXPRESSION_WARNING_IF
:
2146 BrowserStatus
= BROWSER_WARNING_IF
;
2149 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2150 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2152 // This code only used to compatible with old display engine,
2153 // New display engine will not use this field.
2155 if (Expression
->Error
!= 0) {
2156 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2165 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2167 // If in system submit process and for no_submit_if check, not popup this error message.
2168 // Will process this fail again later in not system submit process.
2170 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2173 if (ErrorStr
!= NULL
) {
2174 FreePool (ErrorStr
);
2177 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2180 return EFI_NOT_READY
;
2184 Link
= GetNextNode (ListHead
, Link
);
2191 Perform question check.
2193 If one question has more than one check, process form high priority to low.
2194 Only one error info will be popup.
2196 @param FormSet FormSet data structure.
2197 @param Form Form data structure.
2198 @param Question The Question to be validated.
2200 @retval EFI_SUCCESS Form validation pass.
2201 @retval other Form validation failed.
2205 ValueChangedValidation (
2206 IN FORM_BROWSER_FORMSET
*FormSet
,
2207 IN FORM_BROWSER_FORM
*Form
,
2208 IN FORM_BROWSER_STATEMENT
*Question
2213 Status
= EFI_SUCCESS
;
2216 // Do the inconsistentif check.
2218 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2219 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2220 if (EFI_ERROR (Status
)) {
2226 // Do the warningif check.
2228 if (!IsListEmpty (&Question
->WarningListHead
)) {
2229 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2236 Perform NoSubmit check for each Form in FormSet.
2238 @param FormSet FormSet data structure.
2239 @param CurrentForm Current input form data structure.
2240 @param Statement The statement for this check.
2242 @retval EFI_SUCCESS Form validation pass.
2243 @retval other Form validation failed.
2248 IN FORM_BROWSER_FORMSET
*FormSet
,
2249 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2250 OUT FORM_BROWSER_STATEMENT
**Statement
2255 FORM_BROWSER_STATEMENT
*Question
;
2256 FORM_BROWSER_FORM
*Form
;
2257 LIST_ENTRY
*LinkForm
;
2259 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2260 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2261 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2262 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2264 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2268 Link
= GetFirstNode (&Form
->StatementListHead
);
2269 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2270 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2271 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2272 if (EFI_ERROR (Status
)) {
2273 if (*CurrentForm
== NULL
) {
2274 *CurrentForm
= Form
;
2276 if (Statement
!= NULL
) {
2277 *Statement
= Question
;
2282 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2290 Fill storage's edit copy with settings requested from Configuration Driver.
2292 @param Storage The storage which need to sync.
2293 @param ConfigRequest The config request string which used to sync storage.
2294 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2295 editbuffer to buffer
2296 if TRUE, copy the editbuffer to the buffer.
2297 if FALSE, copy the buffer to the editbuffer.
2299 @retval EFI_SUCCESS The function completed successfully.
2303 SynchronizeStorage (
2304 OUT BROWSER_STORAGE
*Storage
,
2305 IN CHAR16
*ConfigRequest
,
2306 IN BOOLEAN SyncOrRestore
2310 EFI_STRING Progress
;
2314 NAME_VALUE_NODE
*Node
;
2318 Status
= EFI_SUCCESS
;
2321 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2322 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2323 BufferSize
= Storage
->Size
;
2325 if (SyncOrRestore
) {
2326 Src
= Storage
->EditBuffer
;
2327 Dst
= Storage
->Buffer
;
2329 Src
= Storage
->Buffer
;
2330 Dst
= Storage
->EditBuffer
;
2333 if (ConfigRequest
!= NULL
) {
2334 Status
= mHiiConfigRouting
->BlockToConfig(
2342 if (EFI_ERROR (Status
)) {
2346 Status
= mHiiConfigRouting
->ConfigToBlock (
2353 if (Result
!= NULL
) {
2357 CopyMem (Dst
, Src
, BufferSize
);
2359 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2360 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2361 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2362 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2364 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2365 (ConfigRequest
== NULL
)) {
2366 if (SyncOrRestore
) {
2367 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2369 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2373 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2381 When discard the question value, call the callback function with Changed type
2382 to inform the hii driver.
2384 @param FormSet FormSet data structure.
2385 @param Form Form data structure.
2389 SendDiscardInfoToDriver (
2390 IN FORM_BROWSER_FORMSET
*FormSet
,
2391 IN FORM_BROWSER_FORM
*Form
2395 FORM_BROWSER_STATEMENT
*Question
;
2396 EFI_IFR_TYPE_VALUE
*TypeValue
;
2397 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2399 if (FormSet
->ConfigAccess
== NULL
) {
2403 Link
= GetFirstNode (&Form
->StatementListHead
);
2404 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2405 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2406 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2408 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2412 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2416 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2420 if (!Question
->ValueChanged
) {
2425 // Restore the question value before call the CHANGED callback type.
2427 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2429 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2430 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2433 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2434 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2436 TypeValue
= &Question
->HiiValue
.Value
;
2439 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2440 FormSet
->ConfigAccess
->Callback (
2441 FormSet
->ConfigAccess
,
2442 EFI_BROWSER_ACTION_CHANGED
,
2443 Question
->QuestionId
,
2444 Question
->HiiValue
.Type
,
2452 When submit the question value, call the callback function with Submitted type
2453 to inform the hii driver.
2455 @param FormSet FormSet data structure.
2456 @param Form Form data structure.
2460 SubmitCallbackForForm (
2461 IN FORM_BROWSER_FORMSET
*FormSet
,
2462 IN FORM_BROWSER_FORM
*Form
2466 FORM_BROWSER_STATEMENT
*Question
;
2467 EFI_IFR_TYPE_VALUE
*TypeValue
;
2468 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2470 if (FormSet
->ConfigAccess
== NULL
) {
2474 Link
= GetFirstNode (&Form
->StatementListHead
);
2475 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2476 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2477 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2479 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2483 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2487 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2491 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2492 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2494 TypeValue
= &Question
->HiiValue
.Value
;
2497 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2498 FormSet
->ConfigAccess
->Callback (
2499 FormSet
->ConfigAccess
,
2500 EFI_BROWSER_ACTION_SUBMITTED
,
2501 Question
->QuestionId
,
2502 Question
->HiiValue
.Type
,
2510 When value set Success, call the submit callback function.
2512 @param FormSet FormSet data structure.
2513 @param Form Form data structure.
2518 IN FORM_BROWSER_FORMSET
*FormSet
,
2519 IN FORM_BROWSER_FORM
*Form
2522 FORM_BROWSER_FORM
*CurrentForm
;
2526 SubmitCallbackForForm(FormSet
, Form
);
2530 Link
= GetFirstNode (&FormSet
->FormListHead
);
2531 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2532 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2533 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2535 SubmitCallbackForForm(FormSet
, CurrentForm
);
2540 Validate the HiiHandle.
2542 @param HiiHandle The input HiiHandle which need to validate.
2544 @retval TRUE The handle is validate.
2545 @retval FALSE The handle is invalidate.
2550 EFI_HII_HANDLE HiiHandle
2553 EFI_HII_HANDLE
*HiiHandles
;
2557 if (HiiHandle
== NULL
) {
2563 HiiHandles
= HiiGetHiiHandles (NULL
);
2564 ASSERT (HiiHandles
!= NULL
);
2566 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2567 if (HiiHandles
[Index
] == HiiHandle
) {
2573 FreePool (HiiHandles
);
2579 Validate the FormSet. If the formset is not validate, remove it from the list.
2581 @param FormSet The input FormSet which need to validate.
2583 @retval TRUE The handle is validate.
2584 @retval FALSE The handle is invalidate.
2589 FORM_BROWSER_FORMSET
*FormSet
2594 ASSERT (FormSet
!= NULL
);
2596 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2598 // Should not remove the formset which is being used.
2600 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2601 CleanBrowserStorage(FormSet
);
2602 RemoveEntryList (&FormSet
->Link
);
2603 DestroyFormSet (FormSet
);
2609 Check whether need to enable the reset flag in form level.
2610 Also clean all ValueChanged flag in question.
2612 @param SetFlag Whether need to set the Reset Flag.
2613 @param FormSet FormSet data structure.
2614 @param Form Form data structure.
2620 IN FORM_BROWSER_FORMSET
*FormSet
,
2621 IN FORM_BROWSER_FORM
*Form
2625 FORM_BROWSER_STATEMENT
*Question
;
2628 Link
= GetFirstNode (&Form
->StatementListHead
);
2629 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2630 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2631 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2633 if (!Question
->ValueChanged
) {
2637 OldValue
= Question
->ValueChanged
;
2640 // Compare the buffer and editbuffer data to see whether the data has been saved.
2642 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2645 // Only the changed data has been saved, then need to set the reset flag.
2647 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2648 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2649 gResetRequired
= TRUE
;
2652 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2653 gFlagReconnect
= TRUE
;
2660 Check whether need to enable the reset flag.
2661 Also clean ValueChanged flag for all statements.
2663 Form level or formset level, only one.
2665 @param SetFlag Whether need to set the Reset Flag.
2666 @param FormSet FormSet data structure.
2667 @param Form Form data structure.
2671 ValueChangeResetFlagUpdate (
2673 IN FORM_BROWSER_FORMSET
*FormSet
,
2674 IN FORM_BROWSER_FORM
*Form
2677 FORM_BROWSER_FORM
*CurrentForm
;
2681 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2685 Link
= GetFirstNode (&FormSet
->FormListHead
);
2686 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2687 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2688 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2690 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2695 Base on the return Progress string to find the form.
2697 Base on the first return Offset/Width (Name) string to find the form
2698 which keep this string.
2700 @param FormSet FormSet data structure.
2701 @param Storage Storage which has this Progress string.
2702 @param Progress The Progress string which has the first fail string.
2703 @param RetForm The return form for this progress string.
2704 @param RetQuestion The return question for the error progress string.
2706 @retval TRUE Find the error form and statement for this error progress string.
2707 @retval FALSE Not find the error form.
2711 FindQuestionFromProgress (
2712 IN FORM_BROWSER_FORMSET
*FormSet
,
2713 IN BROWSER_STORAGE
*Storage
,
2714 IN EFI_STRING Progress
,
2715 OUT FORM_BROWSER_FORM
**RetForm
,
2716 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2720 LIST_ENTRY
*LinkStorage
;
2721 LIST_ENTRY
*LinkStatement
;
2722 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2723 FORM_BROWSER_FORM
*Form
;
2725 FORM_BROWSER_STATEMENT
*Statement
;
2727 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2731 *RetQuestion
= NULL
;
2734 // Skip the first "&" or the ConfigHdr part.
2736 if (*Progress
== '&') {
2740 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2742 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2744 // For Name/Value type, Skip the ConfigHdr part.
2746 EndStr
= StrStr (Progress
, L
"PATH=");
2747 ASSERT (EndStr
!= NULL
);
2748 while (*EndStr
!= '&') {
2755 // For Buffer type, Skip the ConfigHdr part.
2757 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2758 ASSERT (EndStr
!= NULL
);
2762 Progress
= EndStr
+ 1;
2766 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2768 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2770 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2771 // here, just keep the "Fred" string.
2773 EndStr
= StrStr (Progress
, L
"=");
2774 ASSERT (EndStr
!= NULL
);
2778 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2779 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2781 EndStr
= StrStr (Progress
, L
"&VALUE=");
2782 ASSERT (EndStr
!= NULL
);
2787 // Search in the form list.
2789 Link
= GetFirstNode (&FormSet
->FormListHead
);
2790 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2791 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2792 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2795 // Search in the ConfigReqeust list in this form.
2797 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2798 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2799 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2800 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2802 if (Storage
!= ConfigInfo
->Storage
) {
2806 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2808 // Find the OffsetWidth string in this form.
2815 if (*RetForm
!= NULL
) {
2816 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2817 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2818 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2819 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2821 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2822 *RetQuestion
= Statement
;
2826 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2827 *RetQuestion
= Statement
;
2833 if (*RetForm
!= NULL
) {
2839 // restore the OffsetWidth string to the original format.
2841 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2847 return (BOOLEAN
) (*RetForm
!= NULL
);
2851 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2852 for form and formset.
2854 @param Storage Storage which has this Progress string.
2855 @param ConfigRequest The ConfigRequest string.
2856 @param Progress The Progress string which has the first fail string.
2857 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2858 @param SyncConfigRequest Return the SyncConfigRequest string.
2862 GetSyncRestoreConfigRequest(
2863 IN BROWSER_STORAGE
*Storage
,
2864 IN EFI_STRING ConfigRequest
,
2865 IN EFI_STRING Progress
,
2866 OUT EFI_STRING
*RestoreConfigRequest
,
2867 OUT EFI_STRING
*SyncConfigRequest
2871 EFI_STRING ConfigHdrEndStr
;
2872 EFI_STRING ElementStr
;
2874 UINTN RestoreEleSize
;
2877 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
2879 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
2880 // Need to restore all the fields in the ConfigRequest.
2882 if (*Progress
== L
'G') {
2883 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2884 ASSERT (*RestoreConfigRequest
!= NULL
);
2889 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2891 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2893 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2894 // here, just keep the "Fred" string.
2896 EndStr
= StrStr (Progress
, L
"=");
2897 ASSERT (EndStr
!= NULL
);
2900 // Find the ConfigHdr in ConfigRequest.
2902 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
2903 ASSERT (ConfigHdrEndStr
!= NULL
);
2904 while (*ConfigHdrEndStr
!= L
'&') {
2909 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2910 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2912 EndStr
= StrStr (Progress
, L
"&VALUE=");
2913 ASSERT (EndStr
!= NULL
);
2916 // Find the ConfigHdr in ConfigRequest.
2918 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
2921 // Find the first fail pair in the ConfigRequest.
2923 ElementStr
= StrStr (ConfigRequest
, Progress
);
2924 ASSERT (ElementStr
!= NULL
);
2926 // To get the RestoreConfigRequest.
2928 RestoreEleSize
= StrSize (ElementStr
);
2929 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
2930 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
2931 ASSERT (*RestoreConfigRequest
!= NULL
);
2932 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
2933 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
2935 // To get the SyncConfigRequest.
2937 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
2938 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
2939 ASSERT (*SyncConfigRequest
!= NULL
);
2940 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
2943 // restore the Progress string to the original format.
2945 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2953 Popup an save error info and get user input.
2955 @param TitleId The form title id.
2956 @param HiiHandle The hii handle for this package.
2958 @retval UINT32 The user select option for the save fail.
2959 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2963 IN EFI_STRING_ID TitleId
,
2964 IN EFI_HII_HANDLE HiiHandle
2968 CHAR16
*StringBuffer
;
2971 FormTitle
= GetToken (TitleId
, HiiHandle
);
2973 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2974 ASSERT (StringBuffer
!= NULL
);
2978 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2979 L
"Submit Fail For Form: %s.",
2983 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2985 FreePool (StringBuffer
);
2986 FreePool (FormTitle
);
2992 Popup an NO_SUBMIT_IF error info and get user input.
2994 @param TitleId The form title id.
2995 @param HiiHandle The hii handle for this package.
2997 @retval UINT32 The user select option for the save fail.
2998 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3001 ConfirmNoSubmitFail (
3002 IN EFI_STRING_ID TitleId
,
3003 IN EFI_HII_HANDLE HiiHandle
3007 CHAR16
*StringBuffer
;
3010 FormTitle
= GetToken (TitleId
, HiiHandle
);
3012 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3013 ASSERT (StringBuffer
!= NULL
);
3017 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3018 L
"NO_SUBMIT_IF error For Form: %s.",
3022 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3024 FreePool (StringBuffer
);
3025 FreePool (FormTitle
);
3031 Discard data based on the input setting scope (Form, FormSet or System).
3033 @param FormSet FormSet data structure.
3034 @param Form Form data structure.
3035 @param SettingScope Setting Scope for Discard action.
3037 @retval EFI_SUCCESS The function completed successfully.
3038 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3043 IN FORM_BROWSER_FORMSET
*FormSet
,
3044 IN FORM_BROWSER_FORM
*Form
,
3045 IN BROWSER_SETTING_SCOPE SettingScope
3049 FORMSET_STORAGE
*Storage
;
3050 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3051 FORM_BROWSER_FORMSET
*LocalFormSet
;
3052 FORM_BROWSER_FORMSET
*OldFormSet
;
3055 // Check the supported setting level.
3057 if (SettingScope
>= MaxLevel
) {
3058 return EFI_UNSUPPORTED
;
3061 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3063 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3064 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3065 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3066 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3068 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3073 // Skip if there is no RequestElement
3075 if (ConfigInfo
->ElementCount
== 0) {
3080 // Prepare <ConfigResp>
3082 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3085 // Call callback with Changed type to inform the driver.
3087 SendDiscardInfoToDriver (FormSet
, Form
);
3090 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3091 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3094 // Discard Buffer storage or Name/Value storage
3096 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3097 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3098 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3099 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3101 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3106 // Skip if there is no RequestElement
3108 if (Storage
->ElementCount
== 0) {
3112 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3115 Link
= GetFirstNode (&FormSet
->FormListHead
);
3116 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3117 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3118 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3121 // Call callback with Changed type to inform the driver.
3123 SendDiscardInfoToDriver (FormSet
, Form
);
3126 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3127 } else if (SettingScope
== SystemLevel
) {
3129 // System Level Discard.
3131 OldFormSet
= mSystemLevelFormSet
;
3134 // Discard changed value for each FormSet in the maintain list.
3136 Link
= GetFirstNode (&gBrowserFormSetList
);
3137 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3138 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3139 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3140 if (!ValidateFormSet(LocalFormSet
)) {
3144 mSystemLevelFormSet
= LocalFormSet
;
3146 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3147 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3149 // Remove maintain backup list after discard except for the current using FormSet.
3151 CleanBrowserStorage(LocalFormSet
);
3152 RemoveEntryList (&LocalFormSet
->Link
);
3153 DestroyFormSet (LocalFormSet
);
3157 mSystemLevelFormSet
= OldFormSet
;
3164 Submit data for a form.
3166 @param FormSet FormSet data structure.
3167 @param Form Form data structure.
3169 @retval EFI_SUCCESS The function completed successfully.
3170 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3175 IN FORM_BROWSER_FORMSET
*FormSet
,
3176 IN FORM_BROWSER_FORM
*Form
3181 EFI_STRING ConfigResp
;
3182 EFI_STRING Progress
;
3183 BROWSER_STORAGE
*Storage
;
3184 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3185 BOOLEAN SubmitFormFail
;
3187 SubmitFormFail
= FALSE
;
3189 if (!IsNvUpdateRequiredForForm (Form
)) {
3193 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3194 if (EFI_ERROR (Status
)) {
3198 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3199 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3200 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3201 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3203 Storage
= ConfigInfo
->Storage
;
3204 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3209 // Skip if there is no RequestElement
3211 if (ConfigInfo
->ElementCount
== 0) {
3216 // 1. Prepare <ConfigResp>
3218 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3219 if (EFI_ERROR (Status
)) {
3224 // 2. Set value to hii config routine protocol.
3226 Status
= mHiiConfigRouting
->RouteConfig (
3232 if (EFI_ERROR (Status
)) {
3234 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3236 SubmitFormFail
= TRUE
;
3237 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3238 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3239 FreePool (ConfigResp
);
3243 FreePool (ConfigResp
);
3245 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3247 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3251 // 4. Process the save failed storage.
3253 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3254 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3255 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3256 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3257 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3258 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3260 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3261 // base on the SyncConfigRequest to Sync the buffer.
3263 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3264 FreePool (ConfigInfo
->RestoreConfigRequest
);
3265 ConfigInfo
->RestoreConfigRequest
= NULL
;
3266 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3267 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3268 FreePool (ConfigInfo
->SyncConfigRequest
);
3269 ConfigInfo
->SyncConfigRequest
= NULL
;
3272 Status
= EFI_SUCCESS
;
3275 Status
= EFI_UNSUPPORTED
;
3279 // Free Form save fail list.
3281 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3282 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3283 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3284 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3289 // 5. Update the NV flag.
3291 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3294 // 6 Call callback with Submitted type to inform the driver.
3296 if (!SubmitFormFail
) {
3297 SubmitCallback (FormSet
, Form
);
3304 Submit data for a formset.
3306 @param FormSet FormSet data structure.
3307 @param SkipProcessFail Whether skip to process the save failed storage.
3308 If submit formset is called when do system level save,
3309 set this value to true and process the failed formset
3311 if submit formset is called when do formset level save,
3312 set the value to false and process the failed storage
3313 right after process all storages for this formset.
3315 @retval EFI_SUCCESS The function completed successfully.
3316 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3321 IN FORM_BROWSER_FORMSET
*FormSet
,
3322 IN BOOLEAN SkipProcessFail
3327 EFI_STRING ConfigResp
;
3328 EFI_STRING Progress
;
3329 BROWSER_STORAGE
*Storage
;
3330 FORMSET_STORAGE
*FormSetStorage
;
3331 FORM_BROWSER_FORM
*Form
;
3332 BOOLEAN HasInserted
;
3333 FORM_BROWSER_STATEMENT
*Question
;
3334 BOOLEAN SubmitFormSetFail
;
3336 HasInserted
= FALSE
;
3337 SubmitFormSetFail
= FALSE
;
3339 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3344 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3345 if (EFI_ERROR (Status
)) {
3346 if (SkipProcessFail
) {
3348 // Process NO_SUBMIT check first, so insert it at head.
3350 FormSet
->SaveFailForm
= Form
;
3351 FormSet
->SaveFailStatement
= Question
;
3352 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3361 // Submit Buffer storage or Name/Value storage
3363 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3364 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3365 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3366 Storage
= FormSetStorage
->BrowserStorage
;
3367 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3369 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3374 // Skip if there is no RequestElement
3376 if (FormSetStorage
->ElementCount
== 0) {
3381 // 1. Prepare <ConfigResp>
3383 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3384 if (EFI_ERROR (Status
)) {
3389 // 2. Send <ConfigResp> to Routine config Protocol.
3391 Status
= mHiiConfigRouting
->RouteConfig (
3396 if (EFI_ERROR (Status
)) {
3398 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3400 SubmitFormSetFail
= TRUE
;
3401 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3402 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3405 // Call submit formset for system level, save the formset info
3406 // and process later.
3408 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3409 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3410 FormSet
->SaveFailForm
= Form
;
3411 FormSet
->SaveFailStatement
= Question
;
3412 if (SkipProcessFail
) {
3413 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3418 FreePool (ConfigResp
);
3422 FreePool (ConfigResp
);
3424 // 3. Config success, update storage shadow Buffer
3426 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3430 // 4. Has save fail storage need to handle.
3433 if (!SkipProcessFail
) {
3435 // If not in system level, just handl the save failed storage here.
3437 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3438 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3439 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3440 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3441 Storage
= FormSetStorage
->BrowserStorage
;
3442 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3444 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3445 // base on the SyncConfigRequest to Sync the buffer.
3447 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3448 FreePool (FormSetStorage
->RestoreConfigRequest
);
3449 FormSetStorage
->RestoreConfigRequest
= NULL
;
3450 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3451 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3452 FreePool (FormSetStorage
->SyncConfigRequest
);
3453 FormSetStorage
->SyncConfigRequest
= NULL
;
3456 Status
= EFI_SUCCESS
;
3459 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3461 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3462 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3463 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3464 gCurrentSelection
->FormId
= Form
->FormId
;
3465 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3467 Status
= EFI_UNSUPPORTED
;
3471 // Free FormSet save fail list.
3473 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3474 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3475 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3476 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3480 // If in system level, just return error and handle the failed formset later.
3482 Status
= EFI_UNSUPPORTED
;
3487 // 5. Update the NV flag.
3489 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3492 // 6. Call callback with Submitted type to inform the driver.
3494 if (!SubmitFormSetFail
) {
3495 SubmitCallback (FormSet
, NULL
);
3502 Submit data for all formsets.
3504 @retval EFI_SUCCESS The function completed successfully.
3505 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3515 LIST_ENTRY
*StorageLink
;
3516 FORMSET_STORAGE
*FormSetStorage
;
3517 FORM_BROWSER_FORM
*Form
;
3518 FORM_BROWSER_FORMSET
*LocalFormSet
;
3519 UINT32 UserSelection
;
3520 FORM_BROWSER_STATEMENT
*Question
;
3522 mSystemSubmit
= TRUE
;
3523 Link
= GetFirstNode (&gBrowserFormSetList
);
3524 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3525 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3526 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3527 if (!ValidateFormSet(LocalFormSet
)) {
3531 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3532 if (EFI_ERROR (Status
)) {
3537 // Remove maintain backup list after save except for the current using FormSet.
3539 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3540 CleanBrowserStorage(LocalFormSet
);
3541 RemoveEntryList (&LocalFormSet
->Link
);
3542 DestroyFormSet (LocalFormSet
);
3545 mSystemSubmit
= FALSE
;
3547 Status
= EFI_SUCCESS
;
3550 // Process the save failed formsets.
3552 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3553 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3554 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3555 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3557 if (!ValidateFormSet(LocalFormSet
)) {
3561 Form
= LocalFormSet
->SaveFailForm
;
3562 Question
= LocalFormSet
->SaveFailStatement
;
3565 // Confirm with user, get user input.
3567 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3569 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3571 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3573 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3576 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3577 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3578 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3579 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3580 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3581 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3583 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3586 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3587 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3588 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3589 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3591 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3592 // base on the SyncConfigRequest to Sync the buffer.
3594 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3595 FreePool (FormSetStorage
->RestoreConfigRequest
);
3596 FormSetStorage
->RestoreConfigRequest
= NULL
;
3597 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3598 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3599 FreePool (FormSetStorage
->SyncConfigRequest
);
3600 FormSetStorage
->SyncConfigRequest
= NULL
;
3605 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3606 CleanBrowserStorage(LocalFormSet
);
3607 RemoveEntryList (&LocalFormSet
->Link
);
3608 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3609 DestroyFormSet (LocalFormSet
);
3611 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3614 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3615 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3618 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3620 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3621 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3622 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3623 gCurrentSelection
->FormId
= Form
->FormId
;
3624 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3626 Status
= EFI_UNSUPPORTED
;
3632 // Clean the list which will not process.
3634 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3635 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3636 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3637 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3639 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3640 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3641 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3642 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3650 Submit data based on the input Setting level (Form, FormSet or System).
3652 @param FormSet FormSet data structure.
3653 @param Form Form data structure.
3654 @param SettingScope Setting Scope for Submit action.
3656 @retval EFI_SUCCESS The function completed successfully.
3657 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3662 IN FORM_BROWSER_FORMSET
*FormSet
,
3663 IN FORM_BROWSER_FORM
*Form
,
3664 IN BROWSER_SETTING_SCOPE SettingScope
3669 switch (SettingScope
) {
3671 Status
= SubmitForForm(FormSet
, Form
);
3675 Status
= SubmitForFormSet (FormSet
, FALSE
);
3679 Status
= SubmitForSystem ();
3683 Status
= EFI_UNSUPPORTED
;
3691 Converts the unicode character of the string from uppercase to lowercase.
3692 This is a internal function.
3694 @param ConfigString String to be converted
3700 IN EFI_STRING ConfigString
3706 ASSERT (ConfigString
!= NULL
);
3709 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3711 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3712 if (*String
== L
'=') {
3714 } else if (*String
== L
'&') {
3716 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3717 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3723 Find the point in the ConfigResp string for this question.
3725 @param Question The question.
3726 @param ConfigResp Get ConfigResp string.
3728 @retval point to the offset where is for this question.
3732 GetOffsetFromConfigResp (
3733 IN FORM_BROWSER_STATEMENT
*Question
,
3734 IN CHAR16
*ConfigResp
3737 CHAR16
*RequestElement
;
3741 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3743 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3744 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3745 if (RequestElement
!= NULL
) {
3747 // Skip the "VariableName=" field.
3749 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3752 return RequestElement
;
3756 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3760 // 1. Directly use Question->BlockName to find.
3762 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3763 if (RequestElement
!= NULL
) {
3765 // Skip the "Question->BlockName&VALUE=" field.
3767 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3768 return RequestElement
;
3772 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3774 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3775 ASSERT (BlockData
!= NULL
);
3776 HiiToLower (BlockData
);
3777 RequestElement
= StrStr (ConfigResp
, BlockData
);
3778 FreePool (BlockData
);
3780 if (RequestElement
!= NULL
) {
3782 // Skip the "Question->BlockName&VALUE=" field.
3784 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3787 return RequestElement
;
3791 Get Question default value from AltCfg string.
3793 @param FormSet The form set.
3794 @param Form The form
3795 @param Question The question.
3797 @retval EFI_SUCCESS Question is reset to default value.
3801 GetDefaultValueFromAltCfg (
3802 IN FORM_BROWSER_FORMSET
*FormSet
,
3803 IN FORM_BROWSER_FORM
*Form
,
3804 IN OUT FORM_BROWSER_STATEMENT
*Question
3807 BROWSER_STORAGE
*Storage
;
3808 FORMSET_STORAGE
*FormSetStorage
;
3812 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3814 Storage
= Question
->Storage
;
3815 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3816 return EFI_NOT_FOUND
;
3820 // Try to get AltCfg string from form. If not found it, then
3821 // try to get it from formset.
3824 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3825 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3826 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3827 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3829 if (Storage
== ConfigInfo
->Storage
) {
3830 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3835 if (ConfigResp
== NULL
) {
3836 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3837 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3838 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3839 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3841 if (Storage
== FormSetStorage
->BrowserStorage
) {
3842 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3848 if (ConfigResp
== NULL
) {
3849 return EFI_NOT_FOUND
;
3852 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3853 if (Value
== NULL
) {
3854 return EFI_NOT_FOUND
;
3857 return BufferToValue (Question
, Value
);
3861 Get default Id value used for browser.
3863 @param DefaultId The default id value used by hii.
3865 @retval Browser used default value.
3869 GetDefaultIdForCallBack (
3873 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3874 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3875 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3876 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3877 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3878 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3879 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3880 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3881 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3882 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3883 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3884 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3893 Return data element in an Array by its Index.
3895 @param Array The data array.
3896 @param Type Type of the data in this array.
3897 @param Index Zero based index for data in this array.
3899 @retval Value The data to be returned
3911 ASSERT (Array
!= NULL
);
3915 case EFI_IFR_TYPE_NUM_SIZE_8
:
3916 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3919 case EFI_IFR_TYPE_NUM_SIZE_16
:
3920 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3923 case EFI_IFR_TYPE_NUM_SIZE_32
:
3924 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3927 case EFI_IFR_TYPE_NUM_SIZE_64
:
3928 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3940 Set value of a data element in an Array by its Index.
3942 @param Array The data array.
3943 @param Type Type of the data in this array.
3944 @param Index Zero based index for data in this array.
3945 @param Value The value to be set.
3957 ASSERT (Array
!= NULL
);
3960 case EFI_IFR_TYPE_NUM_SIZE_8
:
3961 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3964 case EFI_IFR_TYPE_NUM_SIZE_16
:
3965 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3968 case EFI_IFR_TYPE_NUM_SIZE_32
:
3969 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3972 case EFI_IFR_TYPE_NUM_SIZE_64
:
3973 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3982 Search an Option of a Question by its value.
3984 @param Question The Question
3985 @param OptionValue Value for Option to be searched.
3987 @retval Pointer Pointer to the found Option.
3988 @retval NULL Option not found.
3993 IN FORM_BROWSER_STATEMENT
*Question
,
3994 IN EFI_HII_VALUE
*OptionValue
3998 QUESTION_OPTION
*Option
;
4001 Link
= GetFirstNode (&Question
->OptionListHead
);
4002 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4003 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4005 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4007 // Check the suppressif condition, only a valid option can be return.
4009 if ((Option
->SuppressExpression
== NULL
) ||
4010 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4015 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4023 Reset Question to its default value.
4025 @param FormSet The form set.
4026 @param Form The form.
4027 @param Question The question.
4028 @param DefaultId The Class of the default.
4030 @retval EFI_SUCCESS Question is reset to default value.
4034 GetQuestionDefault (
4035 IN FORM_BROWSER_FORMSET
*FormSet
,
4036 IN FORM_BROWSER_FORM
*Form
,
4037 IN FORM_BROWSER_STATEMENT
*Question
,
4043 QUESTION_DEFAULT
*Default
;
4044 QUESTION_OPTION
*Option
;
4045 EFI_HII_VALUE
*HiiValue
;
4047 EFI_STRING StrValue
;
4048 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4049 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4052 EFI_IFR_TYPE_VALUE
*TypeValue
;
4054 Status
= EFI_NOT_FOUND
;
4058 // Statement don't have storage, skip them
4060 if (Question
->QuestionId
== 0) {
4065 // There are Five ways to specify default value for a Question:
4066 // 1, use call back function (highest priority)
4067 // 2, use ExtractConfig function
4068 // 3, use nested EFI_IFR_DEFAULT
4069 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4070 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4072 HiiValue
= &Question
->HiiValue
;
4073 TypeValue
= &HiiValue
->Value
;
4074 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4076 // For orderedlist, need to pass the BufferValue to Callback function.
4078 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4082 // Get Question defaut value from call back function.
4084 ConfigAccess
= FormSet
->ConfigAccess
;
4085 Action
= GetDefaultIdForCallBack (DefaultId
);
4086 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4087 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4088 Status
= ConfigAccess
->Callback (
4091 Question
->QuestionId
,
4096 if (!EFI_ERROR (Status
)) {
4097 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4098 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4099 ASSERT (NewString
!= NULL
);
4101 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4102 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4103 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4105 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4108 FreePool (NewString
);
4115 // Get default value from altcfg string.
4117 if (ConfigAccess
!= NULL
) {
4118 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4119 if (!EFI_ERROR (Status
)) {
4125 // EFI_IFR_DEFAULT has highest priority
4127 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4128 Link
= GetFirstNode (&Question
->DefaultListHead
);
4129 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4130 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4132 if (Default
->DefaultId
== DefaultId
) {
4133 if (Default
->ValueExpression
!= NULL
) {
4135 // Default is provided by an Expression, evaluate it
4137 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4138 if (EFI_ERROR (Status
)) {
4142 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4143 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4144 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4145 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4146 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4148 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4149 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4151 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4153 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4154 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4157 // Default value is embedded in EFI_IFR_DEFAULT
4159 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4160 ASSERT (HiiValue
->Buffer
!= NULL
);
4161 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4163 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4167 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4168 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4169 if (StrValue
== NULL
) {
4170 return EFI_NOT_FOUND
;
4172 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4173 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4175 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4182 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4187 // EFI_ONE_OF_OPTION
4189 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4190 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4192 // OneOfOption could only provide Standard and Manufacturing default
4194 Link
= GetFirstNode (&Question
->OptionListHead
);
4195 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4196 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4197 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4199 if ((Option
->SuppressExpression
!= NULL
) &&
4200 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4204 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4205 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4207 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4216 // EFI_IFR_CHECKBOX - lowest priority
4218 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4219 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4221 // Checkbox could only provide Standard and Manufacturing default
4223 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4224 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4226 HiiValue
->Value
.b
= TRUE
;
4228 HiiValue
->Value
.b
= FALSE
;
4236 // For Questions without default
4238 Status
= EFI_NOT_FOUND
;
4239 switch (Question
->Operand
) {
4240 case EFI_IFR_NUMERIC_OP
:
4242 // Take minimum value as numeric default value
4244 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4246 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4248 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4249 case EFI_IFR_NUMERIC_SIZE_1
:
4250 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4251 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4252 Status
= EFI_SUCCESS
;
4255 case EFI_IFR_NUMERIC_SIZE_2
:
4256 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4257 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4258 Status
= EFI_SUCCESS
;
4261 case EFI_IFR_NUMERIC_SIZE_4
:
4262 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4263 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4264 Status
= EFI_SUCCESS
;
4267 case EFI_IFR_NUMERIC_SIZE_8
:
4268 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4269 HiiValue
->Value
.u64
= Question
->Minimum
;
4270 Status
= EFI_SUCCESS
;
4277 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4278 HiiValue
->Value
.u64
= Question
->Minimum
;
4279 Status
= EFI_SUCCESS
;
4284 case EFI_IFR_ONE_OF_OP
:
4286 // Take first oneof option as oneof's default value
4288 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4289 Link
= GetFirstNode (&Question
->OptionListHead
);
4290 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4291 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4292 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4294 if ((Option
->SuppressExpression
!= NULL
) &&
4295 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4299 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4300 Status
= EFI_SUCCESS
;
4306 case EFI_IFR_ORDERED_LIST_OP
:
4308 // Take option sequence in IFR as ordered list's default value
4311 Link
= GetFirstNode (&Question
->OptionListHead
);
4312 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4313 Status
= EFI_SUCCESS
;
4314 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4315 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4317 if ((Option
->SuppressExpression
!= NULL
) &&
4318 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4322 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4325 if (Index
>= Question
->MaxContainers
) {
4339 Get AltCfg string for current form.
4341 @param FormSet Form data structure.
4342 @param Form Form data structure.
4343 @param DefaultId The Class of the default.
4344 @param BrowserStorage The input request storage for the questions.
4348 ExtractAltCfgForForm (
4349 IN FORM_BROWSER_FORMSET
*FormSet
,
4350 IN FORM_BROWSER_FORM
*Form
,
4351 IN UINT16 DefaultId
,
4352 IN BROWSER_STORAGE
*BrowserStorage
4360 BROWSER_STORAGE
*Storage
;
4361 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4362 FORMSET_STORAGE
*FormSetStorage
;
4365 // Check whether has get AltCfg string for this formset.
4366 // If yes, no need to get AltCfg for form.
4368 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4369 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4370 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4371 Storage
= FormSetStorage
->BrowserStorage
;
4372 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4373 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4377 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4378 FormSetStorage
->ElementCount
!= 0 &&
4379 FormSetStorage
->HasCallAltCfg
) {
4385 // Get AltCfg string for each form.
4387 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4388 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4389 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4390 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4392 Storage
= ConfigInfo
->Storage
;
4393 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4397 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4402 // 1. Skip if there is no RequestElement
4404 if (ConfigInfo
->ElementCount
== 0) {
4409 // 2. Get value through hii config routine protocol.
4411 Status
= mHiiConfigRouting
->ExtractConfig (
4413 ConfigInfo
->ConfigRequest
,
4417 if (EFI_ERROR (Status
)) {
4422 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4423 // Get the default configuration string according to the default ID.
4425 Status
= mHiiConfigRouting
->GetAltConfig (
4431 &DefaultId
, // it can be NULL to get the current setting.
4435 if (EFI_ERROR (Status
)) {
4439 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4444 Clean AltCfg string for current form.
4446 @param Form Form data structure.
4450 CleanAltCfgForForm (
4451 IN FORM_BROWSER_FORM
*Form
4455 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4457 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4458 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4459 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4460 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4462 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4463 FreePool (ConfigInfo
->ConfigAltResp
);
4464 ConfigInfo
->ConfigAltResp
= NULL
;
4470 Get AltCfg string for current formset.
4472 @param FormSet Form data structure.
4473 @param DefaultId The Class of the default.
4474 @param BrowserStorage The input request storage for the questions.
4478 ExtractAltCfgForFormSet (
4479 IN FORM_BROWSER_FORMSET
*FormSet
,
4480 IN UINT16 DefaultId
,
4481 IN BROWSER_STORAGE
*BrowserStorage
4489 BROWSER_STORAGE
*Storage
;
4490 FORMSET_STORAGE
*FormSetStorage
;
4492 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4493 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4494 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4495 Storage
= FormSetStorage
->BrowserStorage
;
4496 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4498 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4502 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4507 // 1. Skip if there is no RequestElement
4509 if (FormSetStorage
->ElementCount
== 0) {
4513 FormSetStorage
->HasCallAltCfg
= TRUE
;
4516 // 2. Get value through hii config routine protocol.
4518 Status
= mHiiConfigRouting
->ExtractConfig (
4520 FormSetStorage
->ConfigRequest
,
4524 if (EFI_ERROR (Status
)) {
4529 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4530 // Get the default configuration string according to the default ID.
4532 Status
= mHiiConfigRouting
->GetAltConfig (
4538 &DefaultId
, // it can be NULL to get the current setting.
4543 if (EFI_ERROR (Status
)) {
4547 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4553 Clean AltCfg string for current formset.
4555 @param FormSet Form data structure.
4559 CleanAltCfgForFormSet (
4560 IN FORM_BROWSER_FORMSET
*FormSet
4564 FORMSET_STORAGE
*FormSetStorage
;
4566 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4567 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4568 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4569 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4571 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4572 FreePool (FormSetStorage
->ConfigAltResp
);
4573 FormSetStorage
->ConfigAltResp
= NULL
;
4576 FormSetStorage
->HasCallAltCfg
= FALSE
;
4581 Reset Questions to their initial value or default value in a Form, Formset or System.
4583 GetDefaultValueScope parameter decides which questions will reset
4584 to its default value.
4586 @param FormSet FormSet data structure.
4587 @param Form Form data structure.
4588 @param DefaultId The Class of the default.
4589 @param SettingScope Setting Scope for Default action.
4590 @param GetDefaultValueScope Get default value scope.
4591 @param Storage Get default value only for this storage.
4592 @param RetrieveValueFirst Whether call the retrieve call back to
4593 get the initial value before get default
4595 @param SkipGetAltCfg Whether skip the get altcfg string process.
4597 @retval EFI_SUCCESS The function completed successfully.
4598 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4603 IN FORM_BROWSER_FORMSET
*FormSet
,
4604 IN FORM_BROWSER_FORM
*Form
,
4605 IN UINT16 DefaultId
,
4606 IN BROWSER_SETTING_SCOPE SettingScope
,
4607 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4608 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4609 IN BOOLEAN RetrieveValueFirst
,
4610 IN BOOLEAN SkipGetAltCfg
4614 LIST_ENTRY
*FormLink
;
4616 FORM_BROWSER_STATEMENT
*Question
;
4617 FORM_BROWSER_FORMSET
*LocalFormSet
;
4618 FORM_BROWSER_FORMSET
*OldFormSet
;
4620 Status
= EFI_SUCCESS
;
4623 // Check the supported setting level.
4625 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4626 return EFI_UNSUPPORTED
;
4629 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4630 return EFI_UNSUPPORTED
;
4633 if (SettingScope
== FormLevel
) {
4635 // Prepare the AltCfg String for form.
4637 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4638 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4642 // Extract Form default
4644 Link
= GetFirstNode (&Form
->StatementListHead
);
4645 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4646 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4647 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4650 // If get default value only for this storage, check the storage first.
4652 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4657 // If get default value only for no storage question, just skip the question which has storage.
4659 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4664 // If Question is disabled, don't reset it to default
4666 if (Question
->Expression
!= NULL
) {
4667 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4672 if (RetrieveValueFirst
) {
4674 // Call the Retrieve call back to get the initial question value.
4676 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4680 // If not request to get the initial value or get initial value fail, then get default value.
4682 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4683 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4684 if (EFI_ERROR (Status
)) {
4690 // Synchronize Buffer storage's Edit buffer
4692 if ((Question
->Storage
!= NULL
) &&
4693 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4694 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4699 // Clean the AltCfg String.
4701 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4702 CleanAltCfgForForm(Form
);
4704 } else if (SettingScope
== FormSetLevel
) {
4706 // Prepare the AltCfg String for formset.
4708 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4709 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4712 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4713 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4714 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4715 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4716 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4720 // Clean the AltCfg String.
4722 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4723 CleanAltCfgForFormSet (FormSet
);
4725 } else if (SettingScope
== SystemLevel
) {
4727 // Preload all Hii formset.
4729 LoadAllHiiFormset();
4731 OldFormSet
= mSystemLevelFormSet
;
4734 // Set Default Value for each FormSet in the maintain list.
4736 Link
= GetFirstNode (&gBrowserFormSetList
);
4737 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4738 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4739 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4740 if (!ValidateFormSet(LocalFormSet
)) {
4744 mSystemLevelFormSet
= LocalFormSet
;
4746 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4749 mSystemLevelFormSet
= OldFormSet
;
4757 Validate whether this question's value has changed.
4759 @param FormSet FormSet data structure.
4760 @param Form Form data structure.
4761 @param Question Question to be initialized.
4762 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4764 @retval TRUE Question's value has changed.
4765 @retval FALSE Question's value has not changed
4769 IsQuestionValueChanged (
4770 IN FORM_BROWSER_FORMSET
*FormSet
,
4771 IN FORM_BROWSER_FORM
*Form
,
4772 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4773 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4776 EFI_HII_VALUE BackUpValue
;
4777 CHAR8
*BackUpBuffer
;
4778 EFI_HII_VALUE BackUpValue2
;
4779 CHAR8
*BackUpBuffer2
;
4781 BOOLEAN ValueChanged
;
4785 // For quetion without storage, always mark it as data not changed.
4787 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4791 BackUpBuffer
= NULL
;
4792 BackUpBuffer2
= NULL
;
4793 ValueChanged
= FALSE
;
4795 switch (Question
->Operand
) {
4796 case EFI_IFR_ORDERED_LIST_OP
:
4797 BufferWidth
= Question
->StorageWidth
;
4798 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4799 ASSERT (BackUpBuffer
!= NULL
);
4802 case EFI_IFR_STRING_OP
:
4803 case EFI_IFR_PASSWORD_OP
:
4804 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4805 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4806 ASSERT (BackUpBuffer
!= NULL
);
4813 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4815 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4816 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4817 ASSERT_EFI_ERROR(Status
);
4819 switch (Question
->Operand
) {
4820 case EFI_IFR_ORDERED_LIST_OP
:
4821 BufferWidth
= Question
->StorageWidth
;
4822 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4823 ASSERT (BackUpBuffer2
!= NULL
);
4826 case EFI_IFR_STRING_OP
:
4827 case EFI_IFR_PASSWORD_OP
:
4828 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4829 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4830 ASSERT (BackUpBuffer2
!= NULL
);
4837 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4839 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4840 ASSERT_EFI_ERROR(Status
);
4842 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4843 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4844 ValueChanged
= TRUE
;
4847 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4848 ASSERT_EFI_ERROR(Status
);
4850 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4851 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4852 ValueChanged
= TRUE
;
4856 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4857 if (BackUpBuffer
!= NULL
) {
4858 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4859 FreePool (BackUpBuffer
);
4862 if (BackUpBuffer2
!= NULL
) {
4863 FreePool (BackUpBuffer2
);
4866 Question
->ValueChanged
= ValueChanged
;
4868 return ValueChanged
;
4872 Initialize Question's Edit copy from Storage.
4874 @param Selection Selection contains the information about
4875 the Selection, form and formset to be displayed.
4876 Selection action may be updated in retrieve callback.
4877 If Selection is NULL, only initialize Question value.
4878 @param FormSet FormSet data structure.
4879 @param Form Form data structure.
4881 @retval EFI_SUCCESS The function completed successfully.
4886 IN OUT UI_MENU_SELECTION
*Selection
,
4887 IN FORM_BROWSER_FORMSET
*FormSet
,
4888 IN FORM_BROWSER_FORM
*Form
4893 FORM_BROWSER_STATEMENT
*Question
;
4895 Link
= GetFirstNode (&Form
->StatementListHead
);
4896 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4897 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4900 // Initialize local copy of Value for each Question
4902 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4903 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4905 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4907 if (EFI_ERROR (Status
)) {
4911 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4912 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4915 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4922 Initialize Question's Edit copy from Storage for the whole Formset.
4924 @param Selection Selection contains the information about
4925 the Selection, form and formset to be displayed.
4926 Selection action may be updated in retrieve callback.
4927 If Selection is NULL, only initialize Question value.
4928 @param FormSet FormSet data structure.
4930 @retval EFI_SUCCESS The function completed successfully.
4935 IN OUT UI_MENU_SELECTION
*Selection
,
4936 IN FORM_BROWSER_FORMSET
*FormSet
4941 FORM_BROWSER_FORM
*Form
;
4943 Link
= GetFirstNode (&FormSet
->FormListHead
);
4944 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4945 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4948 // Initialize local copy of Value for each Form
4950 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4951 if (EFI_ERROR (Status
)) {
4955 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4959 // Finished question initialization.
4961 FormSet
->QuestionInited
= TRUE
;
4967 Remove the Request element from the Config Request.
4969 @param Storage Pointer to the browser storage.
4970 @param RequestElement The pointer to the Request element.
4975 IN OUT BROWSER_STORAGE
*Storage
,
4976 IN CHAR16
*RequestElement
4982 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4984 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4986 if (NewStr
== NULL
) {
4991 // Remove this element from this ConfigRequest.
4994 NewStr
+= StrLen (RequestElement
);
4995 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4997 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5001 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5003 @param Storage Pointer to the formset storage.
5004 @param ConfigRequest The pointer to the Request element.
5008 RemoveConfigRequest (
5009 FORMSET_STORAGE
*Storage
,
5010 CHAR16
*ConfigRequest
5013 CHAR16
*RequestElement
;
5014 CHAR16
*NextRequestElement
;
5018 // No request element in it, just return.
5020 if (ConfigRequest
== NULL
) {
5024 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5026 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5031 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5033 SearchKey
= L
"&OFFSET";
5037 // Find SearchKey storage
5039 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5040 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5041 ASSERT (RequestElement
!= NULL
);
5042 RequestElement
= StrStr (RequestElement
, SearchKey
);
5044 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5047 while (RequestElement
!= NULL
) {
5049 // +1 to avoid find header itself.
5051 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5054 // The last Request element in configRequest string.
5056 if (NextRequestElement
!= NULL
) {
5058 // Replace "&" with '\0'.
5060 *NextRequestElement
= L
'\0';
5063 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5065 if (NextRequestElement
!= NULL
) {
5067 // Restore '&' with '\0' for later used.
5069 *NextRequestElement
= L
'&';
5072 RequestElement
= NextRequestElement
;
5076 // If no request element remain, just remove the ConfigRequest string.
5078 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5079 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5080 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5081 Storage
->BrowserStorage
->SpareStrLen
= 0;
5086 Base on the current formset info, clean the ConfigRequest string in browser storage.
5088 @param FormSet Pointer of the FormSet
5092 CleanBrowserStorage (
5093 IN OUT FORM_BROWSER_FORMSET
*FormSet
5097 FORMSET_STORAGE
*Storage
;
5099 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5100 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5101 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5102 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5104 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5105 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5109 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5110 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5111 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5112 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5113 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5114 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5116 Storage
->BrowserStorage
->Initialized
= FALSE
;
5122 Check whether current element in the ConfigReqeust string.
5124 @param BrowserStorage Storage which includes ConfigReqeust.
5125 @param RequestElement New element need to check.
5127 @retval TRUE The Element is in the ConfigReqeust string.
5128 @retval FALSE The Element not in the configReqeust String.
5133 BROWSER_STORAGE
*BrowserStorage
,
5134 CHAR16
*RequestElement
5137 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5141 Append the Request element to the Config Request.
5143 @param ConfigRequest Current ConfigRequest info.
5144 @param SpareStrLen Current remain free buffer for config reqeust.
5145 @param RequestElement New Request element.
5149 AppendConfigRequest (
5150 IN OUT CHAR16
**ConfigRequest
,
5151 IN OUT UINTN
*SpareStrLen
,
5152 IN CHAR16
*RequestElement
5160 StrLength
= StrLen (RequestElement
);
5161 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5162 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5165 // Append <RequestElement> to <ConfigRequest>
5167 if (StrLength
> *SpareStrLen
) {
5169 // Old String buffer is not sufficient for RequestElement, allocate a new one
5171 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5172 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5173 ASSERT (NewStr
!= NULL
);
5175 if (*ConfigRequest
!= NULL
) {
5176 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5177 FreePool (*ConfigRequest
);
5179 *ConfigRequest
= NewStr
;
5180 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5183 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5184 *SpareStrLen
-= StrLength
;
5188 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5190 @param Storage Form set Storage.
5191 @param Request The input request string.
5192 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5194 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5195 @retval FALSE All elements covered by current used elements.
5199 ConfigRequestAdjust (
5200 IN BROWSER_STORAGE
*Storage
,
5202 IN BOOLEAN RespString
5205 CHAR16
*RequestElement
;
5206 CHAR16
*NextRequestElement
;
5207 CHAR16
*NextElementBakup
;
5211 CHAR16
*ConfigRequest
;
5214 NextElementBakup
= NULL
;
5217 if (Request
!= NULL
) {
5218 ConfigRequest
= Request
;
5220 ConfigRequest
= Storage
->ConfigRequest
;
5223 if (Storage
->ConfigRequest
== NULL
) {
5224 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5228 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5230 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5235 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5237 SearchKey
= L
"&OFFSET";
5238 ValueKey
= L
"&VALUE";
5242 // Find SearchKey storage
5244 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5245 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5246 ASSERT (RequestElement
!= NULL
);
5247 RequestElement
= StrStr (RequestElement
, SearchKey
);
5249 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5252 while (RequestElement
!= NULL
) {
5255 // +1 to avoid find header itself.
5257 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5260 // The last Request element in configRequest string.
5262 if (NextRequestElement
!= NULL
) {
5263 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5264 NextElementBakup
= NextRequestElement
;
5265 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5266 ASSERT (NextRequestElement
!= NULL
);
5269 // Replace "&" with '\0'.
5271 *NextRequestElement
= L
'\0';
5273 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5274 NextElementBakup
= NextRequestElement
;
5275 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5276 ASSERT (NextRequestElement
!= NULL
);
5278 // Replace "&" with '\0'.
5280 *NextRequestElement
= L
'\0';
5284 if (!ElementValidation (Storage
, RequestElement
)) {
5286 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5288 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5292 if (NextRequestElement
!= NULL
) {
5294 // Restore '&' with '\0' for later used.
5296 *NextRequestElement
= L
'&';
5299 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5300 RequestElement
= NextElementBakup
;
5302 RequestElement
= NextRequestElement
;
5310 Fill storage's edit copy with settings requested from Configuration Driver.
5312 @param FormSet FormSet data structure.
5313 @param Storage Buffer Storage.
5318 IN FORM_BROWSER_FORMSET
*FormSet
,
5319 IN FORMSET_STORAGE
*Storage
5323 EFI_STRING Progress
;
5326 EFI_STRING ConfigRequest
;
5329 ConfigRequest
= NULL
;
5331 switch (Storage
->BrowserStorage
->Type
) {
5332 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5335 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5336 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5337 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5342 case EFI_HII_VARSTORE_BUFFER
:
5343 case EFI_HII_VARSTORE_NAME_VALUE
:
5345 // Skip if there is no RequestElement.
5347 if (Storage
->ElementCount
== 0) {
5352 // Just update the ConfigRequest, if storage already initialized.
5354 if (Storage
->BrowserStorage
->Initialized
) {
5355 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5359 Storage
->BrowserStorage
->Initialized
= TRUE
;
5366 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5368 // Create the config request string to get all fields for this storage.
5369 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5370 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5372 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5373 ConfigRequest
= AllocateZeroPool (StrLen
);
5374 ASSERT (ConfigRequest
!= NULL
);
5378 L
"%s&OFFSET=0&WIDTH=%04x",
5380 Storage
->BrowserStorage
->Size
);
5382 ConfigRequest
= Storage
->ConfigRequest
;
5386 // Request current settings from Configuration Driver
5388 Status
= mHiiConfigRouting
->ExtractConfig (
5396 // If get value fail, extract default from IFR binary
5398 if (EFI_ERROR (Status
)) {
5399 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5402 // Convert Result from <ConfigAltResp> to <ConfigResp>
5404 StrPtr
= StrStr (Result
, L
"&GUID=");
5405 if (StrPtr
!= NULL
) {
5409 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5413 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5416 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5418 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5420 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5421 if (ConfigRequest
!= NULL
) {
5422 FreePool (ConfigRequest
);
5428 Get Value changed status from old question.
5430 @param NewFormSet FormSet data structure.
5431 @param OldQuestion Old question which has value changed.
5435 SyncStatusForQuestion (
5436 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5437 IN FORM_BROWSER_STATEMENT
*OldQuestion
5441 LIST_ENTRY
*QuestionLink
;
5442 FORM_BROWSER_FORM
*Form
;
5443 FORM_BROWSER_STATEMENT
*Question
;
5446 // For each form in one formset.
5448 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5449 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5450 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5451 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5454 // for each question in one form.
5456 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5457 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5458 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5459 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5461 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5462 Question
->ValueChanged
= TRUE
;
5470 Get Value changed status from old formset.
5472 @param NewFormSet FormSet data structure.
5473 @param OldFormSet FormSet data structure.
5477 SyncStatusForFormSet (
5478 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5479 IN FORM_BROWSER_FORMSET
*OldFormSet
5483 LIST_ENTRY
*QuestionLink
;
5484 FORM_BROWSER_FORM
*Form
;
5485 FORM_BROWSER_STATEMENT
*Question
;
5488 // For each form in one formset.
5490 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5491 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5492 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5493 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5496 // for each question in one form.
5498 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5499 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5500 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5501 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5503 if (!Question
->ValueChanged
) {
5508 // Find the same question in new formset and update the value changed flag.
5510 SyncStatusForQuestion (NewFormSet
, Question
);
5516 Get current setting of Questions.
5518 @param FormSet FormSet data structure.
5522 InitializeCurrentSetting (
5523 IN OUT FORM_BROWSER_FORMSET
*FormSet
5527 FORMSET_STORAGE
*Storage
;
5528 FORM_BROWSER_FORMSET
*OldFormSet
;
5531 // Try to find pre FormSet in the maintain backup list.
5532 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5534 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5535 if (OldFormSet
!= NULL
) {
5536 SyncStatusForFormSet (FormSet
, OldFormSet
);
5537 RemoveEntryList (&OldFormSet
->Link
);
5538 DestroyFormSet (OldFormSet
);
5540 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5543 // Extract default from IFR binary for no storage questions.
5545 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5548 // Request current settings from Configuration Driver
5550 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5551 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5552 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5554 LoadStorage (FormSet
, Storage
);
5556 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5562 Fetch the Ifr binary data of a FormSet.
5564 @param Handle PackageList Handle
5565 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5566 specified (NULL or zero GUID), take the first
5567 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5568 found in package list.
5569 On output, GUID of the formset found(if not NULL).
5570 @param BinaryLength The length of the FormSet IFR binary.
5571 @param BinaryData The buffer designed to receive the FormSet.
5573 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5574 BufferLength was updated.
5575 @retval EFI_INVALID_PARAMETER The handle is unknown.
5576 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5577 be found with the requested FormId.
5582 IN EFI_HII_HANDLE Handle
,
5583 IN OUT EFI_GUID
*FormSetGuid
,
5584 OUT UINTN
*BinaryLength
,
5585 OUT UINT8
**BinaryData
5589 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5595 UINT32 PackageListLength
;
5596 EFI_HII_PACKAGE_HEADER PackageHeader
;
5598 UINT8 NumberOfClassGuid
;
5599 BOOLEAN ClassGuidMatch
;
5600 EFI_GUID
*ClassGuid
;
5601 EFI_GUID
*ComparingGuid
;
5605 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5608 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5610 if (FormSetGuid
== NULL
) {
5611 ComparingGuid
= &gZeroGuid
;
5613 ComparingGuid
= FormSetGuid
;
5617 // Get HII PackageList
5620 HiiPackageList
= NULL
;
5621 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5622 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5623 HiiPackageList
= AllocatePool (BufferSize
);
5624 ASSERT (HiiPackageList
!= NULL
);
5626 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5628 if (EFI_ERROR (Status
)) {
5631 ASSERT (HiiPackageList
!= NULL
);
5634 // Get Form package from this HII package List
5636 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5638 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5640 ClassGuidMatch
= FALSE
;
5641 while (Offset
< PackageListLength
) {
5642 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5643 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5645 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5647 // Search FormSet in this Form Package
5649 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5650 while (Offset2
< PackageHeader
.Length
) {
5651 OpCodeData
= Package
+ Offset2
;
5653 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5655 // Try to compare against formset GUID
5657 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5658 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5662 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5664 // Try to compare against formset class GUID
5666 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5667 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5668 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5669 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5670 ClassGuidMatch
= TRUE
;
5674 if (ClassGuidMatch
) {
5677 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5678 ClassGuidMatch
= TRUE
;
5683 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5686 if (Offset2
< PackageHeader
.Length
) {
5688 // Target formset found
5694 Offset
+= PackageHeader
.Length
;
5697 if (Offset
>= PackageListLength
) {
5699 // Form package not found in this Package List
5701 FreePool (HiiPackageList
);
5702 return EFI_NOT_FOUND
;
5705 if (FormSetGuid
!= NULL
) {
5707 // Return the FormSet GUID
5709 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5713 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5714 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5715 // of the Form Package.
5717 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5718 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5720 FreePool (HiiPackageList
);
5722 if (*BinaryData
== NULL
) {
5723 return EFI_OUT_OF_RESOURCES
;
5731 Initialize the internal data structure of a FormSet.
5733 @param Handle PackageList Handle
5734 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5735 specified (NULL or zero GUID), take the first
5736 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5737 found in package list.
5738 On output, GUID of the formset found(if not NULL).
5739 @param FormSet FormSet data structure.
5741 @retval EFI_SUCCESS The function completed successfully.
5742 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5747 IN EFI_HII_HANDLE Handle
,
5748 IN OUT EFI_GUID
*FormSetGuid
,
5749 OUT FORM_BROWSER_FORMSET
*FormSet
5753 EFI_HANDLE DriverHandle
;
5755 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5756 if (EFI_ERROR (Status
)) {
5760 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5761 FormSet
->HiiHandle
= Handle
;
5762 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5763 FormSet
->QuestionInited
= FALSE
;
5766 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5768 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5769 if (EFI_ERROR (Status
)) {
5772 FormSet
->DriverHandle
= DriverHandle
;
5773 Status
= gBS
->HandleProtocol (
5775 &gEfiHiiConfigAccessProtocolGuid
,
5776 (VOID
**) &FormSet
->ConfigAccess
5778 if (EFI_ERROR (Status
)) {
5780 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5781 // list, then there will be no configuration action required
5783 FormSet
->ConfigAccess
= NULL
;
5787 // Parse the IFR binary OpCodes
5789 Status
= ParseOpCodes (FormSet
);
5796 Save globals used by previous call to SendForm(). SendForm() may be called from
5797 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5798 So, save globals of previous call to SendForm() and restore them upon exit.
5802 SaveBrowserContext (
5806 BROWSER_CONTEXT
*Context
;
5807 FORM_ENTRY_INFO
*MenuList
;
5808 FORM_BROWSER_FORMSET
*FormSet
;
5810 gBrowserContextCount
++;
5811 if (gBrowserContextCount
== 1) {
5813 // This is not reentry of SendForm(), no context to save
5818 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5819 ASSERT (Context
!= NULL
);
5821 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5824 // Save FormBrowser context
5826 Context
->Selection
= gCurrentSelection
;
5827 Context
->ResetRequired
= gResetRequired
;
5828 Context
->FlagReconnect
= gFlagReconnect
;
5829 Context
->CallbackReconnect
= gCallbackReconnect
;
5830 Context
->ExitRequired
= gExitRequired
;
5831 Context
->HiiHandle
= mCurrentHiiHandle
;
5832 Context
->FormId
= mCurrentFormId
;
5833 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5834 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
5835 Context
->CurFakeQestId
= mCurFakeQestId
;
5836 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
5837 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
5840 // Save the menu history data.
5842 InitializeListHead(&Context
->FormHistoryList
);
5843 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5844 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5845 RemoveEntryList (&MenuList
->Link
);
5847 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5851 // Save formset list.
5853 InitializeListHead(&Context
->FormSetList
);
5854 while (!IsListEmpty (&gBrowserFormSetList
)) {
5855 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
5856 RemoveEntryList (&FormSet
->Link
);
5858 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
5862 // Insert to FormBrowser context list
5864 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5869 Restore globals used by previous call to SendForm().
5873 RestoreBrowserContext (
5878 BROWSER_CONTEXT
*Context
;
5879 FORM_ENTRY_INFO
*MenuList
;
5880 FORM_BROWSER_FORMSET
*FormSet
;
5882 ASSERT (gBrowserContextCount
!= 0);
5883 gBrowserContextCount
--;
5884 if (gBrowserContextCount
== 0) {
5886 // This is not reentry of SendForm(), no context to restore
5891 ASSERT (!IsListEmpty (&gBrowserContextList
));
5893 Link
= GetFirstNode (&gBrowserContextList
);
5894 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5897 // Restore FormBrowser context
5899 gCurrentSelection
= Context
->Selection
;
5900 gResetRequired
= Context
->ResetRequired
;
5901 gFlagReconnect
= Context
->FlagReconnect
;
5902 gCallbackReconnect
= Context
->CallbackReconnect
;
5903 gExitRequired
= Context
->ExitRequired
;
5904 mCurrentHiiHandle
= Context
->HiiHandle
;
5905 mCurrentFormId
= Context
->FormId
;
5906 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5907 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
5908 mCurFakeQestId
= Context
->CurFakeQestId
;
5909 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
5910 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
5913 // Restore the menu history data.
5915 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5916 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5917 RemoveEntryList (&MenuList
->Link
);
5919 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5923 // Restore the Formset data.
5925 while (!IsListEmpty (&Context
->FormSetList
)) {
5926 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
5927 RemoveEntryList (&FormSet
->Link
);
5929 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
5933 // Remove from FormBrowser context list
5935 RemoveEntryList (&Context
->Link
);
5936 gBS
->FreePool (Context
);
5940 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5942 @param Handle The Hii Handle.
5944 @return the found FormSet context. If no found, NULL will return.
5947 FORM_BROWSER_FORMSET
*
5948 GetFormSetFromHiiHandle (
5949 EFI_HII_HANDLE Handle
5953 FORM_BROWSER_FORMSET
*FormSet
;
5955 Link
= GetFirstNode (&gBrowserFormSetList
);
5956 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5957 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5958 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5959 if (!ValidateFormSet(FormSet
)) {
5962 if (FormSet
->HiiHandle
== Handle
) {
5971 Check whether the input HII handle is the FormSet that is being used.
5973 @param Handle The Hii Handle.
5975 @retval TRUE HII handle is being used.
5976 @retval FALSE HII handle is not being used.
5980 IsHiiHandleInBrowserContext (
5981 EFI_HII_HANDLE Handle
5985 BROWSER_CONTEXT
*Context
;
5988 // HiiHandle is Current FormSet.
5990 if (mCurrentHiiHandle
== Handle
) {
5995 // Check whether HiiHandle is in BrowserContext.
5997 Link
= GetFirstNode (&gBrowserContextList
);
5998 while (!IsNull (&gBrowserContextList
, Link
)) {
5999 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6000 if (Context
->HiiHandle
== Handle
) {
6002 // HiiHandle is in BrowserContext
6006 Link
= GetNextNode (&gBrowserContextList
, Link
);
6013 Perform Password check.
6014 Passwork may be encrypted by driver that requires the specific check.
6016 @param Form Form where Password Statement is in.
6017 @param Statement Password statement
6018 @param PasswordString Password string to be checked. It may be NULL.
6019 NULL means to restore password.
6020 "" string can be used to checked whether old password does exist.
6022 @return Status Status of Password check.
6027 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6028 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6029 IN EFI_STRING PasswordString OPTIONAL
6033 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6034 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6035 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6036 FORM_BROWSER_STATEMENT
*Question
;
6038 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6039 Question
= GetBrowserStatement(Statement
);
6040 ASSERT (Question
!= NULL
);
6042 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6043 if (ConfigAccess
== NULL
) {
6044 return EFI_UNSUPPORTED
;
6047 if (PasswordString
== NULL
) {
6052 // Check whether has preexisted password.
6054 if (PasswordString
[0] == 0) {
6055 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
6058 return EFI_NOT_READY
;
6063 // Check whether the input password is same as preexisted password.
6065 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
6068 return EFI_NOT_READY
;
6073 // Prepare password string in HII database
6075 if (PasswordString
!= NULL
) {
6076 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6078 IfrTypeValue
.string
= 0;
6082 // Send password to Configuration Driver for validation
6084 Status
= ConfigAccess
->Callback (
6086 EFI_BROWSER_ACTION_CHANGING
,
6087 Question
->QuestionId
,
6088 Question
->HiiValue
.Type
,
6094 // Remove password string from HII database
6096 if (PasswordString
!= NULL
) {
6097 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6104 Find the registered HotKey based on KeyData.
6106 @param[in] KeyData A pointer to a buffer that describes the keystroke
6107 information for the hot key.
6109 @return The registered HotKey context. If no found, NULL will return.
6112 GetHotKeyFromRegisterList (
6113 IN EFI_INPUT_KEY
*KeyData
6117 BROWSER_HOT_KEY
*HotKey
;
6119 Link
= GetFirstNode (&gBrowserHotKeyList
);
6120 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6121 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6122 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6125 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6132 Configure what scope the hot key will impact.
6133 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6134 If no scope is set, the default scope will be FormSet level.
6135 After all registered hot keys are removed, previous Scope can reset to another level.
6137 @param[in] Scope Scope level to be set.
6139 @retval EFI_SUCCESS Scope is set correctly.
6140 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6141 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6147 IN BROWSER_SETTING_SCOPE Scope
6150 if (Scope
>= MaxLevel
) {
6151 return EFI_INVALID_PARAMETER
;
6155 // When no hot key registered in system or on the first setting,
6156 // Scope can be set.
6158 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6159 gBrowserSettingScope
= Scope
;
6160 mBrowserScopeFirstSet
= FALSE
;
6161 } else if (Scope
!= gBrowserSettingScope
) {
6162 return EFI_UNSUPPORTED
;
6169 Register the hot key with its browser action, or unregistered the hot key.
6170 Only support hot key that is not printable character (control key, function key, etc.).
6171 If the action value is zero, the hot key will be unregistered if it has been registered.
6172 If the same hot key has been registered, the new action and help string will override the previous ones.
6174 @param[in] KeyData A pointer to a buffer that describes the keystroke
6175 information for the hot key. Its type is EFI_INPUT_KEY to
6176 be supported by all ConsoleIn devices.
6177 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6178 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6179 @param[in] HelpString Help string that describes the hot key information.
6180 Its value may be NULL for the unregistered hot key.
6182 @retval EFI_SUCCESS Hot key is registered or unregistered.
6183 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6184 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6185 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6186 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6191 IN EFI_INPUT_KEY
*KeyData
,
6193 IN UINT16 DefaultId
,
6194 IN EFI_STRING HelpString OPTIONAL
6197 BROWSER_HOT_KEY
*HotKey
;
6200 // Check input parameters.
6202 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6203 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6204 return EFI_INVALID_PARAMETER
;
6208 // Check whether the input KeyData is in BrowserHotKeyList.
6210 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6213 // Unregister HotKey
6215 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6216 if (HotKey
!= NULL
) {
6218 // The registered HotKey is found.
6219 // Remove it from List, and free its resource.
6221 RemoveEntryList (&HotKey
->Link
);
6222 FreePool (HotKey
->KeyData
);
6223 FreePool (HotKey
->HelpString
);
6227 // The registered HotKey is not found.
6229 return EFI_NOT_FOUND
;
6233 if (HotKey
!= NULL
) {
6234 return EFI_ALREADY_STARTED
;
6238 // Create new Key, and add it into List.
6240 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6241 ASSERT (HotKey
!= NULL
);
6242 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6243 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6244 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6247 // Fill HotKey information.
6249 HotKey
->Action
= Action
;
6250 HotKey
->DefaultId
= DefaultId
;
6251 if (HotKey
->HelpString
!= NULL
) {
6252 FreePool (HotKey
->HelpString
);
6254 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6260 Register Exit handler function.
6261 When more than one handler function is registered, the latter one will override the previous one.
6262 When NULL handler is specified, the previous Exit handler will be unregistered.
6264 @param[in] Handler Pointer to handler function.
6269 RegiserExitHandler (
6270 IN EXIT_HANDLER Handler
6273 ExitHandlerFunction
= Handler
;
6278 Check whether the browser data has been modified.
6280 @retval TRUE Browser data is modified.
6281 @retval FALSE No browser data is modified.
6286 IsBrowserDataModified (
6291 FORM_BROWSER_FORMSET
*FormSet
;
6293 switch (gBrowserSettingScope
) {
6295 if (gCurrentSelection
== NULL
) {
6298 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6301 if (gCurrentSelection
== NULL
) {
6304 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6307 Link
= GetFirstNode (&gBrowserFormSetList
);
6308 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6309 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6310 if (!ValidateFormSet(FormSet
)) {
6314 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6317 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6327 Execute the action requested by the Action parameter.
6329 @param[in] Action Execute the request action.
6330 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6332 @retval EFI_SUCCESS Execute the request action succss.
6333 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6344 FORM_BROWSER_FORMSET
*FormSet
;
6345 FORM_BROWSER_FORM
*Form
;
6347 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6348 return EFI_NOT_READY
;
6351 Status
= EFI_SUCCESS
;
6354 if (gBrowserSettingScope
< SystemLevel
) {
6355 FormSet
= gCurrentSelection
->FormSet
;
6356 Form
= gCurrentSelection
->Form
;
6360 // Executet the discard action.
6362 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6363 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6364 if (EFI_ERROR (Status
)) {
6370 // Executet the difault action.
6372 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6373 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6374 if (EFI_ERROR (Status
)) {
6377 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6381 // Executet the submit action.
6383 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6384 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6385 if (EFI_ERROR (Status
)) {
6391 // Executet the reset action.
6393 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6394 gResetRequired
= TRUE
;
6398 // Executet the exit action.
6400 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6401 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6402 if (gBrowserSettingScope
== SystemLevel
) {
6403 if (ExitHandlerFunction
!= NULL
) {
6404 ExitHandlerFunction ();
6408 gExitRequired
= TRUE
;
6415 Create reminder to let user to choose save or discard the changed browser data.
6416 Caller can use it to actively check the changed browser data.
6418 @retval BROWSER_NO_CHANGES No browser data is changed.
6419 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6420 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6421 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6431 FORM_BROWSER_FORMSET
*FormSet
;
6432 BOOLEAN IsDataChanged
;
6433 UINT32 DataSavedAction
;
6436 DataSavedAction
= BROWSER_NO_CHANGES
;
6437 IsDataChanged
= FALSE
;
6438 Link
= GetFirstNode (&gBrowserFormSetList
);
6439 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6440 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6441 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6442 if (!ValidateFormSet(FormSet
)) {
6445 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6446 IsDataChanged
= TRUE
;
6452 // No data is changed. No save is required.
6454 if (!IsDataChanged
) {
6455 return DataSavedAction
;
6459 // If data is changed, prompt user to save or discard it.
6462 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6464 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6465 SubmitForm (NULL
, NULL
, SystemLevel
);
6466 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6468 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6469 DiscardForm (NULL
, NULL
, SystemLevel
);
6470 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6472 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6473 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6478 return DataSavedAction
;
6482 Check whether the Reset Required for the browser
6484 @retval TRUE Browser required to reset after exit.
6485 @retval FALSE Browser not need to reset after exit.
6494 return gResetRequired
;