2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2015, 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 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
73 extern EFI_GUID mCurrentFormSetGuid
;
74 extern EFI_HII_HANDLE mCurrentHiiHandle
;
75 extern UINT16 mCurrentFormId
;
76 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
79 Create a menu with specified formset GUID and form ID, and add it as a child
80 of the given parent menu.
82 @param HiiHandle Hii handle related to this formset.
83 @param FormSetGuid The Formset Guid of menu to be added.
84 @param FormId The Form ID of menu to be added.
85 @param QuestionId The question id of this menu to be added.
87 @return A pointer to the newly added menu or NULL if memory is insufficient.
92 IN EFI_HII_HANDLE HiiHandle
,
93 IN EFI_GUID
*FormSetGuid
,
98 FORM_ENTRY_INFO
*MenuList
;
100 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
101 if (MenuList
== NULL
) {
105 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
107 MenuList
->HiiHandle
= HiiHandle
;
108 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
109 MenuList
->FormId
= FormId
;
110 MenuList
->QuestionId
= QuestionId
;
113 // If parent is not specified, it is the root Form of a Formset
115 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
121 Return the form id for the input hiihandle and formset.
123 @param HiiHandle HiiHandle for FormSet.
124 @param FormSetGuid The Formset GUID of the menu to search.
126 @return First form's id for this form set.
131 IN EFI_HII_HANDLE HiiHandle
,
132 IN EFI_GUID
*FormSetGuid
136 FORM_BROWSER_FORM
*Form
;
138 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
139 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
145 Search Menu with given FormSetGuid and FormId in all cached menu list.
147 @param HiiHandle HiiHandle for FormSet.
148 @param FormSetGuid The Formset GUID of the menu to search.
149 @param FormId The Form ID of menu to search.
151 @return A pointer to menu found or NULL if not found.
156 IN EFI_HII_HANDLE HiiHandle
,
157 IN EFI_GUID
*FormSetGuid
,
162 FORM_ENTRY_INFO
*MenuList
;
163 FORM_ENTRY_INFO
*RetMenu
;
164 EFI_FORM_ID FirstFormId
;
168 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
169 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
170 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
171 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
174 // If already find the menu, free the menus behind it.
176 if (RetMenu
!= NULL
) {
177 RemoveEntryList (&MenuList
->Link
);
183 // Find the same FromSet.
185 if (MenuList
->HiiHandle
== HiiHandle
) {
186 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
188 // FormSetGuid is not specified.
191 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
192 if (MenuList
->FormId
== FormId
) {
194 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
195 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
196 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
208 Find parent menu for current menu.
210 @param CurrentMenu Current Menu
211 @param SettingLevel Whether find parent menu in Form Level or Formset level.
212 In form level, just find the parent menu;
213 In formset level, find the parent menu which has different
216 @retval The parent menu for current menu.
220 IN FORM_ENTRY_INFO
*CurrentMenu
,
221 IN BROWSER_SETTING_SCOPE SettingLevel
224 FORM_ENTRY_INFO
*ParentMenu
;
227 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
229 if (CurrentMenu
== NULL
) {
234 Link
= &CurrentMenu
->Link
;
236 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
237 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
239 if (SettingLevel
== FormLevel
) {
241 // For FormLevel, just find the parent menu, return.
246 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
248 // For SystemLevel, must find the menu which has different formset.
253 Link
= Link
->BackLink
;
257 // Not find the parent menu, just return NULL.
259 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
267 Free Menu list linked list.
269 @param MenuListHead One Menu list point in the menu list.
274 LIST_ENTRY
*MenuListHead
277 FORM_ENTRY_INFO
*MenuList
;
279 while (!IsListEmpty (MenuListHead
)) {
280 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
281 RemoveEntryList (&MenuList
->Link
);
288 Copy current Menu list to the new menu list.
290 @param NewMenuListHead New create Menu list.
291 @param CurrentMenuListHead Current Menu list.
296 OUT LIST_ENTRY
*NewMenuListHead
,
297 IN LIST_ENTRY
*CurrentMenuListHead
301 FORM_ENTRY_INFO
*MenuList
;
302 FORM_ENTRY_INFO
*NewMenuEntry
;
305 // If new menu list not empty, free it first.
307 UiFreeMenuList (NewMenuListHead
);
309 Link
= GetFirstNode (CurrentMenuListHead
);
310 while (!IsNull (CurrentMenuListHead
, Link
)) {
311 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
312 Link
= GetNextNode (CurrentMenuListHead
, Link
);
314 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
315 ASSERT (NewMenuEntry
!= NULL
);
316 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
317 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
318 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
319 NewMenuEntry
->FormId
= MenuList
->FormId
;
320 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
322 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
327 Load all hii formset to the browser.
335 FORM_BROWSER_FORMSET
*LocalFormSet
;
336 EFI_HII_HANDLE
*HiiHandles
;
340 FORM_BROWSER_FORMSET
*OldFormset
;
342 OldFormset
= mSystemLevelFormSet
;
345 // Get all the Hii handles
347 HiiHandles
= HiiGetHiiHandles (NULL
);
348 ASSERT (HiiHandles
!= NULL
);
351 // Search for formset of each class type
353 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
355 // Check HiiHandles[Index] does exist in global maintain list.
357 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
362 // Initilize FormSet Setting
364 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
365 ASSERT (LocalFormSet
!= NULL
);
366 mSystemLevelFormSet
= LocalFormSet
;
368 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
369 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
370 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
371 DestroyFormSet (LocalFormSet
);
374 InitializeCurrentSetting (LocalFormSet
);
377 // Initilize Questions' Value
379 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
380 if (EFI_ERROR (Status
)) {
381 DestroyFormSet (LocalFormSet
);
387 // Free resources, and restore gOldFormSet and gClassOfVfr
389 FreePool (HiiHandles
);
391 mSystemLevelFormSet
= OldFormset
;
395 Pop up the error info.
397 @param BrowserStatus The input browser status.
398 @param HiiHandle The Hiihandle for this opcode.
399 @param OpCode The opcode use to get the erro info and timeout value.
400 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
405 IN UINT32 BrowserStatus
,
406 IN EFI_HII_HANDLE HiiHandle
,
407 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
408 IN CHAR16
*ErrorString
411 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
412 USER_INPUT UserInputData
;
416 if (OpCode
!= NULL
) {
417 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
418 ASSERT (Statement
!= NULL
);
419 Statement
->OpCode
= OpCode
;
420 gDisplayFormData
.HighLightedStatement
= Statement
;
424 // Used to compatible with old display engine.
425 // New display engine not use this field.
427 gDisplayFormData
.ErrorString
= ErrorString
;
428 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
430 if (HiiHandle
!= NULL
) {
431 gDisplayFormData
.HiiHandle
= HiiHandle
;
434 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
436 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
437 gDisplayFormData
.ErrorString
= NULL
;
439 if (OpCode
!= NULL
) {
440 FreePool (Statement
);
443 return UserInputData
.Action
;
447 This is the routine which an external caller uses to direct the browser
448 where to obtain it's information.
451 @param This The Form Browser protocol instanse.
452 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
453 display a list of the formsets for the handles specified.
454 @param HandleCount The number of Handles specified in Handle.
455 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
456 field in the EFI_IFR_FORM_SET op-code for the specified
457 forms-based package. If FormSetGuid is NULL, then this
458 function will display the first found forms package.
459 @param FormId This field specifies which EFI_IFR_FORM to render as the first
460 displayable page. If this field has a value of 0x0000, then
461 the forms browser will render the specified forms in their encoded order.
462 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
464 @param ActionRequest Points to the action recommended by the form.
466 @retval EFI_SUCCESS The function completed successfully.
467 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
468 @retval EFI_NOT_FOUND No valid forms could be found to display.
474 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
475 IN EFI_HII_HANDLE
*Handles
,
476 IN UINTN HandleCount
,
477 IN EFI_GUID
*FormSetGuid
, OPTIONAL
478 IN UINT16 FormId
, OPTIONAL
479 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
480 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
484 UI_MENU_SELECTION
*Selection
;
486 FORM_BROWSER_FORMSET
*FormSet
;
487 FORM_ENTRY_INFO
*MenuList
;
491 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
493 if (mFormDisplay
== NULL
) {
494 return EFI_UNSUPPORTED
;
498 // Save globals used by SendForm()
500 SaveBrowserContext ();
502 gFlagReconnect
= FALSE
;
503 gResetRequired
= FALSE
;
504 gExitRequired
= FALSE
;
505 gCallbackReconnect
= FALSE
;
506 Status
= EFI_SUCCESS
;
508 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
510 for (Index
= 0; Index
< HandleCount
; Index
++) {
511 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
512 ASSERT (Selection
!= NULL
);
514 Selection
->Handle
= Handles
[Index
];
515 if (FormSetGuid
!= NULL
) {
516 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
517 Selection
->FormId
= FormId
;
519 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
523 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
524 ASSERT (FormSet
!= NULL
);
527 // Validate the HiiHandle
528 // if validate failed, find the first validate parent HiiHandle.
530 if (!ValidateHiiHandle(Selection
->Handle
)) {
531 FindNextMenu (Selection
, FormSetLevel
);
535 // Initialize internal data structures of FormSet
537 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
538 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
539 DestroyFormSet (FormSet
);
542 Selection
->FormSet
= FormSet
;
543 mSystemLevelFormSet
= FormSet
;
546 // Display this formset
548 gCurrentSelection
= Selection
;
550 Status
= SetupBrowser (Selection
);
552 gCurrentSelection
= NULL
;
553 mSystemLevelFormSet
= NULL
;
555 if (gFlagReconnect
|| gCallbackReconnect
) {
556 RetVal
= ReconnectController (FormSet
->DriverHandle
);
558 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
560 gFlagReconnect
= FALSE
;
561 gCallbackReconnect
= FALSE
;
565 // If no data is changed, don't need to save current FormSet into the maintain list.
567 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
568 CleanBrowserStorage(FormSet
);
569 RemoveEntryList (&FormSet
->Link
);
570 DestroyFormSet (FormSet
);
573 if (EFI_ERROR (Status
)) {
576 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
578 FreePool (Selection
);
581 if (ActionRequest
!= NULL
) {
582 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
583 if (gResetRequired
) {
584 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
588 mFormDisplay
->ExitDisplay();
591 // Clear the menu history data.
593 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
594 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
595 RemoveEntryList (&MenuList
->Link
);
600 // Restore globals used by SendForm()
602 RestoreBrowserContext ();
608 Get or set data to the storage.
610 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
611 @param ResultsData A string returned from an IFR browser or
612 equivalent. The results string will have no
613 routing information in them.
614 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
615 (if RetrieveData = TRUE) data from the uncommitted
616 browser state information or set (if RetrieveData
617 = FALSE) data in the uncommitted browser state
619 @param Storage The pointer to the storage.
621 @retval EFI_SUCCESS The results have been distributed or are awaiting
627 IN OUT UINTN
*ResultsDataSize
,
628 IN OUT EFI_STRING
*ResultsData
,
629 IN BOOLEAN RetrieveData
,
630 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 StrCpy (*ResultsData
, 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 ConfigResp
= AllocateZeroPool (BufferSize
);
677 ASSERT (ConfigResp
!= NULL
);
679 StrCpy (ConfigResp
, BrowserStorage
->ConfigHdr
);
680 StrCat (ConfigResp
, L
"&");
681 StrCat (ConfigResp
, *ResultsData
);
684 // Update Browser uncommited data
686 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
687 FreePool (ConfigResp
);
688 if (EFI_ERROR (Status
)) {
697 This routine called this service in the browser to retrieve or set certain uncommitted
698 state information that resides in the open formsets.
700 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
702 @param ResultsDataSize A pointer to the size of the buffer associated
704 @param ResultsData A string returned from an IFR browser or
705 equivalent. The results string will have no
706 routing information in them.
707 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
708 (if RetrieveData = TRUE) data from the uncommitted
709 browser state information or set (if RetrieveData
710 = FALSE) data in the uncommitted browser state
712 @param VariableGuid An optional field to indicate the target variable
714 @param VariableName An optional field to indicate the target
715 human-readable variable name.
717 @retval EFI_SUCCESS The results have been distributed or are awaiting
719 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
720 contain the results data.
726 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
727 IN OUT UINTN
*ResultsDataSize
,
728 IN OUT EFI_STRING ResultsData
,
729 IN BOOLEAN RetrieveData
,
730 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
731 IN CONST CHAR16
*VariableName OPTIONAL
736 BROWSER_STORAGE
*Storage
;
737 FORMSET_STORAGE
*FormsetStorage
;
741 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
742 return EFI_INVALID_PARAMETER
;
745 TotalSize
= *ResultsDataSize
;
748 Status
= EFI_SUCCESS
;
750 if (VariableGuid
!= NULL
) {
752 // Try to find target storage in the current formset.
754 Link
= GetFirstNode (&gBrowserStorageList
);
755 while (!IsNull (&gBrowserStorageList
, Link
)) {
756 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
757 Link
= GetNextNode (&gBrowserStorageList
, Link
);
759 // Check the current storage.
761 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
765 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
766 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
768 // Buffer storage require both GUID and Name
770 if (VariableName
== NULL
) {
771 return EFI_NOT_FOUND
;
774 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
779 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
780 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
781 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
782 return EFI_NOT_FOUND
;
785 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
790 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
791 if (EFI_ERROR (Status
)) {
795 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
796 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
800 // Different formsets may have same varstore, so here just set the flag
801 // not exit the circle.
808 return EFI_NOT_FOUND
;
812 // GUID/Name is not specified, take the first storage in FormSet
814 if (mSystemLevelFormSet
== NULL
) {
815 return EFI_NOT_READY
;
819 // Generate <ConfigResp>
821 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
822 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
823 return EFI_UNSUPPORTED
;
826 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
828 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
829 if (EFI_ERROR (Status
)) {
835 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
836 *ResultsDataSize
= TotalSize
;
845 Callback function for SimpleTextInEx protocol install events
847 @param Event the event that is signaled.
848 @param Context not used here.
853 FormDisplayCallback (
858 if (mFormDisplay
!= NULL
) {
862 gBS
->LocateProtocol (
863 &gEdkiiFormDisplayEngineProtocolGuid
,
865 (VOID
**) &mFormDisplay
870 Initialize Setup Browser driver.
872 @param ImageHandle The image handle.
873 @param SystemTable The system table.
875 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
876 @return Other value if failed to initialize the Setup Browser module.
882 IN EFI_HANDLE ImageHandle
,
883 IN EFI_SYSTEM_TABLE
*SystemTable
890 // Locate required Hii relative protocols
892 Status
= gBS
->LocateProtocol (
893 &gEfiHiiDatabaseProtocolGuid
,
895 (VOID
**) &mHiiDatabase
897 ASSERT_EFI_ERROR (Status
);
899 Status
= gBS
->LocateProtocol (
900 &gEfiHiiConfigRoutingProtocolGuid
,
902 (VOID
**) &mHiiConfigRouting
904 ASSERT_EFI_ERROR (Status
);
906 Status
= gBS
->LocateProtocol (
907 &gEfiDevicePathFromTextProtocolGuid
,
909 (VOID
**) &mPathFromText
913 // Install FormBrowser2 protocol
915 mPrivateData
.Handle
= NULL
;
916 Status
= gBS
->InstallProtocolInterface (
917 &mPrivateData
.Handle
,
918 &gEfiFormBrowser2ProtocolGuid
,
919 EFI_NATIVE_INTERFACE
,
920 &mPrivateData
.FormBrowser2
922 ASSERT_EFI_ERROR (Status
);
925 // Install FormBrowserEx2 protocol
927 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
928 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
929 mPrivateData
.Handle
= NULL
;
930 Status
= gBS
->InstallProtocolInterface (
931 &mPrivateData
.Handle
,
932 &gEdkiiFormBrowserEx2ProtocolGuid
,
933 EFI_NATIVE_INTERFACE
,
934 &mPrivateData
.FormBrowserEx2
936 ASSERT_EFI_ERROR (Status
);
938 Status
= gBS
->InstallProtocolInterface (
939 &mPrivateData
.Handle
,
940 &gEfiFormBrowserExProtocolGuid
,
941 EFI_NATIVE_INTERFACE
,
942 &mPrivateData
.FormBrowserEx
944 ASSERT_EFI_ERROR (Status
);
946 InitializeDisplayFormData ();
948 Status
= gBS
->LocateProtocol (
949 &gEdkiiFormDisplayEngineProtocolGuid
,
951 (VOID
**) &mFormDisplay
954 if (EFI_ERROR (Status
)) {
955 EfiCreateProtocolNotifyEvent (
956 &gEdkiiFormDisplayEngineProtocolGuid
,
969 Create a new string in HII Package List.
971 @param String The String to be added
972 @param HiiHandle The package list in the HII database to insert the
975 @return The output string.
981 IN EFI_HII_HANDLE HiiHandle
984 EFI_STRING_ID StringId
;
986 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
987 ASSERT (StringId
!= 0);
994 Delete a string from HII Package List.
996 @param StringId Id of the string in HII database.
997 @param HiiHandle The HII package list handle.
999 @retval EFI_SUCCESS The string was deleted successfully.
1004 IN EFI_STRING_ID StringId
,
1005 IN EFI_HII_HANDLE HiiHandle
1010 NullChar
= CHAR_NULL
;
1011 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1017 Get the string based on the StringId and HII Package List Handle.
1019 @param Token The String's ID.
1020 @param HiiHandle The package list in the HII database to search for
1021 the specified string.
1023 @return The output string.
1028 IN EFI_STRING_ID Token
,
1029 IN EFI_HII_HANDLE HiiHandle
1034 if (HiiHandle
== NULL
) {
1038 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1039 if (String
== NULL
) {
1040 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1041 ASSERT (String
!= NULL
);
1043 return (CHAR16
*) String
;
1048 Allocate new memory and then copy the Unicode string Source to Destination.
1050 @param Dest Location to copy string
1051 @param Src String to copy
1056 IN OUT CHAR16
**Dest
,
1060 if (*Dest
!= NULL
) {
1063 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1064 ASSERT (*Dest
!= NULL
);
1069 Allocate new memory and concatinate Source on the end of Destination.
1071 @param Dest String to added to the end of.
1072 @param Src String to concatinate.
1077 IN OUT CHAR16
**Dest
,
1084 if (*Dest
== NULL
) {
1085 NewStringCpy (Dest
, Src
);
1089 TmpSize
= StrSize (*Dest
);
1090 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1091 ASSERT (NewString
!= NULL
);
1093 StrCpy (NewString
, *Dest
);
1094 StrCat (NewString
, Src
);
1101 Get Value for given Name from a NameValue Storage.
1103 @param Storage The NameValue Storage.
1104 @param Name The Name.
1105 @param Value The retured Value.
1106 @param GetValueFrom Where to get source value, from EditValue or Value.
1108 @retval EFI_SUCCESS Value found for given Name.
1109 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1114 IN BROWSER_STORAGE
*Storage
,
1116 IN OUT CHAR16
**Value
,
1117 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1121 NAME_VALUE_NODE
*Node
;
1123 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1124 return EFI_INVALID_PARAMETER
;
1129 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1130 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1131 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1133 if (StrCmp (Name
, Node
->Name
) == 0) {
1134 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1135 NewStringCpy (Value
, Node
->EditValue
);
1137 NewStringCpy (Value
, Node
->Value
);
1142 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1145 return EFI_NOT_FOUND
;
1150 Set Value of given Name in a NameValue Storage.
1152 @param Storage The NameValue Storage.
1153 @param Name The Name.
1154 @param Value The Value to set.
1155 @param SetValueTo Whether update editValue or Value.
1156 @param ReturnNode The node use the input name.
1158 @retval EFI_SUCCESS Value found for given Name.
1159 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1164 IN BROWSER_STORAGE
*Storage
,
1167 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1168 OUT NAME_VALUE_NODE
**ReturnNode
1172 NAME_VALUE_NODE
*Node
;
1175 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1176 return EFI_INVALID_PARAMETER
;
1179 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1180 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1181 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1183 if (StrCmp (Name
, Node
->Name
) == 0) {
1184 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1185 Buffer
= Node
->EditValue
;
1187 Buffer
= Node
->Value
;
1189 if (Buffer
!= NULL
) {
1192 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1193 ASSERT (Buffer
!= NULL
);
1194 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1195 Node
->EditValue
= Buffer
;
1197 Node
->Value
= Buffer
;
1200 if (ReturnNode
!= NULL
) {
1207 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1210 return EFI_NOT_FOUND
;
1215 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1217 @param Storage The Storage to be conveted.
1218 @param ConfigResp The returned <ConfigResp>.
1219 @param ConfigRequest The ConfigRequest string.
1220 @param GetEditBuf Get the data from editbuffer or buffer.
1222 @retval EFI_SUCCESS Convert success.
1223 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1227 StorageToConfigResp (
1228 IN BROWSER_STORAGE
*Storage
,
1229 IN CHAR16
**ConfigResp
,
1230 IN CHAR16
*ConfigRequest
,
1231 IN BOOLEAN GetEditBuf
1235 EFI_STRING Progress
;
1237 NAME_VALUE_NODE
*Node
;
1239 FORMSET_STORAGE
*FormsetStorage
;
1241 Status
= EFI_SUCCESS
;
1243 switch (Storage
->Type
) {
1244 case EFI_HII_VARSTORE_BUFFER
:
1245 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1246 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1247 Status
= mHiiConfigRouting
->BlockToConfig (
1257 case EFI_HII_VARSTORE_NAME_VALUE
:
1259 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1260 ASSERT (FormsetStorage
!= NULL
);
1261 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1263 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1264 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1265 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1267 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1268 NewStringCat (ConfigResp
, L
"&");
1269 NewStringCat (ConfigResp
, Node
->Name
);
1270 NewStringCat (ConfigResp
, L
"=");
1272 NewStringCat (ConfigResp
, Node
->EditValue
);
1274 NewStringCat (ConfigResp
, Node
->Value
);
1277 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1281 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1283 Status
= EFI_INVALID_PARAMETER
;
1292 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1294 @param Storage The Storage to receive the settings.
1295 @param ConfigResp The <ConfigResp> to be converted.
1297 @retval EFI_SUCCESS Convert success.
1298 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1302 ConfigRespToStorage (
1303 IN BROWSER_STORAGE
*Storage
,
1304 IN CHAR16
*ConfigResp
1308 EFI_STRING Progress
;
1314 Status
= EFI_SUCCESS
;
1316 switch (Storage
->Type
) {
1317 case EFI_HII_VARSTORE_BUFFER
:
1318 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1319 BufferSize
= Storage
->Size
;
1320 Status
= mHiiConfigRouting
->ConfigToBlock (
1323 Storage
->EditBuffer
,
1329 case EFI_HII_VARSTORE_NAME_VALUE
:
1330 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1331 if (StrPtr
== NULL
) {
1334 StrPtr
= StrStr (ConfigResp
, L
"&");
1335 while (StrPtr
!= NULL
) {
1339 StrPtr
= StrPtr
+ 1;
1341 StrPtr
= StrStr (StrPtr
, L
"=");
1342 if (StrPtr
== NULL
) {
1350 StrPtr
= StrPtr
+ 1;
1352 StrPtr
= StrStr (StrPtr
, L
"&");
1353 if (StrPtr
!= NULL
) {
1356 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1360 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1362 Status
= EFI_INVALID_PARAMETER
;
1370 Convert the buffer value to HiiValue.
1372 @param Question The question.
1373 @param Value Unicode buffer save the question value.
1375 @retval Status whether convert the value success.
1380 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1385 BOOLEAN IsBufferStorage
;
1397 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1398 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1399 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1400 IsBufferStorage
= TRUE
;
1402 IsBufferStorage
= FALSE
;
1406 // Question Value is provided by Buffer Storage or NameValue Storage
1408 if (Question
->BufferValue
!= NULL
) {
1410 // This Question is password or orderedlist
1412 Dst
= Question
->BufferValue
;
1415 // Other type of Questions
1417 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1421 // Temp cut at the end of this section, end with '\0' or '&'.
1424 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1427 TempChar
= *StringPtr
;
1430 LengthStr
= StrLen (Value
);
1431 Status
= EFI_SUCCESS
;
1432 if (!IsBufferStorage
&& IsString
) {
1434 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1435 // Add string tail char L'\0' into Length
1437 Length
= Question
->StorageWidth
+ sizeof (CHAR16
);
1438 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1439 Status
= EFI_BUFFER_TOO_SMALL
;
1441 DstBuf
= (CHAR16
*) Dst
;
1442 ZeroMem (TemStr
, sizeof (TemStr
));
1443 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1444 StrnCpy (TemStr
, Value
+ Index
, 4);
1445 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1448 // Add tailing L'\0' character
1450 DstBuf
[Index
/4] = L
'\0';
1453 if (Question
->StorageWidth
< ((LengthStr
+ 1) / 2)) {
1454 Status
= EFI_BUFFER_TOO_SMALL
;
1456 ZeroMem (TemStr
, sizeof (TemStr
));
1457 for (Index
= 0; Index
< LengthStr
; Index
++) {
1458 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1459 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1460 if ((Index
& 1) == 0) {
1461 Dst
[Index
/2] = DigitUint8
;
1463 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1469 *StringPtr
= TempChar
;
1475 Get Question's current Value.
1477 @param FormSet FormSet data structure.
1478 @param Form Form data structure.
1479 @param Question Question to be initialized.
1480 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1482 @retval EFI_SUCCESS The function completed successfully.
1487 IN FORM_BROWSER_FORMSET
*FormSet
,
1488 IN FORM_BROWSER_FORM
*Form
,
1489 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1490 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1499 BROWSER_STORAGE
*Storage
;
1500 FORMSET_STORAGE
*FormsetStorage
;
1501 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1502 CHAR16
*ConfigRequest
;
1507 BOOLEAN IsBufferStorage
;
1509 Status
= EFI_SUCCESS
;
1513 if (GetValueFrom
>= GetSetValueWithMax
) {
1514 return EFI_INVALID_PARAMETER
;
1518 // Question value is provided by an Expression, evaluate it
1520 if (Question
->ValueExpression
!= NULL
) {
1521 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1522 if (!EFI_ERROR (Status
)) {
1523 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1524 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1525 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1526 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1527 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1529 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1530 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1532 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1534 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1535 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1541 // Get question value by read expression.
1543 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1544 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1545 if (!EFI_ERROR (Status
) &&
1546 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1548 // Only update question value to the valid result.
1550 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1551 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1552 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1553 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1554 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1556 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1557 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1559 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1561 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1562 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1568 // Question value is provided by RTC
1570 Storage
= Question
->Storage
;
1571 QuestionValue
= &Question
->HiiValue
.Value
;
1572 if (Storage
== NULL
) {
1574 // It's a Question without storage, or RTC date/time
1576 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1578 // Date and time define the same Flags bit
1580 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1581 case QF_DATE_STORAGE_TIME
:
1582 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1585 case QF_DATE_STORAGE_WAKEUP
:
1586 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1589 case QF_DATE_STORAGE_NORMAL
:
1592 // For date/time without storage
1597 if (EFI_ERROR (Status
)) {
1601 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1602 QuestionValue
->date
.Year
= EfiTime
.Year
;
1603 QuestionValue
->date
.Month
= EfiTime
.Month
;
1604 QuestionValue
->date
.Day
= EfiTime
.Day
;
1606 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1607 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1608 QuestionValue
->time
.Second
= EfiTime
.Second
;
1616 // Question value is provided by EFI variable
1618 StorageWidth
= Question
->StorageWidth
;
1619 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1620 if (Question
->BufferValue
!= NULL
) {
1621 Dst
= Question
->BufferValue
;
1623 Dst
= (UINT8
*) QuestionValue
;
1626 Status
= gRT
->GetVariable (
1627 Question
->VariableName
,
1634 // Always return success, even this EFI variable doesn't exist
1640 // Question Value is provided by Buffer Storage or NameValue Storage
1642 if (Question
->BufferValue
!= NULL
) {
1644 // This Question is password or orderedlist
1646 Dst
= Question
->BufferValue
;
1649 // Other type of Questions
1651 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1654 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1655 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1656 IsBufferStorage
= TRUE
;
1658 IsBufferStorage
= FALSE
;
1660 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1661 if (IsBufferStorage
) {
1662 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1664 // Copy from storage Edit buffer
1666 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1669 // Copy from storage Edit buffer
1671 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1675 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1676 if (EFI_ERROR (Status
)) {
1680 ASSERT (Value
!= NULL
);
1681 Status
= BufferToValue (Question
, Value
);
1685 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1686 ASSERT (FormsetStorage
!= NULL
);
1688 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1689 // <ConfigHdr> + "&" + <VariableName>
1691 if (IsBufferStorage
) {
1692 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1693 Length
+= StrLen (Question
->BlockName
);
1695 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1696 Length
+= StrLen (Question
->VariableName
) + 1;
1698 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1699 ASSERT (ConfigRequest
!= NULL
);
1701 StrCpy (ConfigRequest
, FormsetStorage
->ConfigHdr
);
1702 if (IsBufferStorage
) {
1703 StrCat (ConfigRequest
, Question
->BlockName
);
1705 StrCat (ConfigRequest
, L
"&");
1706 StrCat (ConfigRequest
, Question
->VariableName
);
1710 // Request current settings from Configuration Driver
1712 Status
= mHiiConfigRouting
->ExtractConfig (
1718 FreePool (ConfigRequest
);
1719 if (EFI_ERROR (Status
)) {
1724 // Skip <ConfigRequest>
1726 if (IsBufferStorage
) {
1727 Value
= StrStr (Result
, L
"&VALUE");
1728 if (Value
== NULL
) {
1730 return EFI_NOT_FOUND
;
1737 Value
= Result
+ Length
;
1739 if (*Value
!= '=') {
1741 return EFI_NOT_FOUND
;
1744 // Skip '=', point to value
1748 Status
= BufferToValue (Question
, Value
);
1749 if (EFI_ERROR (Status
)) {
1755 // Synchronize Edit Buffer
1757 if (IsBufferStorage
) {
1758 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1760 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1763 if (Result
!= NULL
) {
1773 Save Question Value to edit copy(cached) or Storage(uncached).
1775 @param FormSet FormSet data structure.
1776 @param Form Form data structure.
1777 @param Question Pointer to the Question.
1778 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1780 @retval EFI_SUCCESS The function completed successfully.
1785 IN FORM_BROWSER_FORMSET
*FormSet
,
1786 IN FORM_BROWSER_FORM
*Form
,
1787 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1788 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1798 BROWSER_STORAGE
*Storage
;
1799 FORMSET_STORAGE
*FormsetStorage
;
1800 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1805 BOOLEAN IsBufferStorage
;
1811 NAME_VALUE_NODE
*Node
;
1813 Status
= EFI_SUCCESS
;
1816 if (SetValueTo
>= GetSetValueWithMax
) {
1817 return EFI_INVALID_PARAMETER
;
1821 // If Question value is provided by an Expression, then it is read only
1823 if (Question
->ValueExpression
!= NULL
) {
1828 // Before set question value, evaluate its write expression.
1830 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1831 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1832 if (EFI_ERROR (Status
)) {
1838 // Question value is provided by RTC
1840 Storage
= Question
->Storage
;
1841 QuestionValue
= &Question
->HiiValue
.Value
;
1842 if (Storage
== NULL
) {
1844 // It's a Question without storage, or RTC date/time
1846 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1848 // Date and time define the same Flags bit
1850 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1851 case QF_DATE_STORAGE_TIME
:
1852 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1855 case QF_DATE_STORAGE_WAKEUP
:
1856 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1859 case QF_DATE_STORAGE_NORMAL
:
1862 // For date/time without storage
1867 if (EFI_ERROR (Status
)) {
1871 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1872 EfiTime
.Year
= QuestionValue
->date
.Year
;
1873 EfiTime
.Month
= QuestionValue
->date
.Month
;
1874 EfiTime
.Day
= QuestionValue
->date
.Day
;
1876 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1877 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1878 EfiTime
.Second
= QuestionValue
->time
.Second
;
1881 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1882 Status
= gRT
->SetTime (&EfiTime
);
1884 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1892 // Question value is provided by EFI variable
1894 StorageWidth
= Question
->StorageWidth
;
1895 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1896 if (Question
->BufferValue
!= NULL
) {
1897 Src
= Question
->BufferValue
;
1899 Src
= (UINT8
*) QuestionValue
;
1902 Status
= gRT
->SetVariable (
1903 Question
->VariableName
,
1905 Storage
->Attributes
,
1913 // Question Value is provided by Buffer Storage or NameValue Storage
1915 if (Question
->BufferValue
!= NULL
) {
1916 Src
= Question
->BufferValue
;
1918 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1921 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1922 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1923 IsBufferStorage
= TRUE
;
1925 IsBufferStorage
= FALSE
;
1927 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1929 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1930 if (IsBufferStorage
) {
1931 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1933 // Copy to storage edit buffer
1935 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1936 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1938 // Copy to storage edit buffer
1940 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1945 // Allocate enough string buffer.
1948 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1949 Value
= AllocateZeroPool (BufferLen
);
1950 ASSERT (Value
!= NULL
);
1952 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1954 TemName
= (CHAR16
*) Src
;
1956 for (; *TemName
!= L
'\0'; TemName
++) {
1957 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1960 BufferLen
= StorageWidth
* 2 + 1;
1961 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1962 ASSERT (Value
!= NULL
);
1964 // Convert Buffer to Hex String
1966 TemBuffer
= Src
+ StorageWidth
- 1;
1968 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1969 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1973 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1975 if (EFI_ERROR (Status
)) {
1979 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1981 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1982 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1984 if (IsBufferStorage
) {
1985 Length
= StrLen (Question
->BlockName
) + 7;
1987 Length
= StrLen (Question
->VariableName
) + 2;
1989 if (!IsBufferStorage
&& IsString
) {
1990 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1992 Length
+= (StorageWidth
* 2);
1994 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1995 ASSERT (FormsetStorage
!= NULL
);
1996 ConfigResp
= AllocateZeroPool ((StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1997 ASSERT (ConfigResp
!= NULL
);
1999 StrCpy (ConfigResp
, FormsetStorage
->ConfigHdr
);
2000 if (IsBufferStorage
) {
2001 StrCat (ConfigResp
, Question
->BlockName
);
2002 StrCat (ConfigResp
, L
"&VALUE=");
2004 StrCat (ConfigResp
, L
"&");
2005 StrCat (ConfigResp
, Question
->VariableName
);
2006 StrCat (ConfigResp
, L
"=");
2009 Value
= ConfigResp
+ StrLen (ConfigResp
);
2011 if (!IsBufferStorage
&& IsString
) {
2013 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2015 TemName
= (CHAR16
*) Src
;
2017 for (; *TemName
!= L
'\0'; TemName
++) {
2018 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
2022 // Convert Buffer to Hex String
2024 TemBuffer
= Src
+ StorageWidth
- 1;
2026 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2027 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2032 // Convert to lower char.
2034 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2035 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2036 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2041 // Submit Question Value to Configuration Driver
2043 Status
= mHiiConfigRouting
->RouteConfig (
2048 if (EFI_ERROR (Status
)) {
2049 FreePool (ConfigResp
);
2052 FreePool (ConfigResp
);
2055 // Sync storage, from editbuffer to buffer.
2057 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2065 Perform nosubmitif check for a Form.
2067 @param FormSet FormSet data structure.
2068 @param Form Form data structure.
2069 @param Question The Question to be validated.
2070 @param Type Validation type: NoSubmit
2072 @retval EFI_SUCCESS Form validation pass.
2073 @retval other Form validation failed.
2078 IN FORM_BROWSER_FORMSET
*FormSet
,
2079 IN FORM_BROWSER_FORM
*Form
,
2080 IN FORM_BROWSER_STATEMENT
*Question
,
2086 LIST_ENTRY
*ListHead
;
2087 FORM_EXPRESSION
*Expression
;
2088 UINT32 BrowserStatus
;
2091 BrowserStatus
= BROWSER_SUCCESS
;
2095 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2096 ListHead
= &Question
->InconsistentListHead
;
2099 case EFI_HII_EXPRESSION_WARNING_IF
:
2100 ListHead
= &Question
->WarningListHead
;
2103 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2104 ListHead
= &Question
->NoSubmitListHead
;
2109 return EFI_UNSUPPORTED
;
2112 Link
= GetFirstNode (ListHead
);
2113 while (!IsNull (ListHead
, Link
)) {
2114 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2117 // Evaluate the expression
2119 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2120 if (EFI_ERROR (Status
)) {
2124 if (IsTrue (&Expression
->Result
)) {
2126 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2127 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2130 case EFI_HII_EXPRESSION_WARNING_IF
:
2131 BrowserStatus
= BROWSER_WARNING_IF
;
2134 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2135 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2137 // This code only used to compatible with old display engine,
2138 // New display engine will not use this field.
2140 if (Expression
->Error
!= 0) {
2141 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2150 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2152 // If in system submit process and for no_submit_if check, not popup this error message.
2153 // Will process this fail again later in not system submit process.
2155 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2158 if (ErrorStr
!= NULL
) {
2159 FreePool (ErrorStr
);
2162 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2165 return EFI_NOT_READY
;
2169 Link
= GetNextNode (ListHead
, Link
);
2176 Perform question check.
2178 If one question has more than one check, process form high priority to low.
2179 Only one error info will be popup.
2181 @param FormSet FormSet data structure.
2182 @param Form Form data structure.
2183 @param Question The Question to be validated.
2185 @retval EFI_SUCCESS Form validation pass.
2186 @retval other Form validation failed.
2190 ValueChangedValidation (
2191 IN FORM_BROWSER_FORMSET
*FormSet
,
2192 IN FORM_BROWSER_FORM
*Form
,
2193 IN FORM_BROWSER_STATEMENT
*Question
2198 Status
= EFI_SUCCESS
;
2201 // Do the inconsistentif check.
2203 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2204 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2205 if (EFI_ERROR (Status
)) {
2211 // Do the warningif check.
2213 if (!IsListEmpty (&Question
->WarningListHead
)) {
2214 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2221 Perform NoSubmit check for each Form in FormSet.
2223 @param FormSet FormSet data structure.
2224 @param CurrentForm Current input form data structure.
2225 @param Statement The statement for this check.
2227 @retval EFI_SUCCESS Form validation pass.
2228 @retval other Form validation failed.
2233 IN FORM_BROWSER_FORMSET
*FormSet
,
2234 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2235 OUT FORM_BROWSER_STATEMENT
**Statement
2240 FORM_BROWSER_STATEMENT
*Question
;
2241 FORM_BROWSER_FORM
*Form
;
2242 LIST_ENTRY
*LinkForm
;
2244 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2245 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2246 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2247 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2249 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2253 Link
= GetFirstNode (&Form
->StatementListHead
);
2254 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2255 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2256 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2257 if (EFI_ERROR (Status
)) {
2258 if (*CurrentForm
== NULL
) {
2259 *CurrentForm
= Form
;
2261 if (Statement
!= NULL
) {
2262 *Statement
= Question
;
2267 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2275 Fill storage's edit copy with settings requested from Configuration Driver.
2277 @param Storage The storage which need to sync.
2278 @param ConfigRequest The config request string which used to sync storage.
2279 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2280 editbuffer to buffer
2281 if TRUE, copy the editbuffer to the buffer.
2282 if FALSE, copy the buffer to the editbuffer.
2284 @retval EFI_SUCCESS The function completed successfully.
2288 SynchronizeStorage (
2289 OUT BROWSER_STORAGE
*Storage
,
2290 IN CHAR16
*ConfigRequest
,
2291 IN BOOLEAN SyncOrRestore
2295 EFI_STRING Progress
;
2299 NAME_VALUE_NODE
*Node
;
2303 Status
= EFI_SUCCESS
;
2306 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2307 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2308 BufferSize
= Storage
->Size
;
2310 if (SyncOrRestore
) {
2311 Src
= Storage
->EditBuffer
;
2312 Dst
= Storage
->Buffer
;
2314 Src
= Storage
->Buffer
;
2315 Dst
= Storage
->EditBuffer
;
2318 if (ConfigRequest
!= NULL
) {
2319 Status
= mHiiConfigRouting
->BlockToConfig(
2327 if (EFI_ERROR (Status
)) {
2331 Status
= mHiiConfigRouting
->ConfigToBlock (
2338 if (Result
!= NULL
) {
2342 CopyMem (Dst
, Src
, BufferSize
);
2344 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2345 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2346 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2347 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2349 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2350 (ConfigRequest
== NULL
)) {
2351 if (SyncOrRestore
) {
2352 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2354 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2358 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2366 When discard the question value, call the callback function with Changed type
2367 to inform the hii driver.
2369 @param FormSet FormSet data structure.
2370 @param Form Form data structure.
2374 SendDiscardInfoToDriver (
2375 IN FORM_BROWSER_FORMSET
*FormSet
,
2376 IN FORM_BROWSER_FORM
*Form
2380 FORM_BROWSER_STATEMENT
*Question
;
2381 EFI_IFR_TYPE_VALUE
*TypeValue
;
2382 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2384 if (FormSet
->ConfigAccess
== NULL
) {
2388 Link
= GetFirstNode (&Form
->StatementListHead
);
2389 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2390 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2391 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2393 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2397 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2401 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2405 if (!Question
->ValueChanged
) {
2410 // Restore the question value before call the CHANGED callback type.
2412 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2414 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2415 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2417 TypeValue
= &Question
->HiiValue
.Value
;
2420 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2421 FormSet
->ConfigAccess
->Callback (
2422 FormSet
->ConfigAccess
,
2423 EFI_BROWSER_ACTION_CHANGED
,
2424 Question
->QuestionId
,
2425 Question
->HiiValue
.Type
,
2433 Validate the HiiHandle.
2435 @param HiiHandle The input HiiHandle which need to validate.
2437 @retval TRUE The handle is validate.
2438 @retval FALSE The handle is invalidate.
2443 EFI_HII_HANDLE HiiHandle
2446 EFI_HII_HANDLE
*HiiHandles
;
2450 if (HiiHandle
== NULL
) {
2456 HiiHandles
= HiiGetHiiHandles (NULL
);
2457 ASSERT (HiiHandles
!= NULL
);
2459 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2460 if (HiiHandles
[Index
] == HiiHandle
) {
2466 FreePool (HiiHandles
);
2472 Validate the FormSet. If the formset is not validate, remove it from the list.
2474 @param FormSet The input FormSet which need to validate.
2476 @retval TRUE The handle is validate.
2477 @retval FALSE The handle is invalidate.
2482 FORM_BROWSER_FORMSET
*FormSet
2487 ASSERT (FormSet
!= NULL
);
2489 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2491 // Should not remove the formset which is being used.
2493 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2494 CleanBrowserStorage(FormSet
);
2495 RemoveEntryList (&FormSet
->Link
);
2496 DestroyFormSet (FormSet
);
2502 Check whether need to enable the reset flag in form level.
2503 Also clean all ValueChanged flag in question.
2505 @param SetFlag Whether need to set the Reset Flag.
2506 @param FormSet FormSet data structure.
2507 @param Form Form data structure.
2513 IN FORM_BROWSER_FORMSET
*FormSet
,
2514 IN FORM_BROWSER_FORM
*Form
2518 FORM_BROWSER_STATEMENT
*Question
;
2521 Link
= GetFirstNode (&Form
->StatementListHead
);
2522 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2523 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2524 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2526 if (!Question
->ValueChanged
) {
2530 OldValue
= Question
->ValueChanged
;
2533 // Compare the buffer and editbuffer data to see whether the data has been saved.
2535 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2538 // Only the changed data has been saved, then need to set the reset flag.
2540 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2541 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2542 gResetRequired
= TRUE
;
2545 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2546 gFlagReconnect
= TRUE
;
2553 Check whether need to enable the reset flag.
2554 Also clean ValueChanged flag for all statements.
2556 Form level or formset level, only one.
2558 @param SetFlag Whether need to set the Reset Flag.
2559 @param FormSet FormSet data structure.
2560 @param Form Form data structure.
2564 ValueChangeResetFlagUpdate (
2566 IN FORM_BROWSER_FORMSET
*FormSet
,
2567 IN FORM_BROWSER_FORM
*Form
2570 FORM_BROWSER_FORM
*CurrentForm
;
2574 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2578 Link
= GetFirstNode (&FormSet
->FormListHead
);
2579 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2580 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2581 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2583 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2588 Base on the return Progress string to find the form.
2590 Base on the first return Offset/Width (Name) string to find the form
2591 which keep this string.
2593 @param FormSet FormSet data structure.
2594 @param Storage Storage which has this Progress string.
2595 @param Progress The Progress string which has the first fail string.
2596 @param RetForm The return form for this progress string.
2597 @param RetQuestion The return question for the error progress string.
2599 @retval TRUE Find the error form and statement for this error progress string.
2600 @retval FALSE Not find the error form.
2604 FindQuestionFromProgress (
2605 IN FORM_BROWSER_FORMSET
*FormSet
,
2606 IN BROWSER_STORAGE
*Storage
,
2607 IN EFI_STRING Progress
,
2608 OUT FORM_BROWSER_FORM
**RetForm
,
2609 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2613 LIST_ENTRY
*LinkStorage
;
2614 LIST_ENTRY
*LinkStatement
;
2615 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2616 FORM_BROWSER_FORM
*Form
;
2618 FORM_BROWSER_STATEMENT
*Statement
;
2620 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2624 *RetQuestion
= NULL
;
2627 // Skip the first "&" or the ConfigHdr part.
2629 if (*Progress
== '&') {
2633 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2635 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2637 // For Name/Value type, Skip the ConfigHdr part.
2639 EndStr
= StrStr (Progress
, L
"PATH=");
2640 ASSERT (EndStr
!= NULL
);
2641 while (*EndStr
!= '&') {
2648 // For Buffer type, Skip the ConfigHdr part.
2650 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2651 ASSERT (EndStr
!= NULL
);
2655 Progress
= EndStr
+ 1;
2659 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2661 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2663 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2664 // here, just keep the "Fred" string.
2666 EndStr
= StrStr (Progress
, L
"=");
2667 ASSERT (EndStr
!= NULL
);
2671 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2672 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2674 EndStr
= StrStr (Progress
, L
"&VALUE=");
2675 ASSERT (EndStr
!= NULL
);
2680 // Search in the form list.
2682 Link
= GetFirstNode (&FormSet
->FormListHead
);
2683 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2684 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2685 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2688 // Search in the ConfigReqeust list in this form.
2690 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2691 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2692 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2693 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2695 if (Storage
!= ConfigInfo
->Storage
) {
2699 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2701 // Find the OffsetWidth string in this form.
2708 if (*RetForm
!= NULL
) {
2709 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2710 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2711 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2712 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2714 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2715 *RetQuestion
= Statement
;
2719 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2720 *RetQuestion
= Statement
;
2726 if (*RetForm
!= NULL
) {
2732 // restore the OffsetWidth string to the original format.
2734 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2740 return (BOOLEAN
) (*RetForm
!= NULL
);
2744 Popup an save error info and get user input.
2746 @param TitleId The form title id.
2747 @param HiiHandle The hii handle for this package.
2749 @retval UINT32 The user select option for the save fail.
2750 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2754 IN EFI_STRING_ID TitleId
,
2755 IN EFI_HII_HANDLE HiiHandle
2759 CHAR16
*StringBuffer
;
2762 FormTitle
= GetToken (TitleId
, HiiHandle
);
2764 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2765 ASSERT (StringBuffer
!= NULL
);
2769 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2770 L
"Submit Fail For Form: %s.",
2774 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2776 FreePool (StringBuffer
);
2777 FreePool (FormTitle
);
2783 Popup an NO_SUBMIT_IF error info and get user input.
2785 @param TitleId The form title id.
2786 @param HiiHandle The hii handle for this package.
2788 @retval UINT32 The user select option for the save fail.
2789 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2792 ConfirmNoSubmitFail (
2793 IN EFI_STRING_ID TitleId
,
2794 IN EFI_HII_HANDLE HiiHandle
2798 CHAR16
*StringBuffer
;
2801 FormTitle
= GetToken (TitleId
, HiiHandle
);
2803 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2804 ASSERT (StringBuffer
!= NULL
);
2808 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2809 L
"NO_SUBMIT_IF error For Form: %s.",
2813 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2815 FreePool (StringBuffer
);
2816 FreePool (FormTitle
);
2822 Discard data based on the input setting scope (Form, FormSet or System).
2824 @param FormSet FormSet data structure.
2825 @param Form Form data structure.
2826 @param SettingScope Setting Scope for Discard action.
2828 @retval EFI_SUCCESS The function completed successfully.
2829 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2834 IN FORM_BROWSER_FORMSET
*FormSet
,
2835 IN FORM_BROWSER_FORM
*Form
,
2836 IN BROWSER_SETTING_SCOPE SettingScope
2840 FORMSET_STORAGE
*Storage
;
2841 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2842 FORM_BROWSER_FORMSET
*LocalFormSet
;
2843 FORM_BROWSER_FORMSET
*OldFormSet
;
2846 // Check the supported setting level.
2848 if (SettingScope
>= MaxLevel
) {
2849 return EFI_UNSUPPORTED
;
2852 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2854 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2855 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2856 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2857 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2859 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2864 // Skip if there is no RequestElement
2866 if (ConfigInfo
->ElementCount
== 0) {
2871 // Prepare <ConfigResp>
2873 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2876 // Call callback with Changed type to inform the driver.
2878 SendDiscardInfoToDriver (FormSet
, Form
);
2881 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2882 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2885 // Discard Buffer storage or Name/Value storage
2887 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2888 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2889 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2890 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2892 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2897 // Skip if there is no RequestElement
2899 if (Storage
->ElementCount
== 0) {
2903 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2906 Link
= GetFirstNode (&FormSet
->FormListHead
);
2907 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2908 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2909 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2912 // Call callback with Changed type to inform the driver.
2914 SendDiscardInfoToDriver (FormSet
, Form
);
2917 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2918 } else if (SettingScope
== SystemLevel
) {
2920 // System Level Discard.
2922 OldFormSet
= mSystemLevelFormSet
;
2925 // Discard changed value for each FormSet in the maintain list.
2927 Link
= GetFirstNode (&gBrowserFormSetList
);
2928 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2929 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2930 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2931 if (!ValidateFormSet(LocalFormSet
)) {
2935 mSystemLevelFormSet
= LocalFormSet
;
2937 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2938 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2940 // Remove maintain backup list after discard except for the current using FormSet.
2942 CleanBrowserStorage(LocalFormSet
);
2943 RemoveEntryList (&LocalFormSet
->Link
);
2944 DestroyFormSet (LocalFormSet
);
2948 mSystemLevelFormSet
= OldFormSet
;
2955 Submit data for a form.
2957 @param FormSet FormSet data structure.
2958 @param Form Form data structure.
2960 @retval EFI_SUCCESS The function completed successfully.
2961 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2966 IN FORM_BROWSER_FORMSET
*FormSet
,
2967 IN FORM_BROWSER_FORM
*Form
2972 EFI_STRING ConfigResp
;
2973 EFI_STRING Progress
;
2974 BROWSER_STORAGE
*Storage
;
2975 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2977 if (!IsNvUpdateRequiredForForm (Form
)) {
2981 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2982 if (EFI_ERROR (Status
)) {
2986 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2987 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2988 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2989 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2991 Storage
= ConfigInfo
->Storage
;
2992 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2997 // Skip if there is no RequestElement
2999 if (ConfigInfo
->ElementCount
== 0) {
3004 // 1. Prepare <ConfigResp>
3006 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3007 if (EFI_ERROR (Status
)) {
3012 // 2. Set value to hii config routine protocol.
3014 Status
= mHiiConfigRouting
->RouteConfig (
3019 FreePool (ConfigResp
);
3021 if (EFI_ERROR (Status
)) {
3022 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3027 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3029 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3033 // 4. Process the save failed storage.
3035 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3036 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3037 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3038 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3039 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3040 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3042 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3044 Status
= EFI_SUCCESS
;
3047 Status
= EFI_UNSUPPORTED
;
3051 // Free Form save fail list.
3053 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3054 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3055 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3056 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3061 // 5. Update the NV flag.
3063 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3069 Submit data for a formset.
3071 @param FormSet FormSet data structure.
3072 @param SkipProcessFail Whether skip to process the save failed storage.
3073 If submit formset is called when do system level save,
3074 set this value to true and process the failed formset
3076 if submit formset is called when do formset level save,
3077 set the value to false and process the failed storage
3078 right after process all storages for this formset.
3080 @retval EFI_SUCCESS The function completed successfully.
3081 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3086 IN FORM_BROWSER_FORMSET
*FormSet
,
3087 IN BOOLEAN SkipProcessFail
3092 EFI_STRING ConfigResp
;
3093 EFI_STRING Progress
;
3094 BROWSER_STORAGE
*Storage
;
3095 FORMSET_STORAGE
*FormSetStorage
;
3096 FORM_BROWSER_FORM
*Form
;
3097 BOOLEAN HasInserted
;
3098 FORM_BROWSER_STATEMENT
*Question
;
3100 HasInserted
= FALSE
;
3102 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3107 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3108 if (EFI_ERROR (Status
)) {
3109 if (SkipProcessFail
) {
3111 // Process NO_SUBMIT check first, so insert it at head.
3113 FormSet
->SaveFailForm
= Form
;
3114 FormSet
->SaveFailStatement
= Question
;
3115 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3124 // Submit Buffer storage or Name/Value storage
3126 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3127 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3128 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3129 Storage
= FormSetStorage
->BrowserStorage
;
3130 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3132 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3137 // Skip if there is no RequestElement
3139 if (FormSetStorage
->ElementCount
== 0) {
3144 // 1. Prepare <ConfigResp>
3146 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3147 if (EFI_ERROR (Status
)) {
3152 // 2. Send <ConfigResp> to Routine config Protocol.
3154 Status
= mHiiConfigRouting
->RouteConfig (
3159 if (EFI_ERROR (Status
)) {
3160 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3163 // Call submit formset for system level, save the formset info
3164 // and process later.
3166 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3167 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3168 FormSet
->SaveFailForm
= Form
;
3169 FormSet
->SaveFailStatement
= Question
;
3170 if (SkipProcessFail
) {
3171 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3176 FreePool (ConfigResp
);
3180 FreePool (ConfigResp
);
3182 // 3. Config success, update storage shadow Buffer
3184 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3188 // 4. Has save fail storage need to handle.
3191 if (!SkipProcessFail
) {
3193 // If not in system level, just handl the save failed storage here.
3195 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3196 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3197 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3198 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3199 Storage
= FormSetStorage
->BrowserStorage
;
3200 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3202 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3204 Status
= EFI_SUCCESS
;
3207 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3209 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3210 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3211 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3212 gCurrentSelection
->FormId
= Form
->FormId
;
3213 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3215 Status
= EFI_UNSUPPORTED
;
3219 // Free FormSet save fail list.
3221 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3222 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3223 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3224 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3228 // If in system level, just return error and handle the failed formset later.
3230 Status
= EFI_UNSUPPORTED
;
3235 // 5. Update the NV flag.
3237 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3243 Submit data for all formsets.
3245 @retval EFI_SUCCESS The function completed successfully.
3246 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3256 LIST_ENTRY
*StorageLink
;
3257 FORMSET_STORAGE
*FormSetStorage
;
3258 FORM_BROWSER_FORM
*Form
;
3259 FORM_BROWSER_FORMSET
*LocalFormSet
;
3260 UINT32 UserSelection
;
3261 FORM_BROWSER_STATEMENT
*Question
;
3263 mSystemSubmit
= TRUE
;
3264 Link
= GetFirstNode (&gBrowserFormSetList
);
3265 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3266 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3267 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3268 if (!ValidateFormSet(LocalFormSet
)) {
3272 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3273 if (EFI_ERROR (Status
)) {
3278 // Remove maintain backup list after save except for the current using FormSet.
3280 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3281 CleanBrowserStorage(LocalFormSet
);
3282 RemoveEntryList (&LocalFormSet
->Link
);
3283 DestroyFormSet (LocalFormSet
);
3286 mSystemSubmit
= FALSE
;
3288 Status
= EFI_SUCCESS
;
3291 // Process the save failed formsets.
3293 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3294 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3295 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3296 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3298 if (!ValidateFormSet(LocalFormSet
)) {
3302 Form
= LocalFormSet
->SaveFailForm
;
3303 Question
= LocalFormSet
->SaveFailStatement
;
3306 // Confirm with user, get user input.
3308 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3310 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3312 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3314 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3317 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3318 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3319 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3320 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3321 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3322 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3324 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3327 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3328 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3329 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3330 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3332 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3336 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3337 CleanBrowserStorage(LocalFormSet
);
3338 RemoveEntryList (&LocalFormSet
->Link
);
3339 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3340 DestroyFormSet (LocalFormSet
);
3342 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3345 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3346 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3349 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3351 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3352 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3353 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3354 gCurrentSelection
->FormId
= Form
->FormId
;
3355 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3357 Status
= EFI_UNSUPPORTED
;
3363 // Clean the list which will not process.
3365 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3366 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3367 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3368 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3370 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3371 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3372 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3373 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3381 Submit data based on the input Setting level (Form, FormSet or System).
3383 @param FormSet FormSet data structure.
3384 @param Form Form data structure.
3385 @param SettingScope Setting Scope for Submit action.
3387 @retval EFI_SUCCESS The function completed successfully.
3388 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3393 IN FORM_BROWSER_FORMSET
*FormSet
,
3394 IN FORM_BROWSER_FORM
*Form
,
3395 IN BROWSER_SETTING_SCOPE SettingScope
3400 switch (SettingScope
) {
3402 Status
= SubmitForForm(FormSet
, Form
);
3406 Status
= SubmitForFormSet (FormSet
, FALSE
);
3410 Status
= SubmitForSystem ();
3414 Status
= EFI_UNSUPPORTED
;
3422 Converts the unicode character of the string from uppercase to lowercase.
3423 This is a internal function.
3425 @param ConfigString String to be converted
3431 IN EFI_STRING ConfigString
3437 ASSERT (ConfigString
!= NULL
);
3440 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3442 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3443 if (*String
== L
'=') {
3445 } else if (*String
== L
'&') {
3447 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3448 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3454 Find the point in the ConfigResp string for this question.
3456 @param Question The question.
3457 @param ConfigResp Get ConfigResp string.
3459 @retval point to the offset where is for this question.
3463 GetOffsetFromConfigResp (
3464 IN FORM_BROWSER_STATEMENT
*Question
,
3465 IN CHAR16
*ConfigResp
3468 CHAR16
*RequestElement
;
3472 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3474 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3475 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3476 if (RequestElement
!= NULL
) {
3478 // Skip the "VariableName=" field.
3480 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3483 return RequestElement
;
3487 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3491 // 1. Directly use Question->BlockName to find.
3493 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3494 if (RequestElement
!= NULL
) {
3496 // Skip the "Question->BlockName&VALUE=" field.
3498 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3499 return RequestElement
;
3503 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3505 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3506 ASSERT (BlockData
!= NULL
);
3507 HiiToLower (BlockData
);
3508 RequestElement
= StrStr (ConfigResp
, BlockData
);
3509 FreePool (BlockData
);
3511 if (RequestElement
!= NULL
) {
3513 // Skip the "Question->BlockName&VALUE=" field.
3515 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3518 return RequestElement
;
3522 Get Question default value from AltCfg string.
3524 @param FormSet The form set.
3525 @param Form The form
3526 @param Question The question.
3528 @retval EFI_SUCCESS Question is reset to default value.
3532 GetDefaultValueFromAltCfg (
3533 IN FORM_BROWSER_FORMSET
*FormSet
,
3534 IN FORM_BROWSER_FORM
*Form
,
3535 IN OUT FORM_BROWSER_STATEMENT
*Question
3538 BROWSER_STORAGE
*Storage
;
3539 FORMSET_STORAGE
*FormSetStorage
;
3543 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3545 Storage
= Question
->Storage
;
3546 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3547 return EFI_NOT_FOUND
;
3551 // Try to get AltCfg string from form. If not found it, then
3552 // try to get it from formset.
3555 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3556 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3557 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3558 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3560 if (Storage
== ConfigInfo
->Storage
) {
3561 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3566 if (ConfigResp
== NULL
) {
3567 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3568 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3569 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3570 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3572 if (Storage
== FormSetStorage
->BrowserStorage
) {
3573 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3579 if (ConfigResp
== NULL
) {
3580 return EFI_NOT_FOUND
;
3583 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3584 if (Value
== NULL
) {
3585 return EFI_NOT_FOUND
;
3588 return BufferToValue (Question
, Value
);
3592 Get default Id value used for browser.
3594 @param DefaultId The default id value used by hii.
3596 @retval Browser used default value.
3600 GetDefaultIdForCallBack (
3604 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3605 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3606 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3607 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3608 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3609 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3610 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3611 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3612 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3613 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3614 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3615 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3624 Return data element in an Array by its Index.
3626 @param Array The data array.
3627 @param Type Type of the data in this array.
3628 @param Index Zero based index for data in this array.
3630 @retval Value The data to be returned
3642 ASSERT (Array
!= NULL
);
3646 case EFI_IFR_TYPE_NUM_SIZE_8
:
3647 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3650 case EFI_IFR_TYPE_NUM_SIZE_16
:
3651 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3654 case EFI_IFR_TYPE_NUM_SIZE_32
:
3655 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3658 case EFI_IFR_TYPE_NUM_SIZE_64
:
3659 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3671 Set value of a data element in an Array by its Index.
3673 @param Array The data array.
3674 @param Type Type of the data in this array.
3675 @param Index Zero based index for data in this array.
3676 @param Value The value to be set.
3688 ASSERT (Array
!= NULL
);
3691 case EFI_IFR_TYPE_NUM_SIZE_8
:
3692 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3695 case EFI_IFR_TYPE_NUM_SIZE_16
:
3696 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3699 case EFI_IFR_TYPE_NUM_SIZE_32
:
3700 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3703 case EFI_IFR_TYPE_NUM_SIZE_64
:
3704 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3713 Search an Option of a Question by its value.
3715 @param Question The Question
3716 @param OptionValue Value for Option to be searched.
3718 @retval Pointer Pointer to the found Option.
3719 @retval NULL Option not found.
3724 IN FORM_BROWSER_STATEMENT
*Question
,
3725 IN EFI_HII_VALUE
*OptionValue
3729 QUESTION_OPTION
*Option
;
3732 Link
= GetFirstNode (&Question
->OptionListHead
);
3733 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3734 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3736 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3738 // Check the suppressif condition, only a valid option can be return.
3740 if ((Option
->SuppressExpression
== NULL
) ||
3741 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3746 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3754 Reset Question to its default value.
3756 @param FormSet The form set.
3757 @param Form The form.
3758 @param Question The question.
3759 @param DefaultId The Class of the default.
3761 @retval EFI_SUCCESS Question is reset to default value.
3765 GetQuestionDefault (
3766 IN FORM_BROWSER_FORMSET
*FormSet
,
3767 IN FORM_BROWSER_FORM
*Form
,
3768 IN FORM_BROWSER_STATEMENT
*Question
,
3774 QUESTION_DEFAULT
*Default
;
3775 QUESTION_OPTION
*Option
;
3776 EFI_HII_VALUE
*HiiValue
;
3778 EFI_STRING StrValue
;
3779 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3780 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3784 Status
= EFI_NOT_FOUND
;
3788 // Statement don't have storage, skip them
3790 if (Question
->QuestionId
== 0) {
3795 // There are Five ways to specify default value for a Question:
3796 // 1, use call back function (highest priority)
3797 // 2, use ExtractConfig function
3798 // 3, use nested EFI_IFR_DEFAULT
3799 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3800 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3802 HiiValue
= &Question
->HiiValue
;
3805 // Get Question defaut value from call back function.
3807 ConfigAccess
= FormSet
->ConfigAccess
;
3808 Action
= GetDefaultIdForCallBack (DefaultId
);
3809 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3810 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3811 Status
= ConfigAccess
->Callback (
3814 Question
->QuestionId
,
3819 if (!EFI_ERROR (Status
)) {
3820 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3821 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3822 ASSERT (NewString
!= NULL
);
3824 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3825 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3826 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3828 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3831 FreePool (NewString
);
3838 // Get default value from altcfg string.
3840 if (ConfigAccess
!= NULL
) {
3841 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
3842 if (!EFI_ERROR (Status
)) {
3848 // EFI_IFR_DEFAULT has highest priority
3850 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3851 Link
= GetFirstNode (&Question
->DefaultListHead
);
3852 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3853 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3855 if (Default
->DefaultId
== DefaultId
) {
3856 if (Default
->ValueExpression
!= NULL
) {
3858 // Default is provided by an Expression, evaluate it
3860 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3861 if (EFI_ERROR (Status
)) {
3865 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3866 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3867 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3868 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3869 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3871 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3872 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3874 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3876 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3877 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3880 // Default value is embedded in EFI_IFR_DEFAULT
3882 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
3883 ASSERT (HiiValue
->Buffer
!= NULL
);
3884 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
3886 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3890 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3891 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3892 if (StrValue
== NULL
) {
3893 return EFI_NOT_FOUND
;
3895 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3896 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3898 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3905 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3910 // EFI_ONE_OF_OPTION
3912 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3913 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3915 // OneOfOption could only provide Standard and Manufacturing default
3917 Link
= GetFirstNode (&Question
->OptionListHead
);
3918 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3919 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3920 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3922 if ((Option
->SuppressExpression
!= NULL
) &&
3923 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3927 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3928 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3930 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3939 // EFI_IFR_CHECKBOX - lowest priority
3941 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3942 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3944 // Checkbox could only provide Standard and Manufacturing default
3946 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3947 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3949 HiiValue
->Value
.b
= TRUE
;
3951 HiiValue
->Value
.b
= FALSE
;
3959 // For Questions without default
3961 Status
= EFI_NOT_FOUND
;
3962 switch (Question
->Operand
) {
3963 case EFI_IFR_NUMERIC_OP
:
3965 // Take minimum value as numeric default value
3967 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
3969 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
3971 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
3972 case EFI_IFR_NUMERIC_SIZE_1
:
3973 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
3974 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
3975 Status
= EFI_SUCCESS
;
3978 case EFI_IFR_NUMERIC_SIZE_2
:
3979 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
3980 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
3981 Status
= EFI_SUCCESS
;
3984 case EFI_IFR_NUMERIC_SIZE_4
:
3985 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
3986 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
3987 Status
= EFI_SUCCESS
;
3990 case EFI_IFR_NUMERIC_SIZE_8
:
3991 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
3992 HiiValue
->Value
.u64
= Question
->Minimum
;
3993 Status
= EFI_SUCCESS
;
4000 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4001 HiiValue
->Value
.u64
= Question
->Minimum
;
4002 Status
= EFI_SUCCESS
;
4007 case EFI_IFR_ONE_OF_OP
:
4009 // Take first oneof option as oneof's default value
4011 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4012 Link
= GetFirstNode (&Question
->OptionListHead
);
4013 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4014 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4015 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4017 if ((Option
->SuppressExpression
!= NULL
) &&
4018 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4022 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4023 Status
= EFI_SUCCESS
;
4029 case EFI_IFR_ORDERED_LIST_OP
:
4031 // Take option sequence in IFR as ordered list's default value
4034 Link
= GetFirstNode (&Question
->OptionListHead
);
4035 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4036 Status
= EFI_SUCCESS
;
4037 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4038 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4040 if ((Option
->SuppressExpression
!= NULL
) &&
4041 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4045 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4048 if (Index
>= Question
->MaxContainers
) {
4062 Get AltCfg string for current form.
4064 @param FormSet Form data structure.
4065 @param Form Form data structure.
4066 @param DefaultId The Class of the default.
4067 @param BrowserStorage The input request storage for the questions.
4071 ExtractAltCfgForForm (
4072 IN FORM_BROWSER_FORMSET
*FormSet
,
4073 IN FORM_BROWSER_FORM
*Form
,
4074 IN UINT16 DefaultId
,
4075 IN BROWSER_STORAGE
*BrowserStorage
4083 BROWSER_STORAGE
*Storage
;
4084 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4085 FORMSET_STORAGE
*FormSetStorage
;
4088 // Check whether has get AltCfg string for this formset.
4089 // If yes, no need to get AltCfg for form.
4091 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4092 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4093 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4094 Storage
= FormSetStorage
->BrowserStorage
;
4095 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4096 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4100 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4101 FormSetStorage
->ElementCount
!= 0 &&
4102 FormSetStorage
->HasCallAltCfg
) {
4108 // Get AltCfg string for each form.
4110 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4111 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4112 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4113 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4115 Storage
= ConfigInfo
->Storage
;
4116 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4120 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4125 // 1. Skip if there is no RequestElement
4127 if (ConfigInfo
->ElementCount
== 0) {
4132 // 2. Get value through hii config routine protocol.
4134 Status
= mHiiConfigRouting
->ExtractConfig (
4136 ConfigInfo
->ConfigRequest
,
4140 if (EFI_ERROR (Status
)) {
4145 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4146 // Get the default configuration string according to the default ID.
4148 Status
= mHiiConfigRouting
->GetAltConfig (
4154 &DefaultId
, // it can be NULL to get the current setting.
4158 if (EFI_ERROR (Status
)) {
4162 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4167 Clean AltCfg string for current form.
4169 @param Form Form data structure.
4173 CleanAltCfgForForm (
4174 IN FORM_BROWSER_FORM
*Form
4178 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4180 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4181 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4182 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4183 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4185 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4186 FreePool (ConfigInfo
->ConfigAltResp
);
4187 ConfigInfo
->ConfigAltResp
= NULL
;
4193 Get AltCfg string for current formset.
4195 @param FormSet Form data structure.
4196 @param DefaultId The Class of the default.
4197 @param BrowserStorage The input request storage for the questions.
4201 ExtractAltCfgForFormSet (
4202 IN FORM_BROWSER_FORMSET
*FormSet
,
4203 IN UINT16 DefaultId
,
4204 IN BROWSER_STORAGE
*BrowserStorage
4212 BROWSER_STORAGE
*Storage
;
4213 FORMSET_STORAGE
*FormSetStorage
;
4215 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4216 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4217 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4218 Storage
= FormSetStorage
->BrowserStorage
;
4219 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4221 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4225 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4230 // 1. Skip if there is no RequestElement
4232 if (FormSetStorage
->ElementCount
== 0) {
4236 FormSetStorage
->HasCallAltCfg
= TRUE
;
4239 // 2. Get value through hii config routine protocol.
4241 Status
= mHiiConfigRouting
->ExtractConfig (
4243 FormSetStorage
->ConfigRequest
,
4247 if (EFI_ERROR (Status
)) {
4252 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4253 // Get the default configuration string according to the default ID.
4255 Status
= mHiiConfigRouting
->GetAltConfig (
4261 &DefaultId
, // it can be NULL to get the current setting.
4266 if (EFI_ERROR (Status
)) {
4270 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4276 Clean AltCfg string for current formset.
4278 @param FormSet Form data structure.
4282 CleanAltCfgForFormSet (
4283 IN FORM_BROWSER_FORMSET
*FormSet
4287 FORMSET_STORAGE
*FormSetStorage
;
4289 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4290 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4291 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4292 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4294 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4295 FreePool (FormSetStorage
->ConfigAltResp
);
4296 FormSetStorage
->ConfigAltResp
= NULL
;
4299 FormSetStorage
->HasCallAltCfg
= FALSE
;
4304 Reset Questions to their initial value or default value in a Form, Formset or System.
4306 GetDefaultValueScope parameter decides which questions will reset
4307 to its default value.
4309 @param FormSet FormSet data structure.
4310 @param Form Form data structure.
4311 @param DefaultId The Class of the default.
4312 @param SettingScope Setting Scope for Default action.
4313 @param GetDefaultValueScope Get default value scope.
4314 @param Storage Get default value only for this storage.
4315 @param RetrieveValueFirst Whether call the retrieve call back to
4316 get the initial value before get default
4318 @param SkipGetAltCfg Whether skip the get altcfg string process.
4320 @retval EFI_SUCCESS The function completed successfully.
4321 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4326 IN FORM_BROWSER_FORMSET
*FormSet
,
4327 IN FORM_BROWSER_FORM
*Form
,
4328 IN UINT16 DefaultId
,
4329 IN BROWSER_SETTING_SCOPE SettingScope
,
4330 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4331 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4332 IN BOOLEAN RetrieveValueFirst
,
4333 IN BOOLEAN SkipGetAltCfg
4337 LIST_ENTRY
*FormLink
;
4339 FORM_BROWSER_STATEMENT
*Question
;
4340 FORM_BROWSER_FORMSET
*LocalFormSet
;
4341 FORM_BROWSER_FORMSET
*OldFormSet
;
4343 Status
= EFI_SUCCESS
;
4346 // Check the supported setting level.
4348 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4349 return EFI_UNSUPPORTED
;
4352 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4353 return EFI_UNSUPPORTED
;
4356 if (SettingScope
== FormLevel
) {
4358 // Prepare the AltCfg String for form.
4360 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4361 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4365 // Extract Form default
4367 Link
= GetFirstNode (&Form
->StatementListHead
);
4368 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4369 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4370 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4373 // If get default value only for this storage, check the storage first.
4375 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4380 // If get default value only for no storage question, just skip the question which has storage.
4382 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4387 // If Question is disabled, don't reset it to default
4389 if (Question
->Expression
!= NULL
) {
4390 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4395 if (RetrieveValueFirst
) {
4397 // Call the Retrieve call back to get the initial question value.
4399 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4403 // If not request to get the initial value or get initial value fail, then get default value.
4405 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4406 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4407 if (EFI_ERROR (Status
)) {
4413 // Synchronize Buffer storage's Edit buffer
4415 if ((Question
->Storage
!= NULL
) &&
4416 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4417 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4422 // Clean the AltCfg String.
4424 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4425 CleanAltCfgForForm(Form
);
4427 } else if (SettingScope
== FormSetLevel
) {
4429 // Prepare the AltCfg String for formset.
4431 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4432 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4435 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4436 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4437 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4438 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4439 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4443 // Clean the AltCfg String.
4445 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4446 CleanAltCfgForFormSet (FormSet
);
4448 } else if (SettingScope
== SystemLevel
) {
4450 // Preload all Hii formset.
4452 LoadAllHiiFormset();
4454 OldFormSet
= mSystemLevelFormSet
;
4457 // Set Default Value for each FormSet in the maintain list.
4459 Link
= GetFirstNode (&gBrowserFormSetList
);
4460 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4461 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4462 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4463 if (!ValidateFormSet(LocalFormSet
)) {
4467 mSystemLevelFormSet
= LocalFormSet
;
4469 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4472 mSystemLevelFormSet
= OldFormSet
;
4480 Validate whether this question's value has changed.
4482 @param FormSet FormSet data structure.
4483 @param Form Form data structure.
4484 @param Question Question to be initialized.
4485 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4487 @retval TRUE Question's value has changed.
4488 @retval FALSE Question's value has not changed
4492 IsQuestionValueChanged (
4493 IN FORM_BROWSER_FORMSET
*FormSet
,
4494 IN FORM_BROWSER_FORM
*Form
,
4495 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4496 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4499 EFI_HII_VALUE BackUpValue
;
4500 CHAR8
*BackUpBuffer
;
4501 EFI_HII_VALUE BackUpValue2
;
4502 CHAR8
*BackUpBuffer2
;
4504 BOOLEAN ValueChanged
;
4508 // For quetion without storage, always mark it as data not changed.
4510 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4514 BackUpBuffer
= NULL
;
4515 BackUpBuffer2
= NULL
;
4516 ValueChanged
= FALSE
;
4518 switch (Question
->Operand
) {
4519 case EFI_IFR_ORDERED_LIST_OP
:
4520 BufferWidth
= Question
->StorageWidth
;
4521 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4522 ASSERT (BackUpBuffer
!= NULL
);
4525 case EFI_IFR_STRING_OP
:
4526 case EFI_IFR_PASSWORD_OP
:
4527 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4528 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4529 ASSERT (BackUpBuffer
!= NULL
);
4536 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4538 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4539 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4540 ASSERT_EFI_ERROR(Status
);
4542 switch (Question
->Operand
) {
4543 case EFI_IFR_ORDERED_LIST_OP
:
4544 BufferWidth
= Question
->StorageWidth
;
4545 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4546 ASSERT (BackUpBuffer2
!= NULL
);
4549 case EFI_IFR_STRING_OP
:
4550 case EFI_IFR_PASSWORD_OP
:
4551 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4552 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4553 ASSERT (BackUpBuffer2
!= NULL
);
4560 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4562 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4563 ASSERT_EFI_ERROR(Status
);
4565 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4566 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4567 ValueChanged
= TRUE
;
4570 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4571 ASSERT_EFI_ERROR(Status
);
4573 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4574 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4575 ValueChanged
= TRUE
;
4579 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4580 if (BackUpBuffer
!= NULL
) {
4581 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4582 FreePool (BackUpBuffer
);
4585 if (BackUpBuffer2
!= NULL
) {
4586 FreePool (BackUpBuffer2
);
4589 Question
->ValueChanged
= ValueChanged
;
4591 return ValueChanged
;
4595 Initialize Question's Edit copy from Storage.
4597 @param Selection Selection contains the information about
4598 the Selection, form and formset to be displayed.
4599 Selection action may be updated in retrieve callback.
4600 If Selection is NULL, only initialize Question value.
4601 @param FormSet FormSet data structure.
4602 @param Form Form data structure.
4604 @retval EFI_SUCCESS The function completed successfully.
4609 IN OUT UI_MENU_SELECTION
*Selection
,
4610 IN FORM_BROWSER_FORMSET
*FormSet
,
4611 IN FORM_BROWSER_FORM
*Form
4616 FORM_BROWSER_STATEMENT
*Question
;
4618 Link
= GetFirstNode (&Form
->StatementListHead
);
4619 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4620 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4623 // Initialize local copy of Value for each Question
4625 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4626 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4628 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4630 if (EFI_ERROR (Status
)) {
4634 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4635 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4638 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4645 Initialize Question's Edit copy from Storage for the whole Formset.
4647 @param Selection Selection contains the information about
4648 the Selection, form and formset to be displayed.
4649 Selection action may be updated in retrieve callback.
4650 If Selection is NULL, only initialize Question value.
4651 @param FormSet FormSet data structure.
4653 @retval EFI_SUCCESS The function completed successfully.
4658 IN OUT UI_MENU_SELECTION
*Selection
,
4659 IN FORM_BROWSER_FORMSET
*FormSet
4664 FORM_BROWSER_FORM
*Form
;
4666 Link
= GetFirstNode (&FormSet
->FormListHead
);
4667 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4668 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4671 // Initialize local copy of Value for each Form
4673 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4674 if (EFI_ERROR (Status
)) {
4678 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4682 // Finished question initialization.
4684 FormSet
->QuestionInited
= TRUE
;
4690 Remove the Request element from the Config Request.
4692 @param Storage Pointer to the browser storage.
4693 @param RequestElement The pointer to the Request element.
4698 IN OUT BROWSER_STORAGE
*Storage
,
4699 IN CHAR16
*RequestElement
4705 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4707 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4709 if (NewStr
== NULL
) {
4714 // Remove this element from this ConfigRequest.
4717 NewStr
+= StrLen (RequestElement
);
4718 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4720 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4724 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4726 @param Storage Pointer to the formset storage.
4727 @param ConfigRequest The pointer to the Request element.
4731 RemoveConfigRequest (
4732 FORMSET_STORAGE
*Storage
,
4733 CHAR16
*ConfigRequest
4736 CHAR16
*RequestElement
;
4737 CHAR16
*NextRequestElement
;
4741 // No request element in it, just return.
4743 if (ConfigRequest
== NULL
) {
4747 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4749 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4754 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4756 SearchKey
= L
"&OFFSET";
4760 // Find SearchKey storage
4762 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4763 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4764 ASSERT (RequestElement
!= NULL
);
4765 RequestElement
= StrStr (RequestElement
, SearchKey
);
4767 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4770 while (RequestElement
!= NULL
) {
4772 // +1 to avoid find header itself.
4774 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4777 // The last Request element in configRequest string.
4779 if (NextRequestElement
!= NULL
) {
4781 // Replace "&" with '\0'.
4783 *NextRequestElement
= L
'\0';
4786 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
4788 if (NextRequestElement
!= NULL
) {
4790 // Restore '&' with '\0' for later used.
4792 *NextRequestElement
= L
'&';
4795 RequestElement
= NextRequestElement
;
4799 // If no request element remain, just remove the ConfigRequest string.
4801 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4802 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4803 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4804 Storage
->BrowserStorage
->SpareStrLen
= 0;
4809 Base on the current formset info, clean the ConfigRequest string in browser storage.
4811 @param FormSet Pointer of the FormSet
4815 CleanBrowserStorage (
4816 IN OUT FORM_BROWSER_FORMSET
*FormSet
4820 FORMSET_STORAGE
*Storage
;
4822 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4823 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4824 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4825 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4827 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4828 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4832 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
4833 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4834 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4835 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4836 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4837 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4839 Storage
->BrowserStorage
->Initialized
= FALSE
;
4845 Check whether current element in the ConfigReqeust string.
4847 @param BrowserStorage Storage which includes ConfigReqeust.
4848 @param RequestElement New element need to check.
4850 @retval TRUE The Element is in the ConfigReqeust string.
4851 @retval FALSE The Element not in the configReqeust String.
4856 BROWSER_STORAGE
*BrowserStorage
,
4857 CHAR16
*RequestElement
4860 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4864 Append the Request element to the Config Request.
4866 @param ConfigRequest Current ConfigRequest info.
4867 @param SpareStrLen Current remain free buffer for config reqeust.
4868 @param RequestElement New Request element.
4872 AppendConfigRequest (
4873 IN OUT CHAR16
**ConfigRequest
,
4874 IN OUT UINTN
*SpareStrLen
,
4875 IN CHAR16
*RequestElement
4882 StrLength
= StrLen (RequestElement
);
4885 // Append <RequestElement> to <ConfigRequest>
4887 if (StrLength
> *SpareStrLen
) {
4889 // Old String buffer is not sufficient for RequestElement, allocate a new one
4891 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4892 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4893 ASSERT (NewStr
!= NULL
);
4895 if (*ConfigRequest
!= NULL
) {
4896 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4897 FreePool (*ConfigRequest
);
4899 *ConfigRequest
= NewStr
;
4900 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4903 StrCat (*ConfigRequest
, RequestElement
);
4904 *SpareStrLen
-= StrLength
;
4908 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4910 @param Storage Form set Storage.
4911 @param Request The input request string.
4912 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4914 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4915 @retval FALSE All elements covered by current used elements.
4919 ConfigRequestAdjust (
4920 IN BROWSER_STORAGE
*Storage
,
4922 IN BOOLEAN RespString
4925 CHAR16
*RequestElement
;
4926 CHAR16
*NextRequestElement
;
4927 CHAR16
*NextElementBakup
;
4931 CHAR16
*ConfigRequest
;
4934 NextElementBakup
= NULL
;
4937 if (Request
!= NULL
) {
4938 ConfigRequest
= Request
;
4940 ConfigRequest
= Storage
->ConfigRequest
;
4943 if (Storage
->ConfigRequest
== NULL
) {
4944 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4948 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4950 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4955 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4957 SearchKey
= L
"&OFFSET";
4958 ValueKey
= L
"&VALUE";
4962 // Find SearchKey storage
4964 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4965 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4966 ASSERT (RequestElement
!= NULL
);
4967 RequestElement
= StrStr (RequestElement
, SearchKey
);
4969 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4972 while (RequestElement
!= NULL
) {
4975 // +1 to avoid find header itself.
4977 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4980 // The last Request element in configRequest string.
4982 if (NextRequestElement
!= NULL
) {
4983 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4984 NextElementBakup
= NextRequestElement
;
4985 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4986 ASSERT (NextRequestElement
!= NULL
);
4989 // Replace "&" with '\0'.
4991 *NextRequestElement
= L
'\0';
4993 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4994 NextElementBakup
= NextRequestElement
;
4995 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4996 ASSERT (NextRequestElement
!= NULL
);
4998 // Replace "&" with '\0'.
5000 *NextRequestElement
= L
'\0';
5004 if (!ElementValidation (Storage
, RequestElement
)) {
5006 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5008 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5012 if (NextRequestElement
!= NULL
) {
5014 // Restore '&' with '\0' for later used.
5016 *NextRequestElement
= L
'&';
5019 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5020 RequestElement
= NextElementBakup
;
5022 RequestElement
= NextRequestElement
;
5030 Fill storage's edit copy with settings requested from Configuration Driver.
5032 @param FormSet FormSet data structure.
5033 @param Storage Buffer Storage.
5038 IN FORM_BROWSER_FORMSET
*FormSet
,
5039 IN FORMSET_STORAGE
*Storage
5043 EFI_STRING Progress
;
5046 EFI_STRING ConfigRequest
;
5049 ConfigRequest
= NULL
;
5051 switch (Storage
->BrowserStorage
->Type
) {
5052 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5055 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5056 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5057 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5062 case EFI_HII_VARSTORE_BUFFER
:
5063 case EFI_HII_VARSTORE_NAME_VALUE
:
5065 // Skip if there is no RequestElement.
5067 if (Storage
->ElementCount
== 0) {
5072 // Just update the ConfigRequest, if storage already initialized.
5074 if (Storage
->BrowserStorage
->Initialized
) {
5075 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5079 Storage
->BrowserStorage
->Initialized
= TRUE
;
5086 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5088 // Create the config request string to get all fields for this storage.
5089 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5090 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5092 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5093 ConfigRequest
= AllocateZeroPool (StrLen
);
5094 ASSERT (ConfigRequest
!= NULL
);
5098 L
"%s&OFFSET=0&WIDTH=%04x",
5100 Storage
->BrowserStorage
->Size
);
5102 ConfigRequest
= Storage
->ConfigRequest
;
5106 // Request current settings from Configuration Driver
5108 Status
= mHiiConfigRouting
->ExtractConfig (
5116 // If get value fail, extract default from IFR binary
5118 if (EFI_ERROR (Status
)) {
5119 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5122 // Convert Result from <ConfigAltResp> to <ConfigResp>
5124 StrPtr
= StrStr (Result
, L
"&GUID=");
5125 if (StrPtr
!= NULL
) {
5129 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5133 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5136 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5138 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5140 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5141 if (ConfigRequest
!= NULL
) {
5142 FreePool (ConfigRequest
);
5148 Get Value changed status from old question.
5150 @param NewFormSet FormSet data structure.
5151 @param OldQuestion Old question which has value changed.
5155 SyncStatusForQuestion (
5156 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5157 IN FORM_BROWSER_STATEMENT
*OldQuestion
5161 LIST_ENTRY
*QuestionLink
;
5162 FORM_BROWSER_FORM
*Form
;
5163 FORM_BROWSER_STATEMENT
*Question
;
5166 // For each form in one formset.
5168 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5169 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5170 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5171 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5174 // for each question in one form.
5176 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5177 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5178 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5179 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5181 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5182 Question
->ValueChanged
= TRUE
;
5190 Get Value changed status from old formset.
5192 @param NewFormSet FormSet data structure.
5193 @param OldFormSet FormSet data structure.
5197 SyncStatusForFormSet (
5198 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5199 IN FORM_BROWSER_FORMSET
*OldFormSet
5203 LIST_ENTRY
*QuestionLink
;
5204 FORM_BROWSER_FORM
*Form
;
5205 FORM_BROWSER_STATEMENT
*Question
;
5208 // For each form in one formset.
5210 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5211 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5212 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5213 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5216 // for each question in one form.
5218 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5219 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5220 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5221 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5223 if (!Question
->ValueChanged
) {
5228 // Find the same question in new formset and update the value changed flag.
5230 SyncStatusForQuestion (NewFormSet
, Question
);
5236 Get current setting of Questions.
5238 @param FormSet FormSet data structure.
5242 InitializeCurrentSetting (
5243 IN OUT FORM_BROWSER_FORMSET
*FormSet
5247 FORMSET_STORAGE
*Storage
;
5248 FORM_BROWSER_FORMSET
*OldFormSet
;
5251 // Try to find pre FormSet in the maintain backup list.
5252 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5254 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5255 if (OldFormSet
!= NULL
) {
5256 SyncStatusForFormSet (FormSet
, OldFormSet
);
5257 RemoveEntryList (&OldFormSet
->Link
);
5258 DestroyFormSet (OldFormSet
);
5260 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5263 // Extract default from IFR binary for no storage questions.
5265 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5268 // Request current settings from Configuration Driver
5270 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5271 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5272 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5274 LoadStorage (FormSet
, Storage
);
5276 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5282 Fetch the Ifr binary data of a FormSet.
5284 @param Handle PackageList Handle
5285 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5286 specified (NULL or zero GUID), take the first
5287 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5288 found in package list.
5289 On output, GUID of the formset found(if not NULL).
5290 @param BinaryLength The length of the FormSet IFR binary.
5291 @param BinaryData The buffer designed to receive the FormSet.
5293 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5294 BufferLength was updated.
5295 @retval EFI_INVALID_PARAMETER The handle is unknown.
5296 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5297 be found with the requested FormId.
5302 IN EFI_HII_HANDLE Handle
,
5303 IN OUT EFI_GUID
*FormSetGuid
,
5304 OUT UINTN
*BinaryLength
,
5305 OUT UINT8
**BinaryData
5309 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5315 UINT32 PackageListLength
;
5316 EFI_HII_PACKAGE_HEADER PackageHeader
;
5318 UINT8 NumberOfClassGuid
;
5319 BOOLEAN ClassGuidMatch
;
5320 EFI_GUID
*ClassGuid
;
5321 EFI_GUID
*ComparingGuid
;
5325 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5328 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5330 if (FormSetGuid
== NULL
) {
5331 ComparingGuid
= &gZeroGuid
;
5333 ComparingGuid
= FormSetGuid
;
5337 // Get HII PackageList
5340 HiiPackageList
= NULL
;
5341 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5342 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5343 HiiPackageList
= AllocatePool (BufferSize
);
5344 ASSERT (HiiPackageList
!= NULL
);
5346 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5348 if (EFI_ERROR (Status
)) {
5351 ASSERT (HiiPackageList
!= NULL
);
5354 // Get Form package from this HII package List
5356 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5358 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5360 ClassGuidMatch
= FALSE
;
5361 while (Offset
< PackageListLength
) {
5362 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5363 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5365 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5367 // Search FormSet in this Form Package
5369 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5370 while (Offset2
< PackageHeader
.Length
) {
5371 OpCodeData
= Package
+ Offset2
;
5373 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5375 // Try to compare against formset GUID
5377 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5378 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5382 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5384 // Try to compare against formset class GUID
5386 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5387 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5388 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5389 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5390 ClassGuidMatch
= TRUE
;
5394 if (ClassGuidMatch
) {
5397 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5398 ClassGuidMatch
= TRUE
;
5403 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5406 if (Offset2
< PackageHeader
.Length
) {
5408 // Target formset found
5414 Offset
+= PackageHeader
.Length
;
5417 if (Offset
>= PackageListLength
) {
5419 // Form package not found in this Package List
5421 FreePool (HiiPackageList
);
5422 return EFI_NOT_FOUND
;
5425 if (FormSetGuid
!= NULL
) {
5427 // Return the FormSet GUID
5429 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5433 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5434 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5435 // of the Form Package.
5437 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5438 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5440 FreePool (HiiPackageList
);
5442 if (*BinaryData
== NULL
) {
5443 return EFI_OUT_OF_RESOURCES
;
5451 Initialize the internal data structure of a FormSet.
5453 @param Handle PackageList Handle
5454 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5455 specified (NULL or zero GUID), take the first
5456 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5457 found in package list.
5458 On output, GUID of the formset found(if not NULL).
5459 @param FormSet FormSet data structure.
5461 @retval EFI_SUCCESS The function completed successfully.
5462 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5467 IN EFI_HII_HANDLE Handle
,
5468 IN OUT EFI_GUID
*FormSetGuid
,
5469 OUT FORM_BROWSER_FORMSET
*FormSet
5473 EFI_HANDLE DriverHandle
;
5475 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5476 if (EFI_ERROR (Status
)) {
5480 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5481 FormSet
->HiiHandle
= Handle
;
5482 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5483 FormSet
->QuestionInited
= FALSE
;
5486 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5488 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5489 if (EFI_ERROR (Status
)) {
5492 FormSet
->DriverHandle
= DriverHandle
;
5493 Status
= gBS
->HandleProtocol (
5495 &gEfiHiiConfigAccessProtocolGuid
,
5496 (VOID
**) &FormSet
->ConfigAccess
5498 if (EFI_ERROR (Status
)) {
5500 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5501 // list, then there will be no configuration action required
5503 FormSet
->ConfigAccess
= NULL
;
5507 // Parse the IFR binary OpCodes
5509 Status
= ParseOpCodes (FormSet
);
5516 Save globals used by previous call to SendForm(). SendForm() may be called from
5517 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5518 So, save globals of previous call to SendForm() and restore them upon exit.
5522 SaveBrowserContext (
5526 BROWSER_CONTEXT
*Context
;
5527 FORM_ENTRY_INFO
*MenuList
;
5529 gBrowserContextCount
++;
5530 if (gBrowserContextCount
== 1) {
5532 // This is not reentry of SendForm(), no context to save
5537 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5538 ASSERT (Context
!= NULL
);
5540 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5543 // Save FormBrowser context
5545 Context
->Selection
= gCurrentSelection
;
5546 Context
->ResetRequired
= gResetRequired
;
5547 Context
->FlagReconnect
= gFlagReconnect
;
5548 Context
->CallbackReconnect
= gCallbackReconnect
;
5549 Context
->ExitRequired
= gExitRequired
;
5550 Context
->HiiHandle
= mCurrentHiiHandle
;
5551 Context
->FormId
= mCurrentFormId
;
5552 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5555 // Save the menu history data.
5557 InitializeListHead(&Context
->FormHistoryList
);
5558 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5559 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5560 RemoveEntryList (&MenuList
->Link
);
5562 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5566 // Insert to FormBrowser context list
5568 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5573 Restore globals used by previous call to SendForm().
5577 RestoreBrowserContext (
5582 BROWSER_CONTEXT
*Context
;
5583 FORM_ENTRY_INFO
*MenuList
;
5585 ASSERT (gBrowserContextCount
!= 0);
5586 gBrowserContextCount
--;
5587 if (gBrowserContextCount
== 0) {
5589 // This is not reentry of SendForm(), no context to restore
5594 ASSERT (!IsListEmpty (&gBrowserContextList
));
5596 Link
= GetFirstNode (&gBrowserContextList
);
5597 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5600 // Restore FormBrowser context
5602 gCurrentSelection
= Context
->Selection
;
5603 gResetRequired
= Context
->ResetRequired
;
5604 gFlagReconnect
= Context
->FlagReconnect
;
5605 gCallbackReconnect
= Context
->CallbackReconnect
;
5606 gExitRequired
= Context
->ExitRequired
;
5607 mCurrentHiiHandle
= Context
->HiiHandle
;
5608 mCurrentFormId
= Context
->FormId
;
5609 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5612 // Restore the menu history data.
5614 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5615 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5616 RemoveEntryList (&MenuList
->Link
);
5618 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5622 // Remove from FormBrowser context list
5624 RemoveEntryList (&Context
->Link
);
5625 gBS
->FreePool (Context
);
5629 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5631 @param Handle The Hii Handle.
5633 @return the found FormSet context. If no found, NULL will return.
5636 FORM_BROWSER_FORMSET
*
5637 GetFormSetFromHiiHandle (
5638 EFI_HII_HANDLE Handle
5642 FORM_BROWSER_FORMSET
*FormSet
;
5644 Link
= GetFirstNode (&gBrowserFormSetList
);
5645 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5646 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5647 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5648 if (!ValidateFormSet(FormSet
)) {
5651 if (FormSet
->HiiHandle
== Handle
) {
5660 Check whether the input HII handle is the FormSet that is being used.
5662 @param Handle The Hii Handle.
5664 @retval TRUE HII handle is being used.
5665 @retval FALSE HII handle is not being used.
5669 IsHiiHandleInBrowserContext (
5670 EFI_HII_HANDLE Handle
5674 BROWSER_CONTEXT
*Context
;
5677 // HiiHandle is Current FormSet.
5679 if (mCurrentHiiHandle
== Handle
) {
5684 // Check whether HiiHandle is in BrowserContext.
5686 Link
= GetFirstNode (&gBrowserContextList
);
5687 while (!IsNull (&gBrowserContextList
, Link
)) {
5688 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5689 if (Context
->HiiHandle
== Handle
) {
5691 // HiiHandle is in BrowserContext
5695 Link
= GetNextNode (&gBrowserContextList
, Link
);
5702 Perform Password check.
5703 Passwork may be encrypted by driver that requires the specific check.
5705 @param Form Form where Password Statement is in.
5706 @param Statement Password statement
5707 @param PasswordString Password string to be checked. It may be NULL.
5708 NULL means to restore password.
5709 "" string can be used to checked whether old password does exist.
5711 @return Status Status of Password check.
5716 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5717 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5718 IN EFI_STRING PasswordString OPTIONAL
5722 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5723 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5724 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5725 FORM_BROWSER_STATEMENT
*Question
;
5727 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5728 Question
= GetBrowserStatement(Statement
);
5729 ASSERT (Question
!= NULL
);
5731 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5732 if (ConfigAccess
== NULL
) {
5733 return EFI_UNSUPPORTED
;
5736 if (PasswordString
== NULL
) {
5741 // Check whether has preexisted password.
5743 if (PasswordString
[0] == 0) {
5744 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5747 return EFI_NOT_READY
;
5752 // Check whether the input password is same as preexisted password.
5754 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5757 return EFI_NOT_READY
;
5762 // Prepare password string in HII database
5764 if (PasswordString
!= NULL
) {
5765 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5767 IfrTypeValue
.string
= 0;
5771 // Send password to Configuration Driver for validation
5773 Status
= ConfigAccess
->Callback (
5775 EFI_BROWSER_ACTION_CHANGING
,
5776 Question
->QuestionId
,
5777 Question
->HiiValue
.Type
,
5783 // Remove password string from HII database
5785 if (PasswordString
!= NULL
) {
5786 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5793 Find the registered HotKey based on KeyData.
5795 @param[in] KeyData A pointer to a buffer that describes the keystroke
5796 information for the hot key.
5798 @return The registered HotKey context. If no found, NULL will return.
5801 GetHotKeyFromRegisterList (
5802 IN EFI_INPUT_KEY
*KeyData
5806 BROWSER_HOT_KEY
*HotKey
;
5808 Link
= GetFirstNode (&gBrowserHotKeyList
);
5809 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5810 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5811 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5814 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5821 Configure what scope the hot key will impact.
5822 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5823 If no scope is set, the default scope will be FormSet level.
5824 After all registered hot keys are removed, previous Scope can reset to another level.
5826 @param[in] Scope Scope level to be set.
5828 @retval EFI_SUCCESS Scope is set correctly.
5829 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5830 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5836 IN BROWSER_SETTING_SCOPE Scope
5839 if (Scope
>= MaxLevel
) {
5840 return EFI_INVALID_PARAMETER
;
5844 // When no hot key registered in system or on the first setting,
5845 // Scope can be set.
5847 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5848 gBrowserSettingScope
= Scope
;
5849 mBrowserScopeFirstSet
= FALSE
;
5850 } else if (Scope
!= gBrowserSettingScope
) {
5851 return EFI_UNSUPPORTED
;
5858 Register the hot key with its browser action, or unregistered the hot key.
5859 Only support hot key that is not printable character (control key, function key, etc.).
5860 If the action value is zero, the hot key will be unregistered if it has been registered.
5861 If the same hot key has been registered, the new action and help string will override the previous ones.
5863 @param[in] KeyData A pointer to a buffer that describes the keystroke
5864 information for the hot key. Its type is EFI_INPUT_KEY to
5865 be supported by all ConsoleIn devices.
5866 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5867 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5868 @param[in] HelpString Help string that describes the hot key information.
5869 Its value may be NULL for the unregistered hot key.
5871 @retval EFI_SUCCESS Hot key is registered or unregistered.
5872 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5873 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5874 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5879 IN EFI_INPUT_KEY
*KeyData
,
5881 IN UINT16 DefaultId
,
5882 IN EFI_STRING HelpString OPTIONAL
5885 BROWSER_HOT_KEY
*HotKey
;
5888 // Check input parameters.
5890 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5891 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5892 return EFI_INVALID_PARAMETER
;
5896 // Check whether the input KeyData is in BrowserHotKeyList.
5898 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5901 // Unregister HotKey
5903 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5904 if (HotKey
!= NULL
) {
5906 // The registered HotKey is found.
5907 // Remove it from List, and free its resource.
5909 RemoveEntryList (&HotKey
->Link
);
5910 FreePool (HotKey
->KeyData
);
5911 FreePool (HotKey
->HelpString
);
5915 // The registered HotKey is not found.
5917 return EFI_NOT_FOUND
;
5922 // Register HotKey into List.
5924 if (HotKey
== NULL
) {
5926 // Create new Key, and add it into List.
5928 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5929 ASSERT (HotKey
!= NULL
);
5930 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5931 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5932 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5936 // Fill HotKey information.
5938 HotKey
->Action
= Action
;
5939 HotKey
->DefaultId
= DefaultId
;
5940 if (HotKey
->HelpString
!= NULL
) {
5941 FreePool (HotKey
->HelpString
);
5943 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5949 Register Exit handler function.
5950 When more than one handler function is registered, the latter one will override the previous one.
5951 When NULL handler is specified, the previous Exit handler will be unregistered.
5953 @param[in] Handler Pointer to handler function.
5958 RegiserExitHandler (
5959 IN EXIT_HANDLER Handler
5962 ExitHandlerFunction
= Handler
;
5967 Check whether the browser data has been modified.
5969 @retval TRUE Browser data is modified.
5970 @retval FALSE No browser data is modified.
5975 IsBrowserDataModified (
5980 FORM_BROWSER_FORMSET
*FormSet
;
5982 switch (gBrowserSettingScope
) {
5984 if (gCurrentSelection
== NULL
) {
5987 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5990 if (gCurrentSelection
== NULL
) {
5993 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5996 Link
= GetFirstNode (&gBrowserFormSetList
);
5997 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5998 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5999 if (!ValidateFormSet(FormSet
)) {
6003 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6006 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6016 Execute the action requested by the Action parameter.
6018 @param[in] Action Execute the request action.
6019 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6021 @retval EFI_SUCCESS Execute the request action succss.
6022 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6033 FORM_BROWSER_FORMSET
*FormSet
;
6034 FORM_BROWSER_FORM
*Form
;
6036 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6037 return EFI_NOT_READY
;
6040 Status
= EFI_SUCCESS
;
6043 if (gBrowserSettingScope
< SystemLevel
) {
6044 FormSet
= gCurrentSelection
->FormSet
;
6045 Form
= gCurrentSelection
->Form
;
6049 // Executet the discard action.
6051 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6052 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6053 if (EFI_ERROR (Status
)) {
6059 // Executet the difault action.
6061 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6062 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6063 if (EFI_ERROR (Status
)) {
6066 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6070 // Executet the submit action.
6072 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6073 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6074 if (EFI_ERROR (Status
)) {
6080 // Executet the reset action.
6082 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6083 gResetRequired
= TRUE
;
6087 // Executet the exit action.
6089 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6090 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6091 if (gBrowserSettingScope
== SystemLevel
) {
6092 if (ExitHandlerFunction
!= NULL
) {
6093 ExitHandlerFunction ();
6097 gExitRequired
= TRUE
;
6104 Create reminder to let user to choose save or discard the changed browser data.
6105 Caller can use it to actively check the changed browser data.
6107 @retval BROWSER_NO_CHANGES No browser data is changed.
6108 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6109 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6110 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6120 FORM_BROWSER_FORMSET
*FormSet
;
6121 BOOLEAN IsDataChanged
;
6122 UINT32 DataSavedAction
;
6125 DataSavedAction
= BROWSER_NO_CHANGES
;
6126 IsDataChanged
= FALSE
;
6127 Link
= GetFirstNode (&gBrowserFormSetList
);
6128 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6129 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6130 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6131 if (!ValidateFormSet(FormSet
)) {
6134 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6135 IsDataChanged
= TRUE
;
6141 // No data is changed. No save is required.
6143 if (!IsDataChanged
) {
6144 return DataSavedAction
;
6148 // If data is changed, prompt user to save or discard it.
6151 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6153 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6154 SubmitForm (NULL
, NULL
, SystemLevel
);
6155 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6157 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6158 DiscardForm (NULL
, NULL
, SystemLevel
);
6159 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6161 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6162 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6167 return DataSavedAction
;
6171 Check whether the Reset Required for the browser
6173 @retval TRUE Browser required to reset after exit.
6174 @retval FALSE Browser not need to reset after exit.
6183 return gResetRequired
;