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 extern EFI_GUID mCurrentFormSetGuid
;
72 extern EFI_HII_HANDLE mCurrentHiiHandle
;
73 extern UINT16 mCurrentFormId
;
74 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
77 Create a menu with specified formset GUID and form ID, and add it as a child
78 of the given parent menu.
80 @param HiiHandle Hii handle related to this formset.
81 @param FormSetGuid The Formset Guid of menu to be added.
82 @param FormId The Form ID of menu to be added.
83 @param QuestionId The question id of this menu to be added.
85 @return A pointer to the newly added menu or NULL if memory is insufficient.
90 IN EFI_HII_HANDLE HiiHandle
,
91 IN EFI_GUID
*FormSetGuid
,
96 FORM_ENTRY_INFO
*MenuList
;
98 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
99 if (MenuList
== NULL
) {
103 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
105 MenuList
->HiiHandle
= HiiHandle
;
106 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
107 MenuList
->FormId
= FormId
;
108 MenuList
->QuestionId
= QuestionId
;
111 // If parent is not specified, it is the root Form of a Formset
113 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
119 Return the form id for the input hiihandle and formset.
121 @param HiiHandle HiiHandle for FormSet.
122 @param FormSetGuid The Formset GUID of the menu to search.
124 @return First form's id for this form set.
129 IN EFI_HII_HANDLE HiiHandle
,
130 IN EFI_GUID
*FormSetGuid
134 FORM_BROWSER_FORM
*Form
;
136 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
137 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
143 Search Menu with given FormSetGuid and FormId in all cached menu list.
145 @param HiiHandle HiiHandle for FormSet.
146 @param FormSetGuid The Formset GUID of the menu to search.
147 @param FormId The Form ID of menu to search.
149 @return A pointer to menu found or NULL if not found.
154 IN EFI_HII_HANDLE HiiHandle
,
155 IN EFI_GUID
*FormSetGuid
,
160 FORM_ENTRY_INFO
*MenuList
;
161 FORM_ENTRY_INFO
*RetMenu
;
162 EFI_FORM_ID FirstFormId
;
166 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
167 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
168 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
169 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
172 // If already find the menu, free the menus behind it.
174 if (RetMenu
!= NULL
) {
175 RemoveEntryList (&MenuList
->Link
);
181 // Find the same FromSet.
183 if (MenuList
->HiiHandle
== HiiHandle
) {
184 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
186 // FormSetGuid is not specified.
189 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
190 if (MenuList
->FormId
== FormId
) {
192 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
193 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
194 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
206 Find parent menu for current menu.
208 @param CurrentMenu Current Menu
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.
210 In form level, just find the parent menu;
211 In formset level, find the parent menu which has different
214 @retval The parent menu for current menu.
218 IN FORM_ENTRY_INFO
*CurrentMenu
,
219 IN BROWSER_SETTING_SCOPE SettingLevel
222 FORM_ENTRY_INFO
*ParentMenu
;
225 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
227 if (CurrentMenu
== NULL
) {
232 Link
= &CurrentMenu
->Link
;
234 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
235 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
237 if (SettingLevel
== FormLevel
) {
239 // For FormLevel, just find the parent menu, return.
244 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
246 // For SystemLevel, must find the menu which has different formset.
251 Link
= Link
->BackLink
;
255 // Not find the parent menu, just return NULL.
257 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
265 Free Menu list linked list.
267 @param MenuListHead One Menu list point in the menu list.
272 LIST_ENTRY
*MenuListHead
275 FORM_ENTRY_INFO
*MenuList
;
277 while (!IsListEmpty (MenuListHead
)) {
278 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
279 RemoveEntryList (&MenuList
->Link
);
286 Copy current Menu list to the new menu list.
288 @param NewMenuListHead New create Menu list.
289 @param CurrentMenuListHead Current Menu list.
294 OUT LIST_ENTRY
*NewMenuListHead
,
295 IN LIST_ENTRY
*CurrentMenuListHead
299 FORM_ENTRY_INFO
*MenuList
;
300 FORM_ENTRY_INFO
*NewMenuEntry
;
303 // If new menu list not empty, free it first.
305 UiFreeMenuList (NewMenuListHead
);
307 Link
= GetFirstNode (CurrentMenuListHead
);
308 while (!IsNull (CurrentMenuListHead
, Link
)) {
309 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
310 Link
= GetNextNode (CurrentMenuListHead
, Link
);
312 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
313 ASSERT (NewMenuEntry
!= NULL
);
314 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
315 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
316 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
317 NewMenuEntry
->FormId
= MenuList
->FormId
;
318 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
320 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
325 Load all hii formset to the browser.
333 FORM_BROWSER_FORMSET
*LocalFormSet
;
334 EFI_HII_HANDLE
*HiiHandles
;
338 FORM_BROWSER_FORMSET
*OldFormset
;
340 OldFormset
= mSystemLevelFormSet
;
343 // Get all the Hii handles
345 HiiHandles
= HiiGetHiiHandles (NULL
);
346 ASSERT (HiiHandles
!= NULL
);
349 // Search for formset of each class type
351 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
353 // Check HiiHandles[Index] does exist in global maintain list.
355 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
360 // Initilize FormSet Setting
362 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
363 ASSERT (LocalFormSet
!= NULL
);
364 mSystemLevelFormSet
= LocalFormSet
;
366 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
367 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
368 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
369 DestroyFormSet (LocalFormSet
);
372 InitializeCurrentSetting (LocalFormSet
);
375 // Initilize Questions' Value
377 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
378 if (EFI_ERROR (Status
)) {
379 DestroyFormSet (LocalFormSet
);
385 // Free resources, and restore gOldFormSet and gClassOfVfr
387 FreePool (HiiHandles
);
389 mSystemLevelFormSet
= OldFormset
;
393 Pop up the error info.
395 @param BrowserStatus The input browser status.
396 @param HiiHandle The Hiihandle for this opcode.
397 @param OpCode The opcode use to get the erro info and timeout value.
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
403 IN UINT32 BrowserStatus
,
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
406 IN CHAR16
*ErrorString
409 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
410 USER_INPUT UserInputData
;
414 if (OpCode
!= NULL
) {
415 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
416 ASSERT (Statement
!= NULL
);
417 Statement
->OpCode
= OpCode
;
418 gDisplayFormData
.HighLightedStatement
= Statement
;
422 // Used to compatible with old display engine.
423 // New display engine not use this field.
425 gDisplayFormData
.ErrorString
= ErrorString
;
426 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
428 if (HiiHandle
!= NULL
) {
429 gDisplayFormData
.HiiHandle
= HiiHandle
;
432 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
434 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
435 gDisplayFormData
.ErrorString
= NULL
;
437 if (OpCode
!= NULL
) {
438 FreePool (Statement
);
441 return UserInputData
.Action
;
445 This is the routine which an external caller uses to direct the browser
446 where to obtain it's information.
449 @param This The Form Browser protocol instanse.
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
451 display a list of the formsets for the handles specified.
452 @param HandleCount The number of Handles specified in Handle.
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
454 field in the EFI_IFR_FORM_SET op-code for the specified
455 forms-based package. If FormSetGuid is NULL, then this
456 function will display the first found forms package.
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first
458 displayable page. If this field has a value of 0x0000, then
459 the forms browser will render the specified forms in their encoded order.
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
462 @param ActionRequest Points to the action recommended by the form.
464 @retval EFI_SUCCESS The function completed successfully.
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
466 @retval EFI_NOT_FOUND No valid forms could be found to display.
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
473 IN EFI_HII_HANDLE
*Handles
,
474 IN UINTN HandleCount
,
475 IN EFI_GUID
*FormSetGuid
, OPTIONAL
476 IN UINT16 FormId
, OPTIONAL
477 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
482 UI_MENU_SELECTION
*Selection
;
484 FORM_BROWSER_FORMSET
*FormSet
;
485 FORM_ENTRY_INFO
*MenuList
;
489 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
491 if (mFormDisplay
== NULL
) {
492 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
493 return EFI_UNSUPPORTED
;
497 // Save globals used by SendForm()
499 SaveBrowserContext ();
501 gFlagReconnect
= FALSE
;
502 gResetRequired
= FALSE
;
503 gExitRequired
= FALSE
;
504 gCallbackReconnect
= FALSE
;
505 Status
= EFI_SUCCESS
;
507 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
509 for (Index
= 0; Index
< HandleCount
; Index
++) {
510 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
511 ASSERT (Selection
!= NULL
);
513 Selection
->Handle
= Handles
[Index
];
514 if (FormSetGuid
!= NULL
) {
515 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
516 Selection
->FormId
= FormId
;
518 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
522 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
523 ASSERT (FormSet
!= NULL
);
526 // Validate the HiiHandle
527 // if validate failed, find the first validate parent HiiHandle.
529 if (!ValidateHiiHandle(Selection
->Handle
)) {
530 FindNextMenu (Selection
, FormSetLevel
);
534 // Initialize internal data structures of FormSet
536 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
537 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
538 DestroyFormSet (FormSet
);
541 Selection
->FormSet
= FormSet
;
542 mSystemLevelFormSet
= FormSet
;
545 // Display this formset
547 gCurrentSelection
= Selection
;
549 Status
= SetupBrowser (Selection
);
551 gCurrentSelection
= NULL
;
552 mSystemLevelFormSet
= NULL
;
554 if (gFlagReconnect
|| gCallbackReconnect
) {
555 RetVal
= ReconnectController (FormSet
->DriverHandle
);
557 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
559 gFlagReconnect
= FALSE
;
560 gCallbackReconnect
= FALSE
;
564 // If no data is changed, don't need to save current FormSet into the maintain list.
566 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
567 CleanBrowserStorage(FormSet
);
568 RemoveEntryList (&FormSet
->Link
);
569 DestroyFormSet (FormSet
);
572 if (EFI_ERROR (Status
)) {
575 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
577 FreePool (Selection
);
580 if (ActionRequest
!= NULL
) {
581 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
582 if (gResetRequired
) {
583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
587 mFormDisplay
->ExitDisplay();
590 // Clear the menu history data.
592 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
593 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
594 RemoveEntryList (&MenuList
->Link
);
599 // Restore globals used by SendForm()
601 RestoreBrowserContext ();
607 Get or set data to the storage.
609 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
610 @param ResultsData A string returned from an IFR browser or
611 equivalent. The results string will have no
612 routing information in them.
613 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
614 (if RetrieveData = TRUE) data from the uncommitted
615 browser state information or set (if RetrieveData
616 = FALSE) data in the uncommitted browser state
618 @param Storage The pointer to the storage.
620 @retval EFI_SUCCESS The results have been distributed or are awaiting
626 IN OUT UINTN
*ResultsDataSize
,
627 IN OUT EFI_STRING
*ResultsData
,
628 IN BOOLEAN RetrieveData
,
629 IN BROWSER_STORAGE
*Storage
638 FORMSET_STORAGE
*BrowserStorage
;
642 // Generate <ConfigResp>
644 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
645 if (EFI_ERROR (Status
)) {
650 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
651 // Also need to consider add "\0" at first time.
653 StrPtr
= StrStr (ConfigResp
, L
"PATH");
654 ASSERT (StrPtr
!= NULL
);
655 StrPtr
= StrStr (StrPtr
, L
"&");
657 BufferSize
= StrSize (StrPtr
);
660 // Copy the data if the input buffer is bigger enough.
662 if (*ResultsDataSize
>= BufferSize
) {
663 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
666 *ResultsDataSize
= BufferSize
;
667 FreePool (ConfigResp
);
670 // Prepare <ConfigResp>
672 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
673 ASSERT (BrowserStorage
!= NULL
);
674 TmpSize
= StrLen (*ResultsData
);
675 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
676 MaxLen
= BufferSize
/ sizeof (CHAR16
);
677 ConfigResp
= AllocateZeroPool (BufferSize
);
678 ASSERT (ConfigResp
!= NULL
);
680 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
681 StrCatS (ConfigResp
, MaxLen
, L
"&");
682 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
685 // Update Browser uncommited data
687 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
688 FreePool (ConfigResp
);
689 if (EFI_ERROR (Status
)) {
698 This routine called this service in the browser to retrieve or set certain uncommitted
699 state information that resides in the open formsets.
701 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
703 @param ResultsDataSize A pointer to the size of the buffer associated
705 @param ResultsData A string returned from an IFR browser or
706 equivalent. The results string will have no
707 routing information in them.
708 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
709 (if RetrieveData = TRUE) data from the uncommitted
710 browser state information or set (if RetrieveData
711 = FALSE) data in the uncommitted browser state
713 @param VariableGuid An optional field to indicate the target variable
715 @param VariableName An optional field to indicate the target
716 human-readable variable name.
718 @retval EFI_SUCCESS The results have been distributed or are awaiting
720 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
721 contain the results data.
727 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
728 IN OUT UINTN
*ResultsDataSize
,
729 IN OUT EFI_STRING ResultsData
,
730 IN BOOLEAN RetrieveData
,
731 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
732 IN CONST CHAR16
*VariableName OPTIONAL
737 BROWSER_STORAGE
*Storage
;
738 FORMSET_STORAGE
*FormsetStorage
;
742 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
743 return EFI_INVALID_PARAMETER
;
746 TotalSize
= *ResultsDataSize
;
749 Status
= EFI_SUCCESS
;
751 if (VariableGuid
!= NULL
) {
753 // Try to find target storage in the current formset.
755 Link
= GetFirstNode (&gBrowserStorageList
);
756 while (!IsNull (&gBrowserStorageList
, Link
)) {
757 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
758 Link
= GetNextNode (&gBrowserStorageList
, Link
);
760 // Check the current storage.
762 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
766 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
767 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
769 // Buffer storage require both GUID and Name
771 if (VariableName
== NULL
) {
772 return EFI_NOT_FOUND
;
775 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
780 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
781 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
782 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
783 return EFI_NOT_FOUND
;
786 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
791 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
792 if (EFI_ERROR (Status
)) {
796 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
797 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
801 // Different formsets may have same varstore, so here just set the flag
802 // not exit the circle.
809 return EFI_NOT_FOUND
;
813 // GUID/Name is not specified, take the first storage in FormSet
815 if (mSystemLevelFormSet
== NULL
) {
816 return EFI_NOT_READY
;
820 // Generate <ConfigResp>
822 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
823 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
824 return EFI_UNSUPPORTED
;
827 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
829 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
830 if (EFI_ERROR (Status
)) {
836 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
837 *ResultsDataSize
= TotalSize
;
846 Callback function for SimpleTextInEx protocol install events
848 @param Event the event that is signaled.
849 @param Context not used here.
854 FormDisplayCallback (
859 if (mFormDisplay
!= NULL
) {
863 gBS
->LocateProtocol (
864 &gEdkiiFormDisplayEngineProtocolGuid
,
866 (VOID
**) &mFormDisplay
871 Initialize Setup Browser driver.
873 @param ImageHandle The image handle.
874 @param SystemTable The system table.
876 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
877 @return Other value if failed to initialize the Setup Browser module.
883 IN EFI_HANDLE ImageHandle
,
884 IN EFI_SYSTEM_TABLE
*SystemTable
891 // Locate required Hii relative protocols
893 Status
= gBS
->LocateProtocol (
894 &gEfiHiiDatabaseProtocolGuid
,
896 (VOID
**) &mHiiDatabase
898 ASSERT_EFI_ERROR (Status
);
900 Status
= gBS
->LocateProtocol (
901 &gEfiHiiConfigRoutingProtocolGuid
,
903 (VOID
**) &mHiiConfigRouting
905 ASSERT_EFI_ERROR (Status
);
907 Status
= gBS
->LocateProtocol (
908 &gEfiDevicePathFromTextProtocolGuid
,
910 (VOID
**) &mPathFromText
914 // Install FormBrowser2 protocol
916 mPrivateData
.Handle
= NULL
;
917 Status
= gBS
->InstallProtocolInterface (
918 &mPrivateData
.Handle
,
919 &gEfiFormBrowser2ProtocolGuid
,
920 EFI_NATIVE_INTERFACE
,
921 &mPrivateData
.FormBrowser2
923 ASSERT_EFI_ERROR (Status
);
926 // Install FormBrowserEx2 protocol
928 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
929 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
930 mPrivateData
.Handle
= NULL
;
931 Status
= gBS
->InstallProtocolInterface (
932 &mPrivateData
.Handle
,
933 &gEdkiiFormBrowserEx2ProtocolGuid
,
934 EFI_NATIVE_INTERFACE
,
935 &mPrivateData
.FormBrowserEx2
937 ASSERT_EFI_ERROR (Status
);
939 Status
= gBS
->InstallProtocolInterface (
940 &mPrivateData
.Handle
,
941 &gEfiFormBrowserExProtocolGuid
,
942 EFI_NATIVE_INTERFACE
,
943 &mPrivateData
.FormBrowserEx
945 ASSERT_EFI_ERROR (Status
);
947 InitializeDisplayFormData ();
949 Status
= gBS
->LocateProtocol (
950 &gEdkiiFormDisplayEngineProtocolGuid
,
952 (VOID
**) &mFormDisplay
955 if (EFI_ERROR (Status
)) {
956 EfiCreateProtocolNotifyEvent (
957 &gEdkiiFormDisplayEngineProtocolGuid
,
970 Create a new string in HII Package List.
972 @param String The String to be added
973 @param HiiHandle The package list in the HII database to insert the
976 @return The output string.
982 IN EFI_HII_HANDLE HiiHandle
985 EFI_STRING_ID StringId
;
987 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
988 ASSERT (StringId
!= 0);
995 Delete a string from HII Package List.
997 @param StringId Id of the string in HII database.
998 @param HiiHandle The HII package list handle.
1000 @retval EFI_SUCCESS The string was deleted successfully.
1005 IN EFI_STRING_ID StringId
,
1006 IN EFI_HII_HANDLE HiiHandle
1011 NullChar
= CHAR_NULL
;
1012 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1018 Get the string based on the StringId and HII Package List Handle.
1020 @param Token The String's ID.
1021 @param HiiHandle The package list in the HII database to search for
1022 the specified string.
1024 @return The output string.
1029 IN EFI_STRING_ID Token
,
1030 IN EFI_HII_HANDLE HiiHandle
1035 if (HiiHandle
== NULL
) {
1039 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1040 if (String
== NULL
) {
1041 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1042 ASSERT (String
!= NULL
);
1044 return (CHAR16
*) String
;
1049 Allocate new memory and then copy the Unicode string Source to Destination.
1051 @param Dest Location to copy string
1052 @param Src String to copy
1057 IN OUT CHAR16
**Dest
,
1061 if (*Dest
!= NULL
) {
1064 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1065 ASSERT (*Dest
!= NULL
);
1070 Allocate new memory and concatinate Source on the end of Destination.
1072 @param Dest String to added to the end of.
1073 @param Src String to concatinate.
1078 IN OUT CHAR16
**Dest
,
1085 if (*Dest
== NULL
) {
1086 NewStringCpy (Dest
, Src
);
1090 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1091 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1092 ASSERT (NewString
!= NULL
);
1094 StrCpyS (NewString
, MaxLen
, *Dest
);
1095 StrCatS (NewString
, MaxLen
, Src
);
1102 Get Value for given Name from a NameValue Storage.
1104 @param Storage The NameValue Storage.
1105 @param Name The Name.
1106 @param Value The retured Value.
1107 @param GetValueFrom Where to get source value, from EditValue or Value.
1109 @retval EFI_SUCCESS Value found for given Name.
1110 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1115 IN BROWSER_STORAGE
*Storage
,
1117 IN OUT CHAR16
**Value
,
1118 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1122 NAME_VALUE_NODE
*Node
;
1124 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1125 return EFI_INVALID_PARAMETER
;
1130 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1131 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1132 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1134 if (StrCmp (Name
, Node
->Name
) == 0) {
1135 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1136 NewStringCpy (Value
, Node
->EditValue
);
1138 NewStringCpy (Value
, Node
->Value
);
1143 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1146 return EFI_NOT_FOUND
;
1151 Set Value of given Name in a NameValue Storage.
1153 @param Storage The NameValue Storage.
1154 @param Name The Name.
1155 @param Value The Value to set.
1156 @param SetValueTo Whether update editValue or Value.
1157 @param ReturnNode The node use the input name.
1159 @retval EFI_SUCCESS Value found for given Name.
1160 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1165 IN BROWSER_STORAGE
*Storage
,
1168 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1169 OUT NAME_VALUE_NODE
**ReturnNode
1173 NAME_VALUE_NODE
*Node
;
1176 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1177 return EFI_INVALID_PARAMETER
;
1180 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1181 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1182 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1184 if (StrCmp (Name
, Node
->Name
) == 0) {
1185 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1186 Buffer
= Node
->EditValue
;
1188 Buffer
= Node
->Value
;
1190 if (Buffer
!= NULL
) {
1193 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1194 ASSERT (Buffer
!= NULL
);
1195 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1196 Node
->EditValue
= Buffer
;
1198 Node
->Value
= Buffer
;
1201 if (ReturnNode
!= NULL
) {
1208 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1211 return EFI_NOT_FOUND
;
1216 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1218 @param Storage The Storage to be conveted.
1219 @param ConfigResp The returned <ConfigResp>.
1220 @param ConfigRequest The ConfigRequest string.
1221 @param GetEditBuf Get the data from editbuffer or buffer.
1223 @retval EFI_SUCCESS Convert success.
1224 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1228 StorageToConfigResp (
1229 IN BROWSER_STORAGE
*Storage
,
1230 IN CHAR16
**ConfigResp
,
1231 IN CHAR16
*ConfigRequest
,
1232 IN BOOLEAN GetEditBuf
1236 EFI_STRING Progress
;
1238 NAME_VALUE_NODE
*Node
;
1240 FORMSET_STORAGE
*FormsetStorage
;
1242 Status
= EFI_SUCCESS
;
1244 switch (Storage
->Type
) {
1245 case EFI_HII_VARSTORE_BUFFER
:
1246 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1247 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1248 Status
= mHiiConfigRouting
->BlockToConfig (
1258 case EFI_HII_VARSTORE_NAME_VALUE
:
1260 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1261 ASSERT (FormsetStorage
!= NULL
);
1262 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1264 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1265 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1266 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1268 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1269 NewStringCat (ConfigResp
, L
"&");
1270 NewStringCat (ConfigResp
, Node
->Name
);
1271 NewStringCat (ConfigResp
, L
"=");
1273 NewStringCat (ConfigResp
, Node
->EditValue
);
1275 NewStringCat (ConfigResp
, Node
->Value
);
1278 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1282 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1284 Status
= EFI_INVALID_PARAMETER
;
1293 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1295 @param Storage The Storage to receive the settings.
1296 @param ConfigResp The <ConfigResp> to be converted.
1298 @retval EFI_SUCCESS Convert success.
1299 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1303 ConfigRespToStorage (
1304 IN BROWSER_STORAGE
*Storage
,
1305 IN CHAR16
*ConfigResp
1309 EFI_STRING Progress
;
1315 Status
= EFI_SUCCESS
;
1317 switch (Storage
->Type
) {
1318 case EFI_HII_VARSTORE_BUFFER
:
1319 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1320 BufferSize
= Storage
->Size
;
1321 Status
= mHiiConfigRouting
->ConfigToBlock (
1324 Storage
->EditBuffer
,
1330 case EFI_HII_VARSTORE_NAME_VALUE
:
1331 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1332 if (StrPtr
== NULL
) {
1335 StrPtr
= StrStr (ConfigResp
, L
"&");
1336 while (StrPtr
!= NULL
) {
1340 StrPtr
= StrPtr
+ 1;
1342 StrPtr
= StrStr (StrPtr
, L
"=");
1343 if (StrPtr
== NULL
) {
1351 StrPtr
= StrPtr
+ 1;
1353 StrPtr
= StrStr (StrPtr
, L
"&");
1354 if (StrPtr
!= NULL
) {
1357 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1361 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1363 Status
= EFI_INVALID_PARAMETER
;
1371 Convert the buffer value to HiiValue.
1373 @param Question The question.
1374 @param Value Unicode buffer save the question value.
1376 @retval Status whether convert the value success.
1381 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1386 BOOLEAN IsBufferStorage
;
1398 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1399 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1400 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1401 IsBufferStorage
= TRUE
;
1403 IsBufferStorage
= FALSE
;
1407 // Question Value is provided by Buffer Storage or NameValue Storage
1409 if (Question
->BufferValue
!= NULL
) {
1411 // This Question is password or orderedlist
1413 Dst
= Question
->BufferValue
;
1416 // Other type of Questions
1418 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1422 // Temp cut at the end of this section, end with '\0' or '&'.
1425 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1428 TempChar
= *StringPtr
;
1431 LengthStr
= StrLen (Value
);
1432 Status
= EFI_SUCCESS
;
1433 if (!IsBufferStorage
&& IsString
) {
1435 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1436 // Add string tail char L'\0' into Length
1438 Length
= Question
->StorageWidth
+ sizeof (CHAR16
);
1439 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1440 Status
= EFI_BUFFER_TOO_SMALL
;
1442 DstBuf
= (CHAR16
*) Dst
;
1443 ZeroMem (TemStr
, sizeof (TemStr
));
1444 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1445 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1446 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1449 // Add tailing L'\0' character
1451 DstBuf
[Index
/4] = L
'\0';
1454 if (Question
->StorageWidth
< ((LengthStr
+ 1) / 2)) {
1455 Status
= EFI_BUFFER_TOO_SMALL
;
1457 ZeroMem (TemStr
, sizeof (TemStr
));
1458 for (Index
= 0; Index
< LengthStr
; Index
++) {
1459 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1460 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1461 if ((Index
& 1) == 0) {
1462 Dst
[Index
/2] = DigitUint8
;
1464 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1470 *StringPtr
= TempChar
;
1476 Get Question's current Value.
1478 @param FormSet FormSet data structure.
1479 @param Form Form data structure.
1480 @param Question Question to be initialized.
1481 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1483 @retval EFI_SUCCESS The function completed successfully.
1488 IN FORM_BROWSER_FORMSET
*FormSet
,
1489 IN FORM_BROWSER_FORM
*Form
,
1490 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1491 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1500 BROWSER_STORAGE
*Storage
;
1501 FORMSET_STORAGE
*FormsetStorage
;
1502 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1503 CHAR16
*ConfigRequest
;
1508 BOOLEAN IsBufferStorage
;
1511 Status
= EFI_SUCCESS
;
1515 if (GetValueFrom
>= GetSetValueWithMax
) {
1516 return EFI_INVALID_PARAMETER
;
1520 // Question value is provided by an Expression, evaluate it
1522 if (Question
->ValueExpression
!= NULL
) {
1523 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1524 if (!EFI_ERROR (Status
)) {
1525 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1526 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1527 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1528 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1529 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1531 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1532 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1534 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1536 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1537 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1543 // Get question value by read expression.
1545 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1546 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1547 if (!EFI_ERROR (Status
) &&
1548 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1550 // Only update question value to the valid result.
1552 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1553 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1554 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1555 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1556 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1558 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1559 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1561 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1563 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1564 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1570 // Question value is provided by RTC
1572 Storage
= Question
->Storage
;
1573 QuestionValue
= &Question
->HiiValue
.Value
;
1574 if (Storage
== NULL
) {
1576 // It's a Question without storage, or RTC date/time
1578 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1580 // Date and time define the same Flags bit
1582 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1583 case QF_DATE_STORAGE_TIME
:
1584 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1587 case QF_DATE_STORAGE_WAKEUP
:
1588 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1591 case QF_DATE_STORAGE_NORMAL
:
1594 // For date/time without storage
1599 if (EFI_ERROR (Status
)) {
1600 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1601 QuestionValue
->date
.Year
= 0xff;
1602 QuestionValue
->date
.Month
= 0xff;
1603 QuestionValue
->date
.Day
= 0xff;
1605 QuestionValue
->time
.Hour
= 0xff;
1606 QuestionValue
->time
.Minute
= 0xff;
1607 QuestionValue
->time
.Second
= 0xff;
1612 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1613 QuestionValue
->date
.Year
= EfiTime
.Year
;
1614 QuestionValue
->date
.Month
= EfiTime
.Month
;
1615 QuestionValue
->date
.Day
= EfiTime
.Day
;
1617 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1618 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1619 QuestionValue
->time
.Second
= EfiTime
.Second
;
1627 // Question value is provided by EFI variable
1629 StorageWidth
= Question
->StorageWidth
;
1630 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1631 if (Question
->BufferValue
!= NULL
) {
1632 Dst
= Question
->BufferValue
;
1634 Dst
= (UINT8
*) QuestionValue
;
1637 Status
= gRT
->GetVariable (
1638 Question
->VariableName
,
1645 // Always return success, even this EFI variable doesn't exist
1651 // Question Value is provided by Buffer Storage or NameValue Storage
1653 if (Question
->BufferValue
!= NULL
) {
1655 // This Question is password or orderedlist
1657 Dst
= Question
->BufferValue
;
1660 // Other type of Questions
1662 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1665 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1666 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1667 IsBufferStorage
= TRUE
;
1669 IsBufferStorage
= FALSE
;
1671 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1672 if (IsBufferStorage
) {
1673 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1675 // Copy from storage Edit buffer
1677 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1680 // Copy from storage Edit buffer
1682 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1686 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1687 if (EFI_ERROR (Status
)) {
1691 ASSERT (Value
!= NULL
);
1692 Status
= BufferToValue (Question
, Value
);
1696 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1697 ASSERT (FormsetStorage
!= NULL
);
1699 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1700 // <ConfigHdr> + "&" + <VariableName>
1702 if (IsBufferStorage
) {
1703 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1704 Length
+= StrLen (Question
->BlockName
);
1706 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1707 Length
+= StrLen (Question
->VariableName
) + 1;
1709 // Allocate buffer include '\0'
1710 MaxLen
= Length
+ 1;
1711 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1712 ASSERT (ConfigRequest
!= NULL
);
1714 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1715 if (IsBufferStorage
) {
1716 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1718 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1719 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1723 // Request current settings from Configuration Driver
1725 Status
= mHiiConfigRouting
->ExtractConfig (
1731 FreePool (ConfigRequest
);
1732 if (EFI_ERROR (Status
)) {
1737 // Skip <ConfigRequest>
1739 if (IsBufferStorage
) {
1740 Value
= StrStr (Result
, L
"&VALUE");
1741 if (Value
== NULL
) {
1743 return EFI_NOT_FOUND
;
1750 Value
= Result
+ Length
;
1752 if (*Value
!= '=') {
1754 return EFI_NOT_FOUND
;
1757 // Skip '=', point to value
1761 Status
= BufferToValue (Question
, Value
);
1762 if (EFI_ERROR (Status
)) {
1768 // Synchronize Edit Buffer
1770 if (IsBufferStorage
) {
1771 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1773 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1776 if (Result
!= NULL
) {
1786 Save Question Value to edit copy(cached) or Storage(uncached).
1788 @param FormSet FormSet data structure.
1789 @param Form Form data structure.
1790 @param Question Pointer to the Question.
1791 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1793 @retval EFI_SUCCESS The function completed successfully.
1798 IN FORM_BROWSER_FORMSET
*FormSet
,
1799 IN FORM_BROWSER_FORM
*Form
,
1800 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1801 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1811 BROWSER_STORAGE
*Storage
;
1812 FORMSET_STORAGE
*FormsetStorage
;
1813 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1818 BOOLEAN IsBufferStorage
;
1824 NAME_VALUE_NODE
*Node
;
1827 Status
= EFI_SUCCESS
;
1830 if (SetValueTo
>= GetSetValueWithMax
) {
1831 return EFI_INVALID_PARAMETER
;
1835 // If Question value is provided by an Expression, then it is read only
1837 if (Question
->ValueExpression
!= NULL
) {
1842 // Before set question value, evaluate its write expression.
1844 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1845 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1846 if (EFI_ERROR (Status
)) {
1852 // Question value is provided by RTC
1854 Storage
= Question
->Storage
;
1855 QuestionValue
= &Question
->HiiValue
.Value
;
1856 if (Storage
== NULL
) {
1858 // It's a Question without storage, or RTC date/time
1860 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1862 // Date and time define the same Flags bit
1864 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1865 case QF_DATE_STORAGE_TIME
:
1866 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1869 case QF_DATE_STORAGE_WAKEUP
:
1870 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1873 case QF_DATE_STORAGE_NORMAL
:
1876 // For date/time without storage
1881 if (EFI_ERROR (Status
)) {
1885 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1886 EfiTime
.Year
= QuestionValue
->date
.Year
;
1887 EfiTime
.Month
= QuestionValue
->date
.Month
;
1888 EfiTime
.Day
= QuestionValue
->date
.Day
;
1890 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1891 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1892 EfiTime
.Second
= QuestionValue
->time
.Second
;
1895 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1896 Status
= gRT
->SetTime (&EfiTime
);
1898 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1906 // Question value is provided by EFI variable
1908 StorageWidth
= Question
->StorageWidth
;
1909 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1910 if (Question
->BufferValue
!= NULL
) {
1911 Src
= Question
->BufferValue
;
1913 Src
= (UINT8
*) QuestionValue
;
1916 Status
= gRT
->SetVariable (
1917 Question
->VariableName
,
1919 Storage
->Attributes
,
1927 // Question Value is provided by Buffer Storage or NameValue Storage
1929 if (Question
->BufferValue
!= NULL
) {
1930 Src
= Question
->BufferValue
;
1932 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1935 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1936 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1937 IsBufferStorage
= TRUE
;
1939 IsBufferStorage
= FALSE
;
1941 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1943 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1944 if (IsBufferStorage
) {
1945 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1947 // Copy to storage edit buffer
1949 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1950 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1952 // Copy to storage edit buffer
1954 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1959 // Allocate enough string buffer.
1962 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1963 Value
= AllocateZeroPool (BufferLen
);
1964 ASSERT (Value
!= NULL
);
1966 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1968 TemName
= (CHAR16
*) Src
;
1970 for (; *TemName
!= L
'\0'; TemName
++) {
1971 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1974 BufferLen
= StorageWidth
* 2 + 1;
1975 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1976 ASSERT (Value
!= NULL
);
1978 // Convert Buffer to Hex String
1980 TemBuffer
= Src
+ StorageWidth
- 1;
1982 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1983 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1987 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1989 if (EFI_ERROR (Status
)) {
1993 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1995 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1996 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1998 if (IsBufferStorage
) {
1999 Length
= StrLen (Question
->BlockName
) + 7;
2001 Length
= StrLen (Question
->VariableName
) + 2;
2003 if (!IsBufferStorage
&& IsString
) {
2004 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2006 Length
+= (StorageWidth
* 2);
2008 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2009 ASSERT (FormsetStorage
!= NULL
);
2010 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2011 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2012 ASSERT (ConfigResp
!= NULL
);
2014 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2015 if (IsBufferStorage
) {
2016 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2017 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2019 StrCatS (ConfigResp
, MaxLen
, L
"&");
2020 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2021 StrCatS (ConfigResp
, MaxLen
, L
"=");
2024 Value
= ConfigResp
+ StrLen (ConfigResp
);
2026 if (!IsBufferStorage
&& IsString
) {
2028 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2030 TemName
= (CHAR16
*) Src
;
2032 for (; *TemName
!= L
'\0'; TemName
++) {
2033 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
2037 // Convert Buffer to Hex String
2039 TemBuffer
= Src
+ StorageWidth
- 1;
2041 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2042 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2047 // Convert to lower char.
2049 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2050 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2051 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2056 // Submit Question Value to Configuration Driver
2058 Status
= mHiiConfigRouting
->RouteConfig (
2063 if (EFI_ERROR (Status
)) {
2064 FreePool (ConfigResp
);
2067 FreePool (ConfigResp
);
2070 // Sync storage, from editbuffer to buffer.
2072 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2080 Perform nosubmitif check for a Form.
2082 @param FormSet FormSet data structure.
2083 @param Form Form data structure.
2084 @param Question The Question to be validated.
2085 @param Type Validation type: NoSubmit
2087 @retval EFI_SUCCESS Form validation pass.
2088 @retval other Form validation failed.
2093 IN FORM_BROWSER_FORMSET
*FormSet
,
2094 IN FORM_BROWSER_FORM
*Form
,
2095 IN FORM_BROWSER_STATEMENT
*Question
,
2101 LIST_ENTRY
*ListHead
;
2102 FORM_EXPRESSION
*Expression
;
2103 UINT32 BrowserStatus
;
2106 BrowserStatus
= BROWSER_SUCCESS
;
2110 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2111 ListHead
= &Question
->InconsistentListHead
;
2114 case EFI_HII_EXPRESSION_WARNING_IF
:
2115 ListHead
= &Question
->WarningListHead
;
2118 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2119 ListHead
= &Question
->NoSubmitListHead
;
2124 return EFI_UNSUPPORTED
;
2127 Link
= GetFirstNode (ListHead
);
2128 while (!IsNull (ListHead
, Link
)) {
2129 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2132 // Evaluate the expression
2134 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2135 if (EFI_ERROR (Status
)) {
2139 if (IsTrue (&Expression
->Result
)) {
2141 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2142 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2145 case EFI_HII_EXPRESSION_WARNING_IF
:
2146 BrowserStatus
= BROWSER_WARNING_IF
;
2149 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2150 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2152 // This code only used to compatible with old display engine,
2153 // New display engine will not use this field.
2155 if (Expression
->Error
!= 0) {
2156 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2165 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2167 // If in system submit process and for no_submit_if check, not popup this error message.
2168 // Will process this fail again later in not system submit process.
2170 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2173 if (ErrorStr
!= NULL
) {
2174 FreePool (ErrorStr
);
2177 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2180 return EFI_NOT_READY
;
2184 Link
= GetNextNode (ListHead
, Link
);
2191 Perform question check.
2193 If one question has more than one check, process form high priority to low.
2194 Only one error info will be popup.
2196 @param FormSet FormSet data structure.
2197 @param Form Form data structure.
2198 @param Question The Question to be validated.
2200 @retval EFI_SUCCESS Form validation pass.
2201 @retval other Form validation failed.
2205 ValueChangedValidation (
2206 IN FORM_BROWSER_FORMSET
*FormSet
,
2207 IN FORM_BROWSER_FORM
*Form
,
2208 IN FORM_BROWSER_STATEMENT
*Question
2213 Status
= EFI_SUCCESS
;
2216 // Do the inconsistentif check.
2218 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2219 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2220 if (EFI_ERROR (Status
)) {
2226 // Do the warningif check.
2228 if (!IsListEmpty (&Question
->WarningListHead
)) {
2229 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2236 Perform NoSubmit check for each Form in FormSet.
2238 @param FormSet FormSet data structure.
2239 @param CurrentForm Current input form data structure.
2240 @param Statement The statement for this check.
2242 @retval EFI_SUCCESS Form validation pass.
2243 @retval other Form validation failed.
2248 IN FORM_BROWSER_FORMSET
*FormSet
,
2249 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2250 OUT FORM_BROWSER_STATEMENT
**Statement
2255 FORM_BROWSER_STATEMENT
*Question
;
2256 FORM_BROWSER_FORM
*Form
;
2257 LIST_ENTRY
*LinkForm
;
2259 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2260 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2261 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2262 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2264 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2268 Link
= GetFirstNode (&Form
->StatementListHead
);
2269 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2270 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2271 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2272 if (EFI_ERROR (Status
)) {
2273 if (*CurrentForm
== NULL
) {
2274 *CurrentForm
= Form
;
2276 if (Statement
!= NULL
) {
2277 *Statement
= Question
;
2282 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2290 Fill storage's edit copy with settings requested from Configuration Driver.
2292 @param Storage The storage which need to sync.
2293 @param ConfigRequest The config request string which used to sync storage.
2294 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2295 editbuffer to buffer
2296 if TRUE, copy the editbuffer to the buffer.
2297 if FALSE, copy the buffer to the editbuffer.
2299 @retval EFI_SUCCESS The function completed successfully.
2303 SynchronizeStorage (
2304 OUT BROWSER_STORAGE
*Storage
,
2305 IN CHAR16
*ConfigRequest
,
2306 IN BOOLEAN SyncOrRestore
2310 EFI_STRING Progress
;
2314 NAME_VALUE_NODE
*Node
;
2318 Status
= EFI_SUCCESS
;
2321 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2322 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2323 BufferSize
= Storage
->Size
;
2325 if (SyncOrRestore
) {
2326 Src
= Storage
->EditBuffer
;
2327 Dst
= Storage
->Buffer
;
2329 Src
= Storage
->Buffer
;
2330 Dst
= Storage
->EditBuffer
;
2333 if (ConfigRequest
!= NULL
) {
2334 Status
= mHiiConfigRouting
->BlockToConfig(
2342 if (EFI_ERROR (Status
)) {
2346 Status
= mHiiConfigRouting
->ConfigToBlock (
2353 if (Result
!= NULL
) {
2357 CopyMem (Dst
, Src
, BufferSize
);
2359 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2360 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2361 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2362 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2364 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2365 (ConfigRequest
== NULL
)) {
2366 if (SyncOrRestore
) {
2367 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2369 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2373 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2381 When discard the question value, call the callback function with Changed type
2382 to inform the hii driver.
2384 @param FormSet FormSet data structure.
2385 @param Form Form data structure.
2389 SendDiscardInfoToDriver (
2390 IN FORM_BROWSER_FORMSET
*FormSet
,
2391 IN FORM_BROWSER_FORM
*Form
2395 FORM_BROWSER_STATEMENT
*Question
;
2396 EFI_IFR_TYPE_VALUE
*TypeValue
;
2397 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2399 if (FormSet
->ConfigAccess
== NULL
) {
2403 Link
= GetFirstNode (&Form
->StatementListHead
);
2404 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2405 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2406 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2408 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2412 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2416 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2420 if (!Question
->ValueChanged
) {
2425 // Restore the question value before call the CHANGED callback type.
2427 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2429 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2430 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2432 TypeValue
= &Question
->HiiValue
.Value
;
2435 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2436 FormSet
->ConfigAccess
->Callback (
2437 FormSet
->ConfigAccess
,
2438 EFI_BROWSER_ACTION_CHANGED
,
2439 Question
->QuestionId
,
2440 Question
->HiiValue
.Type
,
2448 Validate the HiiHandle.
2450 @param HiiHandle The input HiiHandle which need to validate.
2452 @retval TRUE The handle is validate.
2453 @retval FALSE The handle is invalidate.
2458 EFI_HII_HANDLE HiiHandle
2461 EFI_HII_HANDLE
*HiiHandles
;
2465 if (HiiHandle
== NULL
) {
2471 HiiHandles
= HiiGetHiiHandles (NULL
);
2472 ASSERT (HiiHandles
!= NULL
);
2474 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2475 if (HiiHandles
[Index
] == HiiHandle
) {
2481 FreePool (HiiHandles
);
2487 Validate the FormSet. If the formset is not validate, remove it from the list.
2489 @param FormSet The input FormSet which need to validate.
2491 @retval TRUE The handle is validate.
2492 @retval FALSE The handle is invalidate.
2497 FORM_BROWSER_FORMSET
*FormSet
2502 ASSERT (FormSet
!= NULL
);
2504 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2506 // Should not remove the formset which is being used.
2508 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2509 CleanBrowserStorage(FormSet
);
2510 RemoveEntryList (&FormSet
->Link
);
2511 DestroyFormSet (FormSet
);
2517 Check whether need to enable the reset flag in form level.
2518 Also clean all ValueChanged flag in question.
2520 @param SetFlag Whether need to set the Reset Flag.
2521 @param FormSet FormSet data structure.
2522 @param Form Form data structure.
2528 IN FORM_BROWSER_FORMSET
*FormSet
,
2529 IN FORM_BROWSER_FORM
*Form
2533 FORM_BROWSER_STATEMENT
*Question
;
2536 Link
= GetFirstNode (&Form
->StatementListHead
);
2537 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2538 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2539 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2541 if (!Question
->ValueChanged
) {
2545 OldValue
= Question
->ValueChanged
;
2548 // Compare the buffer and editbuffer data to see whether the data has been saved.
2550 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2553 // Only the changed data has been saved, then need to set the reset flag.
2555 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2556 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2557 gResetRequired
= TRUE
;
2560 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2561 gFlagReconnect
= TRUE
;
2568 Check whether need to enable the reset flag.
2569 Also clean ValueChanged flag for all statements.
2571 Form level or formset level, only one.
2573 @param SetFlag Whether need to set the Reset Flag.
2574 @param FormSet FormSet data structure.
2575 @param Form Form data structure.
2579 ValueChangeResetFlagUpdate (
2581 IN FORM_BROWSER_FORMSET
*FormSet
,
2582 IN FORM_BROWSER_FORM
*Form
2585 FORM_BROWSER_FORM
*CurrentForm
;
2589 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2593 Link
= GetFirstNode (&FormSet
->FormListHead
);
2594 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2595 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2596 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2598 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2603 Base on the return Progress string to find the form.
2605 Base on the first return Offset/Width (Name) string to find the form
2606 which keep this string.
2608 @param FormSet FormSet data structure.
2609 @param Storage Storage which has this Progress string.
2610 @param Progress The Progress string which has the first fail string.
2611 @param RetForm The return form for this progress string.
2612 @param RetQuestion The return question for the error progress string.
2614 @retval TRUE Find the error form and statement for this error progress string.
2615 @retval FALSE Not find the error form.
2619 FindQuestionFromProgress (
2620 IN FORM_BROWSER_FORMSET
*FormSet
,
2621 IN BROWSER_STORAGE
*Storage
,
2622 IN EFI_STRING Progress
,
2623 OUT FORM_BROWSER_FORM
**RetForm
,
2624 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2628 LIST_ENTRY
*LinkStorage
;
2629 LIST_ENTRY
*LinkStatement
;
2630 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2631 FORM_BROWSER_FORM
*Form
;
2633 FORM_BROWSER_STATEMENT
*Statement
;
2635 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2639 *RetQuestion
= NULL
;
2642 // Skip the first "&" or the ConfigHdr part.
2644 if (*Progress
== '&') {
2648 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2650 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2652 // For Name/Value type, Skip the ConfigHdr part.
2654 EndStr
= StrStr (Progress
, L
"PATH=");
2655 ASSERT (EndStr
!= NULL
);
2656 while (*EndStr
!= '&') {
2663 // For Buffer type, Skip the ConfigHdr part.
2665 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2666 ASSERT (EndStr
!= NULL
);
2670 Progress
= EndStr
+ 1;
2674 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2676 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2678 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2679 // here, just keep the "Fred" string.
2681 EndStr
= StrStr (Progress
, L
"=");
2682 ASSERT (EndStr
!= NULL
);
2686 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2687 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2689 EndStr
= StrStr (Progress
, L
"&VALUE=");
2690 ASSERT (EndStr
!= NULL
);
2695 // Search in the form list.
2697 Link
= GetFirstNode (&FormSet
->FormListHead
);
2698 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2699 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2700 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2703 // Search in the ConfigReqeust list in this form.
2705 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2706 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2707 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2708 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2710 if (Storage
!= ConfigInfo
->Storage
) {
2714 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2716 // Find the OffsetWidth string in this form.
2723 if (*RetForm
!= NULL
) {
2724 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2725 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2726 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2727 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2729 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2730 *RetQuestion
= Statement
;
2734 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2735 *RetQuestion
= Statement
;
2741 if (*RetForm
!= NULL
) {
2747 // restore the OffsetWidth string to the original format.
2749 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2755 return (BOOLEAN
) (*RetForm
!= NULL
);
2759 Popup an save error info and get user input.
2761 @param TitleId The form title id.
2762 @param HiiHandle The hii handle for this package.
2764 @retval UINT32 The user select option for the save fail.
2765 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2769 IN EFI_STRING_ID TitleId
,
2770 IN EFI_HII_HANDLE HiiHandle
2774 CHAR16
*StringBuffer
;
2777 FormTitle
= GetToken (TitleId
, HiiHandle
);
2779 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2780 ASSERT (StringBuffer
!= NULL
);
2784 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2785 L
"Submit Fail For Form: %s.",
2789 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2791 FreePool (StringBuffer
);
2792 FreePool (FormTitle
);
2798 Popup an NO_SUBMIT_IF error info and get user input.
2800 @param TitleId The form title id.
2801 @param HiiHandle The hii handle for this package.
2803 @retval UINT32 The user select option for the save fail.
2804 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2807 ConfirmNoSubmitFail (
2808 IN EFI_STRING_ID TitleId
,
2809 IN EFI_HII_HANDLE HiiHandle
2813 CHAR16
*StringBuffer
;
2816 FormTitle
= GetToken (TitleId
, HiiHandle
);
2818 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2819 ASSERT (StringBuffer
!= NULL
);
2823 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2824 L
"NO_SUBMIT_IF error For Form: %s.",
2828 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2830 FreePool (StringBuffer
);
2831 FreePool (FormTitle
);
2837 Discard data based on the input setting scope (Form, FormSet or System).
2839 @param FormSet FormSet data structure.
2840 @param Form Form data structure.
2841 @param SettingScope Setting Scope for Discard action.
2843 @retval EFI_SUCCESS The function completed successfully.
2844 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2849 IN FORM_BROWSER_FORMSET
*FormSet
,
2850 IN FORM_BROWSER_FORM
*Form
,
2851 IN BROWSER_SETTING_SCOPE SettingScope
2855 FORMSET_STORAGE
*Storage
;
2856 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2857 FORM_BROWSER_FORMSET
*LocalFormSet
;
2858 FORM_BROWSER_FORMSET
*OldFormSet
;
2861 // Check the supported setting level.
2863 if (SettingScope
>= MaxLevel
) {
2864 return EFI_UNSUPPORTED
;
2867 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2869 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2870 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2871 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2872 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2874 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2879 // Skip if there is no RequestElement
2881 if (ConfigInfo
->ElementCount
== 0) {
2886 // Prepare <ConfigResp>
2888 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2891 // Call callback with Changed type to inform the driver.
2893 SendDiscardInfoToDriver (FormSet
, Form
);
2896 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2897 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2900 // Discard Buffer storage or Name/Value storage
2902 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2903 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2904 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2905 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2907 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2912 // Skip if there is no RequestElement
2914 if (Storage
->ElementCount
== 0) {
2918 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2921 Link
= GetFirstNode (&FormSet
->FormListHead
);
2922 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2923 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2924 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2927 // Call callback with Changed type to inform the driver.
2929 SendDiscardInfoToDriver (FormSet
, Form
);
2932 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2933 } else if (SettingScope
== SystemLevel
) {
2935 // System Level Discard.
2937 OldFormSet
= mSystemLevelFormSet
;
2940 // Discard changed value for each FormSet in the maintain list.
2942 Link
= GetFirstNode (&gBrowserFormSetList
);
2943 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2944 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2945 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2946 if (!ValidateFormSet(LocalFormSet
)) {
2950 mSystemLevelFormSet
= LocalFormSet
;
2952 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2953 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2955 // Remove maintain backup list after discard except for the current using FormSet.
2957 CleanBrowserStorage(LocalFormSet
);
2958 RemoveEntryList (&LocalFormSet
->Link
);
2959 DestroyFormSet (LocalFormSet
);
2963 mSystemLevelFormSet
= OldFormSet
;
2970 Submit data for a form.
2972 @param FormSet FormSet data structure.
2973 @param Form Form data structure.
2975 @retval EFI_SUCCESS The function completed successfully.
2976 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2981 IN FORM_BROWSER_FORMSET
*FormSet
,
2982 IN FORM_BROWSER_FORM
*Form
2987 EFI_STRING ConfigResp
;
2988 EFI_STRING Progress
;
2989 BROWSER_STORAGE
*Storage
;
2990 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2992 if (!IsNvUpdateRequiredForForm (Form
)) {
2996 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2997 if (EFI_ERROR (Status
)) {
3001 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3002 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3003 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3004 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3006 Storage
= ConfigInfo
->Storage
;
3007 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3012 // Skip if there is no RequestElement
3014 if (ConfigInfo
->ElementCount
== 0) {
3019 // 1. Prepare <ConfigResp>
3021 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3022 if (EFI_ERROR (Status
)) {
3027 // 2. Set value to hii config routine protocol.
3029 Status
= mHiiConfigRouting
->RouteConfig (
3034 FreePool (ConfigResp
);
3036 if (EFI_ERROR (Status
)) {
3037 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3042 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3044 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3048 // 4. Process the save failed storage.
3050 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3051 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3052 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3053 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3054 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3055 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3057 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3059 Status
= EFI_SUCCESS
;
3062 Status
= EFI_UNSUPPORTED
;
3066 // Free Form save fail list.
3068 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3069 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3070 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3071 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3076 // 5. Update the NV flag.
3078 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3084 Submit data for a formset.
3086 @param FormSet FormSet data structure.
3087 @param SkipProcessFail Whether skip to process the save failed storage.
3088 If submit formset is called when do system level save,
3089 set this value to true and process the failed formset
3091 if submit formset is called when do formset level save,
3092 set the value to false and process the failed storage
3093 right after process all storages for this formset.
3095 @retval EFI_SUCCESS The function completed successfully.
3096 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3101 IN FORM_BROWSER_FORMSET
*FormSet
,
3102 IN BOOLEAN SkipProcessFail
3107 EFI_STRING ConfigResp
;
3108 EFI_STRING Progress
;
3109 BROWSER_STORAGE
*Storage
;
3110 FORMSET_STORAGE
*FormSetStorage
;
3111 FORM_BROWSER_FORM
*Form
;
3112 BOOLEAN HasInserted
;
3113 FORM_BROWSER_STATEMENT
*Question
;
3115 HasInserted
= FALSE
;
3117 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3122 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3123 if (EFI_ERROR (Status
)) {
3124 if (SkipProcessFail
) {
3126 // Process NO_SUBMIT check first, so insert it at head.
3128 FormSet
->SaveFailForm
= Form
;
3129 FormSet
->SaveFailStatement
= Question
;
3130 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3139 // Submit Buffer storage or Name/Value storage
3141 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3142 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3143 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3144 Storage
= FormSetStorage
->BrowserStorage
;
3145 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3147 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3152 // Skip if there is no RequestElement
3154 if (FormSetStorage
->ElementCount
== 0) {
3159 // 1. Prepare <ConfigResp>
3161 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3162 if (EFI_ERROR (Status
)) {
3167 // 2. Send <ConfigResp> to Routine config Protocol.
3169 Status
= mHiiConfigRouting
->RouteConfig (
3174 if (EFI_ERROR (Status
)) {
3175 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3178 // Call submit formset for system level, save the formset info
3179 // and process later.
3181 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3182 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3183 FormSet
->SaveFailForm
= Form
;
3184 FormSet
->SaveFailStatement
= Question
;
3185 if (SkipProcessFail
) {
3186 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3191 FreePool (ConfigResp
);
3195 FreePool (ConfigResp
);
3197 // 3. Config success, update storage shadow Buffer
3199 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3203 // 4. Has save fail storage need to handle.
3206 if (!SkipProcessFail
) {
3208 // If not in system level, just handl the save failed storage here.
3210 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3211 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3212 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3213 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3214 Storage
= FormSetStorage
->BrowserStorage
;
3215 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3217 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3219 Status
= EFI_SUCCESS
;
3222 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3224 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3225 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3226 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3227 gCurrentSelection
->FormId
= Form
->FormId
;
3228 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3230 Status
= EFI_UNSUPPORTED
;
3234 // Free FormSet save fail list.
3236 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3237 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3238 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3239 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3243 // If in system level, just return error and handle the failed formset later.
3245 Status
= EFI_UNSUPPORTED
;
3250 // 5. Update the NV flag.
3252 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3258 Submit data for all formsets.
3260 @retval EFI_SUCCESS The function completed successfully.
3261 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3271 LIST_ENTRY
*StorageLink
;
3272 FORMSET_STORAGE
*FormSetStorage
;
3273 FORM_BROWSER_FORM
*Form
;
3274 FORM_BROWSER_FORMSET
*LocalFormSet
;
3275 UINT32 UserSelection
;
3276 FORM_BROWSER_STATEMENT
*Question
;
3278 mSystemSubmit
= TRUE
;
3279 Link
= GetFirstNode (&gBrowserFormSetList
);
3280 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3281 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3282 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3283 if (!ValidateFormSet(LocalFormSet
)) {
3287 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3288 if (EFI_ERROR (Status
)) {
3293 // Remove maintain backup list after save except for the current using FormSet.
3295 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3296 CleanBrowserStorage(LocalFormSet
);
3297 RemoveEntryList (&LocalFormSet
->Link
);
3298 DestroyFormSet (LocalFormSet
);
3301 mSystemSubmit
= FALSE
;
3303 Status
= EFI_SUCCESS
;
3306 // Process the save failed formsets.
3308 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3309 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3310 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3311 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3313 if (!ValidateFormSet(LocalFormSet
)) {
3317 Form
= LocalFormSet
->SaveFailForm
;
3318 Question
= LocalFormSet
->SaveFailStatement
;
3321 // Confirm with user, get user input.
3323 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3325 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3327 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3329 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3332 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3333 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3334 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3335 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3336 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3337 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3339 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3342 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3343 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3344 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3345 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3347 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3351 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3352 CleanBrowserStorage(LocalFormSet
);
3353 RemoveEntryList (&LocalFormSet
->Link
);
3354 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3355 DestroyFormSet (LocalFormSet
);
3357 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3360 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3361 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3364 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3366 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3367 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3368 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3369 gCurrentSelection
->FormId
= Form
->FormId
;
3370 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3372 Status
= EFI_UNSUPPORTED
;
3378 // Clean the list which will not process.
3380 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3381 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3382 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3383 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3385 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3386 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3387 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3388 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3396 Submit data based on the input Setting level (Form, FormSet or System).
3398 @param FormSet FormSet data structure.
3399 @param Form Form data structure.
3400 @param SettingScope Setting Scope for Submit action.
3402 @retval EFI_SUCCESS The function completed successfully.
3403 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3408 IN FORM_BROWSER_FORMSET
*FormSet
,
3409 IN FORM_BROWSER_FORM
*Form
,
3410 IN BROWSER_SETTING_SCOPE SettingScope
3415 switch (SettingScope
) {
3417 Status
= SubmitForForm(FormSet
, Form
);
3421 Status
= SubmitForFormSet (FormSet
, FALSE
);
3425 Status
= SubmitForSystem ();
3429 Status
= EFI_UNSUPPORTED
;
3437 Converts the unicode character of the string from uppercase to lowercase.
3438 This is a internal function.
3440 @param ConfigString String to be converted
3446 IN EFI_STRING ConfigString
3452 ASSERT (ConfigString
!= NULL
);
3455 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3457 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3458 if (*String
== L
'=') {
3460 } else if (*String
== L
'&') {
3462 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3463 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3469 Find the point in the ConfigResp string for this question.
3471 @param Question The question.
3472 @param ConfigResp Get ConfigResp string.
3474 @retval point to the offset where is for this question.
3478 GetOffsetFromConfigResp (
3479 IN FORM_BROWSER_STATEMENT
*Question
,
3480 IN CHAR16
*ConfigResp
3483 CHAR16
*RequestElement
;
3487 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3489 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3490 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3491 if (RequestElement
!= NULL
) {
3493 // Skip the "VariableName=" field.
3495 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3498 return RequestElement
;
3502 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3506 // 1. Directly use Question->BlockName to find.
3508 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3509 if (RequestElement
!= NULL
) {
3511 // Skip the "Question->BlockName&VALUE=" field.
3513 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3514 return RequestElement
;
3518 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3520 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3521 ASSERT (BlockData
!= NULL
);
3522 HiiToLower (BlockData
);
3523 RequestElement
= StrStr (ConfigResp
, BlockData
);
3524 FreePool (BlockData
);
3526 if (RequestElement
!= NULL
) {
3528 // Skip the "Question->BlockName&VALUE=" field.
3530 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3533 return RequestElement
;
3537 Get Question default value from AltCfg string.
3539 @param FormSet The form set.
3540 @param Form The form
3541 @param Question The question.
3543 @retval EFI_SUCCESS Question is reset to default value.
3547 GetDefaultValueFromAltCfg (
3548 IN FORM_BROWSER_FORMSET
*FormSet
,
3549 IN FORM_BROWSER_FORM
*Form
,
3550 IN OUT FORM_BROWSER_STATEMENT
*Question
3553 BROWSER_STORAGE
*Storage
;
3554 FORMSET_STORAGE
*FormSetStorage
;
3558 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3560 Storage
= Question
->Storage
;
3561 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3562 return EFI_NOT_FOUND
;
3566 // Try to get AltCfg string from form. If not found it, then
3567 // try to get it from formset.
3570 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3571 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3572 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3573 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3575 if (Storage
== ConfigInfo
->Storage
) {
3576 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3581 if (ConfigResp
== NULL
) {
3582 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3583 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3584 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3585 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3587 if (Storage
== FormSetStorage
->BrowserStorage
) {
3588 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3594 if (ConfigResp
== NULL
) {
3595 return EFI_NOT_FOUND
;
3598 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3599 if (Value
== NULL
) {
3600 return EFI_NOT_FOUND
;
3603 return BufferToValue (Question
, Value
);
3607 Get default Id value used for browser.
3609 @param DefaultId The default id value used by hii.
3611 @retval Browser used default value.
3615 GetDefaultIdForCallBack (
3619 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3620 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3621 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3622 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3623 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3624 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3625 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3626 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3627 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3628 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3629 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3630 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3639 Return data element in an Array by its Index.
3641 @param Array The data array.
3642 @param Type Type of the data in this array.
3643 @param Index Zero based index for data in this array.
3645 @retval Value The data to be returned
3657 ASSERT (Array
!= NULL
);
3661 case EFI_IFR_TYPE_NUM_SIZE_8
:
3662 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3665 case EFI_IFR_TYPE_NUM_SIZE_16
:
3666 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3669 case EFI_IFR_TYPE_NUM_SIZE_32
:
3670 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3673 case EFI_IFR_TYPE_NUM_SIZE_64
:
3674 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3686 Set value of a data element in an Array by its Index.
3688 @param Array The data array.
3689 @param Type Type of the data in this array.
3690 @param Index Zero based index for data in this array.
3691 @param Value The value to be set.
3703 ASSERT (Array
!= NULL
);
3706 case EFI_IFR_TYPE_NUM_SIZE_8
:
3707 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3710 case EFI_IFR_TYPE_NUM_SIZE_16
:
3711 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3714 case EFI_IFR_TYPE_NUM_SIZE_32
:
3715 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3718 case EFI_IFR_TYPE_NUM_SIZE_64
:
3719 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3728 Search an Option of a Question by its value.
3730 @param Question The Question
3731 @param OptionValue Value for Option to be searched.
3733 @retval Pointer Pointer to the found Option.
3734 @retval NULL Option not found.
3739 IN FORM_BROWSER_STATEMENT
*Question
,
3740 IN EFI_HII_VALUE
*OptionValue
3744 QUESTION_OPTION
*Option
;
3747 Link
= GetFirstNode (&Question
->OptionListHead
);
3748 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3749 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3751 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3753 // Check the suppressif condition, only a valid option can be return.
3755 if ((Option
->SuppressExpression
== NULL
) ||
3756 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3761 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3769 Reset Question to its default value.
3771 @param FormSet The form set.
3772 @param Form The form.
3773 @param Question The question.
3774 @param DefaultId The Class of the default.
3776 @retval EFI_SUCCESS Question is reset to default value.
3780 GetQuestionDefault (
3781 IN FORM_BROWSER_FORMSET
*FormSet
,
3782 IN FORM_BROWSER_FORM
*Form
,
3783 IN FORM_BROWSER_STATEMENT
*Question
,
3789 QUESTION_DEFAULT
*Default
;
3790 QUESTION_OPTION
*Option
;
3791 EFI_HII_VALUE
*HiiValue
;
3793 EFI_STRING StrValue
;
3794 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3795 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3799 Status
= EFI_NOT_FOUND
;
3803 // Statement don't have storage, skip them
3805 if (Question
->QuestionId
== 0) {
3810 // There are Five ways to specify default value for a Question:
3811 // 1, use call back function (highest priority)
3812 // 2, use ExtractConfig function
3813 // 3, use nested EFI_IFR_DEFAULT
3814 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3815 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3817 HiiValue
= &Question
->HiiValue
;
3820 // Get Question defaut value from call back function.
3822 ConfigAccess
= FormSet
->ConfigAccess
;
3823 Action
= GetDefaultIdForCallBack (DefaultId
);
3824 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3825 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3826 Status
= ConfigAccess
->Callback (
3829 Question
->QuestionId
,
3834 if (!EFI_ERROR (Status
)) {
3835 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3836 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3837 ASSERT (NewString
!= NULL
);
3839 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3840 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3841 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3843 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3846 FreePool (NewString
);
3853 // Get default value from altcfg string.
3855 if (ConfigAccess
!= NULL
) {
3856 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
3857 if (!EFI_ERROR (Status
)) {
3863 // EFI_IFR_DEFAULT has highest priority
3865 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3866 Link
= GetFirstNode (&Question
->DefaultListHead
);
3867 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3868 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3870 if (Default
->DefaultId
== DefaultId
) {
3871 if (Default
->ValueExpression
!= NULL
) {
3873 // Default is provided by an Expression, evaluate it
3875 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3876 if (EFI_ERROR (Status
)) {
3880 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3881 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3882 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3883 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3884 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3886 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3887 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3889 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3891 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3892 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3895 // Default value is embedded in EFI_IFR_DEFAULT
3897 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
3898 ASSERT (HiiValue
->Buffer
!= NULL
);
3899 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
3901 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3905 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3906 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3907 if (StrValue
== NULL
) {
3908 return EFI_NOT_FOUND
;
3910 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3911 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3913 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3920 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3925 // EFI_ONE_OF_OPTION
3927 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3928 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3930 // OneOfOption could only provide Standard and Manufacturing default
3932 Link
= GetFirstNode (&Question
->OptionListHead
);
3933 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3934 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3935 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3937 if ((Option
->SuppressExpression
!= NULL
) &&
3938 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3942 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3943 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3945 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3954 // EFI_IFR_CHECKBOX - lowest priority
3956 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3957 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3959 // Checkbox could only provide Standard and Manufacturing default
3961 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3962 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3964 HiiValue
->Value
.b
= TRUE
;
3966 HiiValue
->Value
.b
= FALSE
;
3974 // For Questions without default
3976 Status
= EFI_NOT_FOUND
;
3977 switch (Question
->Operand
) {
3978 case EFI_IFR_NUMERIC_OP
:
3980 // Take minimum value as numeric default value
3982 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
3984 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
3986 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
3987 case EFI_IFR_NUMERIC_SIZE_1
:
3988 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
3989 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
3990 Status
= EFI_SUCCESS
;
3993 case EFI_IFR_NUMERIC_SIZE_2
:
3994 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
3995 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
3996 Status
= EFI_SUCCESS
;
3999 case EFI_IFR_NUMERIC_SIZE_4
:
4000 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4001 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4002 Status
= EFI_SUCCESS
;
4005 case EFI_IFR_NUMERIC_SIZE_8
:
4006 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4007 HiiValue
->Value
.u64
= Question
->Minimum
;
4008 Status
= EFI_SUCCESS
;
4015 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4016 HiiValue
->Value
.u64
= Question
->Minimum
;
4017 Status
= EFI_SUCCESS
;
4022 case EFI_IFR_ONE_OF_OP
:
4024 // Take first oneof option as oneof's default value
4026 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4027 Link
= GetFirstNode (&Question
->OptionListHead
);
4028 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4029 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4030 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4032 if ((Option
->SuppressExpression
!= NULL
) &&
4033 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4037 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4038 Status
= EFI_SUCCESS
;
4044 case EFI_IFR_ORDERED_LIST_OP
:
4046 // Take option sequence in IFR as ordered list's default value
4049 Link
= GetFirstNode (&Question
->OptionListHead
);
4050 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4051 Status
= EFI_SUCCESS
;
4052 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4053 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4055 if ((Option
->SuppressExpression
!= NULL
) &&
4056 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4060 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4063 if (Index
>= Question
->MaxContainers
) {
4077 Get AltCfg string for current form.
4079 @param FormSet Form data structure.
4080 @param Form Form data structure.
4081 @param DefaultId The Class of the default.
4082 @param BrowserStorage The input request storage for the questions.
4086 ExtractAltCfgForForm (
4087 IN FORM_BROWSER_FORMSET
*FormSet
,
4088 IN FORM_BROWSER_FORM
*Form
,
4089 IN UINT16 DefaultId
,
4090 IN BROWSER_STORAGE
*BrowserStorage
4098 BROWSER_STORAGE
*Storage
;
4099 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4100 FORMSET_STORAGE
*FormSetStorage
;
4103 // Check whether has get AltCfg string for this formset.
4104 // If yes, no need to get AltCfg for form.
4106 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4107 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4108 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4109 Storage
= FormSetStorage
->BrowserStorage
;
4110 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4111 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4115 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4116 FormSetStorage
->ElementCount
!= 0 &&
4117 FormSetStorage
->HasCallAltCfg
) {
4123 // Get AltCfg string for each form.
4125 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4126 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4127 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4128 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4130 Storage
= ConfigInfo
->Storage
;
4131 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4135 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4140 // 1. Skip if there is no RequestElement
4142 if (ConfigInfo
->ElementCount
== 0) {
4147 // 2. Get value through hii config routine protocol.
4149 Status
= mHiiConfigRouting
->ExtractConfig (
4151 ConfigInfo
->ConfigRequest
,
4155 if (EFI_ERROR (Status
)) {
4160 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4161 // Get the default configuration string according to the default ID.
4163 Status
= mHiiConfigRouting
->GetAltConfig (
4169 &DefaultId
, // it can be NULL to get the current setting.
4173 if (EFI_ERROR (Status
)) {
4177 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4182 Clean AltCfg string for current form.
4184 @param Form Form data structure.
4188 CleanAltCfgForForm (
4189 IN FORM_BROWSER_FORM
*Form
4193 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4195 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4196 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4197 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4198 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4200 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4201 FreePool (ConfigInfo
->ConfigAltResp
);
4202 ConfigInfo
->ConfigAltResp
= NULL
;
4208 Get AltCfg string for current formset.
4210 @param FormSet Form data structure.
4211 @param DefaultId The Class of the default.
4212 @param BrowserStorage The input request storage for the questions.
4216 ExtractAltCfgForFormSet (
4217 IN FORM_BROWSER_FORMSET
*FormSet
,
4218 IN UINT16 DefaultId
,
4219 IN BROWSER_STORAGE
*BrowserStorage
4227 BROWSER_STORAGE
*Storage
;
4228 FORMSET_STORAGE
*FormSetStorage
;
4230 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4231 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4232 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4233 Storage
= FormSetStorage
->BrowserStorage
;
4234 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4236 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4240 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4245 // 1. Skip if there is no RequestElement
4247 if (FormSetStorage
->ElementCount
== 0) {
4251 FormSetStorage
->HasCallAltCfg
= TRUE
;
4254 // 2. Get value through hii config routine protocol.
4256 Status
= mHiiConfigRouting
->ExtractConfig (
4258 FormSetStorage
->ConfigRequest
,
4262 if (EFI_ERROR (Status
)) {
4267 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4268 // Get the default configuration string according to the default ID.
4270 Status
= mHiiConfigRouting
->GetAltConfig (
4276 &DefaultId
, // it can be NULL to get the current setting.
4281 if (EFI_ERROR (Status
)) {
4285 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4291 Clean AltCfg string for current formset.
4293 @param FormSet Form data structure.
4297 CleanAltCfgForFormSet (
4298 IN FORM_BROWSER_FORMSET
*FormSet
4302 FORMSET_STORAGE
*FormSetStorage
;
4304 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4305 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4306 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4307 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4309 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4310 FreePool (FormSetStorage
->ConfigAltResp
);
4311 FormSetStorage
->ConfigAltResp
= NULL
;
4314 FormSetStorage
->HasCallAltCfg
= FALSE
;
4319 Reset Questions to their initial value or default value in a Form, Formset or System.
4321 GetDefaultValueScope parameter decides which questions will reset
4322 to its default value.
4324 @param FormSet FormSet data structure.
4325 @param Form Form data structure.
4326 @param DefaultId The Class of the default.
4327 @param SettingScope Setting Scope for Default action.
4328 @param GetDefaultValueScope Get default value scope.
4329 @param Storage Get default value only for this storage.
4330 @param RetrieveValueFirst Whether call the retrieve call back to
4331 get the initial value before get default
4333 @param SkipGetAltCfg Whether skip the get altcfg string process.
4335 @retval EFI_SUCCESS The function completed successfully.
4336 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4341 IN FORM_BROWSER_FORMSET
*FormSet
,
4342 IN FORM_BROWSER_FORM
*Form
,
4343 IN UINT16 DefaultId
,
4344 IN BROWSER_SETTING_SCOPE SettingScope
,
4345 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4346 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4347 IN BOOLEAN RetrieveValueFirst
,
4348 IN BOOLEAN SkipGetAltCfg
4352 LIST_ENTRY
*FormLink
;
4354 FORM_BROWSER_STATEMENT
*Question
;
4355 FORM_BROWSER_FORMSET
*LocalFormSet
;
4356 FORM_BROWSER_FORMSET
*OldFormSet
;
4358 Status
= EFI_SUCCESS
;
4361 // Check the supported setting level.
4363 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4364 return EFI_UNSUPPORTED
;
4367 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4368 return EFI_UNSUPPORTED
;
4371 if (SettingScope
== FormLevel
) {
4373 // Prepare the AltCfg String for form.
4375 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4376 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4380 // Extract Form default
4382 Link
= GetFirstNode (&Form
->StatementListHead
);
4383 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4384 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4385 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4388 // If get default value only for this storage, check the storage first.
4390 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4395 // If get default value only for no storage question, just skip the question which has storage.
4397 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4402 // If Question is disabled, don't reset it to default
4404 if (Question
->Expression
!= NULL
) {
4405 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4410 if (RetrieveValueFirst
) {
4412 // Call the Retrieve call back to get the initial question value.
4414 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4418 // If not request to get the initial value or get initial value fail, then get default value.
4420 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4421 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4422 if (EFI_ERROR (Status
)) {
4428 // Synchronize Buffer storage's Edit buffer
4430 if ((Question
->Storage
!= NULL
) &&
4431 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4432 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4437 // Clean the AltCfg String.
4439 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4440 CleanAltCfgForForm(Form
);
4442 } else if (SettingScope
== FormSetLevel
) {
4444 // Prepare the AltCfg String for formset.
4446 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4447 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4450 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4451 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4452 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4453 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4454 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4458 // Clean the AltCfg String.
4460 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4461 CleanAltCfgForFormSet (FormSet
);
4463 } else if (SettingScope
== SystemLevel
) {
4465 // Preload all Hii formset.
4467 LoadAllHiiFormset();
4469 OldFormSet
= mSystemLevelFormSet
;
4472 // Set Default Value for each FormSet in the maintain list.
4474 Link
= GetFirstNode (&gBrowserFormSetList
);
4475 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4476 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4477 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4478 if (!ValidateFormSet(LocalFormSet
)) {
4482 mSystemLevelFormSet
= LocalFormSet
;
4484 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4487 mSystemLevelFormSet
= OldFormSet
;
4495 Validate whether this question's value has changed.
4497 @param FormSet FormSet data structure.
4498 @param Form Form data structure.
4499 @param Question Question to be initialized.
4500 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4502 @retval TRUE Question's value has changed.
4503 @retval FALSE Question's value has not changed
4507 IsQuestionValueChanged (
4508 IN FORM_BROWSER_FORMSET
*FormSet
,
4509 IN FORM_BROWSER_FORM
*Form
,
4510 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4511 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4514 EFI_HII_VALUE BackUpValue
;
4515 CHAR8
*BackUpBuffer
;
4516 EFI_HII_VALUE BackUpValue2
;
4517 CHAR8
*BackUpBuffer2
;
4519 BOOLEAN ValueChanged
;
4523 // For quetion without storage, always mark it as data not changed.
4525 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4529 BackUpBuffer
= NULL
;
4530 BackUpBuffer2
= NULL
;
4531 ValueChanged
= FALSE
;
4533 switch (Question
->Operand
) {
4534 case EFI_IFR_ORDERED_LIST_OP
:
4535 BufferWidth
= Question
->StorageWidth
;
4536 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4537 ASSERT (BackUpBuffer
!= NULL
);
4540 case EFI_IFR_STRING_OP
:
4541 case EFI_IFR_PASSWORD_OP
:
4542 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4543 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4544 ASSERT (BackUpBuffer
!= NULL
);
4551 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4553 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4554 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4555 ASSERT_EFI_ERROR(Status
);
4557 switch (Question
->Operand
) {
4558 case EFI_IFR_ORDERED_LIST_OP
:
4559 BufferWidth
= Question
->StorageWidth
;
4560 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4561 ASSERT (BackUpBuffer2
!= NULL
);
4564 case EFI_IFR_STRING_OP
:
4565 case EFI_IFR_PASSWORD_OP
:
4566 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4567 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4568 ASSERT (BackUpBuffer2
!= NULL
);
4575 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4577 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4578 ASSERT_EFI_ERROR(Status
);
4580 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4581 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4582 ValueChanged
= TRUE
;
4585 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4586 ASSERT_EFI_ERROR(Status
);
4588 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4589 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4590 ValueChanged
= TRUE
;
4594 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4595 if (BackUpBuffer
!= NULL
) {
4596 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4597 FreePool (BackUpBuffer
);
4600 if (BackUpBuffer2
!= NULL
) {
4601 FreePool (BackUpBuffer2
);
4604 Question
->ValueChanged
= ValueChanged
;
4606 return ValueChanged
;
4610 Initialize Question's Edit copy from Storage.
4612 @param Selection Selection contains the information about
4613 the Selection, form and formset to be displayed.
4614 Selection action may be updated in retrieve callback.
4615 If Selection is NULL, only initialize Question value.
4616 @param FormSet FormSet data structure.
4617 @param Form Form data structure.
4619 @retval EFI_SUCCESS The function completed successfully.
4624 IN OUT UI_MENU_SELECTION
*Selection
,
4625 IN FORM_BROWSER_FORMSET
*FormSet
,
4626 IN FORM_BROWSER_FORM
*Form
4631 FORM_BROWSER_STATEMENT
*Question
;
4633 Link
= GetFirstNode (&Form
->StatementListHead
);
4634 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4635 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4638 // Initialize local copy of Value for each Question
4640 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4641 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4643 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4645 if (EFI_ERROR (Status
)) {
4649 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4650 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4653 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4660 Initialize Question's Edit copy from Storage for the whole Formset.
4662 @param Selection Selection contains the information about
4663 the Selection, form and formset to be displayed.
4664 Selection action may be updated in retrieve callback.
4665 If Selection is NULL, only initialize Question value.
4666 @param FormSet FormSet data structure.
4668 @retval EFI_SUCCESS The function completed successfully.
4673 IN OUT UI_MENU_SELECTION
*Selection
,
4674 IN FORM_BROWSER_FORMSET
*FormSet
4679 FORM_BROWSER_FORM
*Form
;
4681 Link
= GetFirstNode (&FormSet
->FormListHead
);
4682 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4683 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4686 // Initialize local copy of Value for each Form
4688 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4689 if (EFI_ERROR (Status
)) {
4693 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4697 // Finished question initialization.
4699 FormSet
->QuestionInited
= TRUE
;
4705 Remove the Request element from the Config Request.
4707 @param Storage Pointer to the browser storage.
4708 @param RequestElement The pointer to the Request element.
4713 IN OUT BROWSER_STORAGE
*Storage
,
4714 IN CHAR16
*RequestElement
4720 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4722 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4724 if (NewStr
== NULL
) {
4729 // Remove this element from this ConfigRequest.
4732 NewStr
+= StrLen (RequestElement
);
4733 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4735 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4739 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4741 @param Storage Pointer to the formset storage.
4742 @param ConfigRequest The pointer to the Request element.
4746 RemoveConfigRequest (
4747 FORMSET_STORAGE
*Storage
,
4748 CHAR16
*ConfigRequest
4751 CHAR16
*RequestElement
;
4752 CHAR16
*NextRequestElement
;
4756 // No request element in it, just return.
4758 if (ConfigRequest
== NULL
) {
4762 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4764 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4769 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4771 SearchKey
= L
"&OFFSET";
4775 // Find SearchKey storage
4777 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4778 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4779 ASSERT (RequestElement
!= NULL
);
4780 RequestElement
= StrStr (RequestElement
, SearchKey
);
4782 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4785 while (RequestElement
!= NULL
) {
4787 // +1 to avoid find header itself.
4789 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4792 // The last Request element in configRequest string.
4794 if (NextRequestElement
!= NULL
) {
4796 // Replace "&" with '\0'.
4798 *NextRequestElement
= L
'\0';
4801 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
4803 if (NextRequestElement
!= NULL
) {
4805 // Restore '&' with '\0' for later used.
4807 *NextRequestElement
= L
'&';
4810 RequestElement
= NextRequestElement
;
4814 // If no request element remain, just remove the ConfigRequest string.
4816 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4817 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4818 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4819 Storage
->BrowserStorage
->SpareStrLen
= 0;
4824 Base on the current formset info, clean the ConfigRequest string in browser storage.
4826 @param FormSet Pointer of the FormSet
4830 CleanBrowserStorage (
4831 IN OUT FORM_BROWSER_FORMSET
*FormSet
4835 FORMSET_STORAGE
*Storage
;
4837 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4838 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4839 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4840 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4842 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4843 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4847 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
4848 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4849 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4850 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4851 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4852 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4854 Storage
->BrowserStorage
->Initialized
= FALSE
;
4860 Check whether current element in the ConfigReqeust string.
4862 @param BrowserStorage Storage which includes ConfigReqeust.
4863 @param RequestElement New element need to check.
4865 @retval TRUE The Element is in the ConfigReqeust string.
4866 @retval FALSE The Element not in the configReqeust String.
4871 BROWSER_STORAGE
*BrowserStorage
,
4872 CHAR16
*RequestElement
4875 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4879 Append the Request element to the Config Request.
4881 @param ConfigRequest Current ConfigRequest info.
4882 @param SpareStrLen Current remain free buffer for config reqeust.
4883 @param RequestElement New Request element.
4887 AppendConfigRequest (
4888 IN OUT CHAR16
**ConfigRequest
,
4889 IN OUT UINTN
*SpareStrLen
,
4890 IN CHAR16
*RequestElement
4898 StrLength
= StrLen (RequestElement
);
4899 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4900 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
4903 // Append <RequestElement> to <ConfigRequest>
4905 if (StrLength
> *SpareStrLen
) {
4907 // Old String buffer is not sufficient for RequestElement, allocate a new one
4909 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
4910 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
4911 ASSERT (NewStr
!= NULL
);
4913 if (*ConfigRequest
!= NULL
) {
4914 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4915 FreePool (*ConfigRequest
);
4917 *ConfigRequest
= NewStr
;
4918 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4921 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
4922 *SpareStrLen
-= StrLength
;
4926 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4928 @param Storage Form set Storage.
4929 @param Request The input request string.
4930 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4932 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4933 @retval FALSE All elements covered by current used elements.
4937 ConfigRequestAdjust (
4938 IN BROWSER_STORAGE
*Storage
,
4940 IN BOOLEAN RespString
4943 CHAR16
*RequestElement
;
4944 CHAR16
*NextRequestElement
;
4945 CHAR16
*NextElementBakup
;
4949 CHAR16
*ConfigRequest
;
4952 NextElementBakup
= NULL
;
4955 if (Request
!= NULL
) {
4956 ConfigRequest
= Request
;
4958 ConfigRequest
= Storage
->ConfigRequest
;
4961 if (Storage
->ConfigRequest
== NULL
) {
4962 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4966 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4968 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4973 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4975 SearchKey
= L
"&OFFSET";
4976 ValueKey
= L
"&VALUE";
4980 // Find SearchKey storage
4982 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4983 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4984 ASSERT (RequestElement
!= NULL
);
4985 RequestElement
= StrStr (RequestElement
, SearchKey
);
4987 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4990 while (RequestElement
!= NULL
) {
4993 // +1 to avoid find header itself.
4995 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4998 // The last Request element in configRequest string.
5000 if (NextRequestElement
!= NULL
) {
5001 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5002 NextElementBakup
= NextRequestElement
;
5003 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5004 ASSERT (NextRequestElement
!= NULL
);
5007 // Replace "&" with '\0'.
5009 *NextRequestElement
= L
'\0';
5011 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5012 NextElementBakup
= NextRequestElement
;
5013 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5014 ASSERT (NextRequestElement
!= NULL
);
5016 // Replace "&" with '\0'.
5018 *NextRequestElement
= L
'\0';
5022 if (!ElementValidation (Storage
, RequestElement
)) {
5024 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5026 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5030 if (NextRequestElement
!= NULL
) {
5032 // Restore '&' with '\0' for later used.
5034 *NextRequestElement
= L
'&';
5037 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5038 RequestElement
= NextElementBakup
;
5040 RequestElement
= NextRequestElement
;
5048 Fill storage's edit copy with settings requested from Configuration Driver.
5050 @param FormSet FormSet data structure.
5051 @param Storage Buffer Storage.
5056 IN FORM_BROWSER_FORMSET
*FormSet
,
5057 IN FORMSET_STORAGE
*Storage
5061 EFI_STRING Progress
;
5064 EFI_STRING ConfigRequest
;
5067 ConfigRequest
= NULL
;
5069 switch (Storage
->BrowserStorage
->Type
) {
5070 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5073 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5074 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5075 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5080 case EFI_HII_VARSTORE_BUFFER
:
5081 case EFI_HII_VARSTORE_NAME_VALUE
:
5083 // Skip if there is no RequestElement.
5085 if (Storage
->ElementCount
== 0) {
5090 // Just update the ConfigRequest, if storage already initialized.
5092 if (Storage
->BrowserStorage
->Initialized
) {
5093 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5097 Storage
->BrowserStorage
->Initialized
= TRUE
;
5104 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5106 // Create the config request string to get all fields for this storage.
5107 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5108 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5110 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5111 ConfigRequest
= AllocateZeroPool (StrLen
);
5112 ASSERT (ConfigRequest
!= NULL
);
5116 L
"%s&OFFSET=0&WIDTH=%04x",
5118 Storage
->BrowserStorage
->Size
);
5120 ConfigRequest
= Storage
->ConfigRequest
;
5124 // Request current settings from Configuration Driver
5126 Status
= mHiiConfigRouting
->ExtractConfig (
5134 // If get value fail, extract default from IFR binary
5136 if (EFI_ERROR (Status
)) {
5137 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5140 // Convert Result from <ConfigAltResp> to <ConfigResp>
5142 StrPtr
= StrStr (Result
, L
"&GUID=");
5143 if (StrPtr
!= NULL
) {
5147 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5151 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5154 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5156 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5158 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5159 if (ConfigRequest
!= NULL
) {
5160 FreePool (ConfigRequest
);
5166 Get Value changed status from old question.
5168 @param NewFormSet FormSet data structure.
5169 @param OldQuestion Old question which has value changed.
5173 SyncStatusForQuestion (
5174 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5175 IN FORM_BROWSER_STATEMENT
*OldQuestion
5179 LIST_ENTRY
*QuestionLink
;
5180 FORM_BROWSER_FORM
*Form
;
5181 FORM_BROWSER_STATEMENT
*Question
;
5184 // For each form in one formset.
5186 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5187 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5188 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5189 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5192 // for each question in one form.
5194 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5195 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5196 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5197 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5199 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5200 Question
->ValueChanged
= TRUE
;
5208 Get Value changed status from old formset.
5210 @param NewFormSet FormSet data structure.
5211 @param OldFormSet FormSet data structure.
5215 SyncStatusForFormSet (
5216 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5217 IN FORM_BROWSER_FORMSET
*OldFormSet
5221 LIST_ENTRY
*QuestionLink
;
5222 FORM_BROWSER_FORM
*Form
;
5223 FORM_BROWSER_STATEMENT
*Question
;
5226 // For each form in one formset.
5228 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5229 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5230 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5231 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5234 // for each question in one form.
5236 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5237 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5238 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5239 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5241 if (!Question
->ValueChanged
) {
5246 // Find the same question in new formset and update the value changed flag.
5248 SyncStatusForQuestion (NewFormSet
, Question
);
5254 Get current setting of Questions.
5256 @param FormSet FormSet data structure.
5260 InitializeCurrentSetting (
5261 IN OUT FORM_BROWSER_FORMSET
*FormSet
5265 FORMSET_STORAGE
*Storage
;
5266 FORM_BROWSER_FORMSET
*OldFormSet
;
5269 // Try to find pre FormSet in the maintain backup list.
5270 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5272 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5273 if (OldFormSet
!= NULL
) {
5274 SyncStatusForFormSet (FormSet
, OldFormSet
);
5275 RemoveEntryList (&OldFormSet
->Link
);
5276 DestroyFormSet (OldFormSet
);
5278 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5281 // Extract default from IFR binary for no storage questions.
5283 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5286 // Request current settings from Configuration Driver
5288 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5289 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5290 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5292 LoadStorage (FormSet
, Storage
);
5294 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5300 Fetch the Ifr binary data of a FormSet.
5302 @param Handle PackageList Handle
5303 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5304 specified (NULL or zero GUID), take the first
5305 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5306 found in package list.
5307 On output, GUID of the formset found(if not NULL).
5308 @param BinaryLength The length of the FormSet IFR binary.
5309 @param BinaryData The buffer designed to receive the FormSet.
5311 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5312 BufferLength was updated.
5313 @retval EFI_INVALID_PARAMETER The handle is unknown.
5314 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5315 be found with the requested FormId.
5320 IN EFI_HII_HANDLE Handle
,
5321 IN OUT EFI_GUID
*FormSetGuid
,
5322 OUT UINTN
*BinaryLength
,
5323 OUT UINT8
**BinaryData
5327 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5333 UINT32 PackageListLength
;
5334 EFI_HII_PACKAGE_HEADER PackageHeader
;
5336 UINT8 NumberOfClassGuid
;
5337 BOOLEAN ClassGuidMatch
;
5338 EFI_GUID
*ClassGuid
;
5339 EFI_GUID
*ComparingGuid
;
5343 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5346 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5348 if (FormSetGuid
== NULL
) {
5349 ComparingGuid
= &gZeroGuid
;
5351 ComparingGuid
= FormSetGuid
;
5355 // Get HII PackageList
5358 HiiPackageList
= NULL
;
5359 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5360 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5361 HiiPackageList
= AllocatePool (BufferSize
);
5362 ASSERT (HiiPackageList
!= NULL
);
5364 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5366 if (EFI_ERROR (Status
)) {
5369 ASSERT (HiiPackageList
!= NULL
);
5372 // Get Form package from this HII package List
5374 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5376 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5378 ClassGuidMatch
= FALSE
;
5379 while (Offset
< PackageListLength
) {
5380 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5381 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5383 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5385 // Search FormSet in this Form Package
5387 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5388 while (Offset2
< PackageHeader
.Length
) {
5389 OpCodeData
= Package
+ Offset2
;
5391 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5393 // Try to compare against formset GUID
5395 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5396 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5400 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5402 // Try to compare against formset class GUID
5404 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5405 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5406 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5407 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5408 ClassGuidMatch
= TRUE
;
5412 if (ClassGuidMatch
) {
5415 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5416 ClassGuidMatch
= TRUE
;
5421 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5424 if (Offset2
< PackageHeader
.Length
) {
5426 // Target formset found
5432 Offset
+= PackageHeader
.Length
;
5435 if (Offset
>= PackageListLength
) {
5437 // Form package not found in this Package List
5439 FreePool (HiiPackageList
);
5440 return EFI_NOT_FOUND
;
5443 if (FormSetGuid
!= NULL
) {
5445 // Return the FormSet GUID
5447 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5451 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5452 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5453 // of the Form Package.
5455 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5456 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5458 FreePool (HiiPackageList
);
5460 if (*BinaryData
== NULL
) {
5461 return EFI_OUT_OF_RESOURCES
;
5469 Initialize the internal data structure of a FormSet.
5471 @param Handle PackageList Handle
5472 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5473 specified (NULL or zero GUID), take the first
5474 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5475 found in package list.
5476 On output, GUID of the formset found(if not NULL).
5477 @param FormSet FormSet data structure.
5479 @retval EFI_SUCCESS The function completed successfully.
5480 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5485 IN EFI_HII_HANDLE Handle
,
5486 IN OUT EFI_GUID
*FormSetGuid
,
5487 OUT FORM_BROWSER_FORMSET
*FormSet
5491 EFI_HANDLE DriverHandle
;
5493 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5494 if (EFI_ERROR (Status
)) {
5498 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5499 FormSet
->HiiHandle
= Handle
;
5500 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5501 FormSet
->QuestionInited
= FALSE
;
5504 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5506 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5507 if (EFI_ERROR (Status
)) {
5510 FormSet
->DriverHandle
= DriverHandle
;
5511 Status
= gBS
->HandleProtocol (
5513 &gEfiHiiConfigAccessProtocolGuid
,
5514 (VOID
**) &FormSet
->ConfigAccess
5516 if (EFI_ERROR (Status
)) {
5518 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5519 // list, then there will be no configuration action required
5521 FormSet
->ConfigAccess
= NULL
;
5525 // Parse the IFR binary OpCodes
5527 Status
= ParseOpCodes (FormSet
);
5534 Save globals used by previous call to SendForm(). SendForm() may be called from
5535 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5536 So, save globals of previous call to SendForm() and restore them upon exit.
5540 SaveBrowserContext (
5544 BROWSER_CONTEXT
*Context
;
5545 FORM_ENTRY_INFO
*MenuList
;
5547 gBrowserContextCount
++;
5548 if (gBrowserContextCount
== 1) {
5550 // This is not reentry of SendForm(), no context to save
5555 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5556 ASSERT (Context
!= NULL
);
5558 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5561 // Save FormBrowser context
5563 Context
->Selection
= gCurrentSelection
;
5564 Context
->ResetRequired
= gResetRequired
;
5565 Context
->FlagReconnect
= gFlagReconnect
;
5566 Context
->CallbackReconnect
= gCallbackReconnect
;
5567 Context
->ExitRequired
= gExitRequired
;
5568 Context
->HiiHandle
= mCurrentHiiHandle
;
5569 Context
->FormId
= mCurrentFormId
;
5570 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5573 // Save the menu history data.
5575 InitializeListHead(&Context
->FormHistoryList
);
5576 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5577 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5578 RemoveEntryList (&MenuList
->Link
);
5580 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5584 // Insert to FormBrowser context list
5586 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5591 Restore globals used by previous call to SendForm().
5595 RestoreBrowserContext (
5600 BROWSER_CONTEXT
*Context
;
5601 FORM_ENTRY_INFO
*MenuList
;
5603 ASSERT (gBrowserContextCount
!= 0);
5604 gBrowserContextCount
--;
5605 if (gBrowserContextCount
== 0) {
5607 // This is not reentry of SendForm(), no context to restore
5612 ASSERT (!IsListEmpty (&gBrowserContextList
));
5614 Link
= GetFirstNode (&gBrowserContextList
);
5615 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5618 // Restore FormBrowser context
5620 gCurrentSelection
= Context
->Selection
;
5621 gResetRequired
= Context
->ResetRequired
;
5622 gFlagReconnect
= Context
->FlagReconnect
;
5623 gCallbackReconnect
= Context
->CallbackReconnect
;
5624 gExitRequired
= Context
->ExitRequired
;
5625 mCurrentHiiHandle
= Context
->HiiHandle
;
5626 mCurrentFormId
= Context
->FormId
;
5627 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5630 // Restore the menu history data.
5632 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5633 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5634 RemoveEntryList (&MenuList
->Link
);
5636 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5640 // Remove from FormBrowser context list
5642 RemoveEntryList (&Context
->Link
);
5643 gBS
->FreePool (Context
);
5647 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5649 @param Handle The Hii Handle.
5651 @return the found FormSet context. If no found, NULL will return.
5654 FORM_BROWSER_FORMSET
*
5655 GetFormSetFromHiiHandle (
5656 EFI_HII_HANDLE Handle
5660 FORM_BROWSER_FORMSET
*FormSet
;
5662 Link
= GetFirstNode (&gBrowserFormSetList
);
5663 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5664 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5665 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5666 if (!ValidateFormSet(FormSet
)) {
5669 if (FormSet
->HiiHandle
== Handle
) {
5678 Check whether the input HII handle is the FormSet that is being used.
5680 @param Handle The Hii Handle.
5682 @retval TRUE HII handle is being used.
5683 @retval FALSE HII handle is not being used.
5687 IsHiiHandleInBrowserContext (
5688 EFI_HII_HANDLE Handle
5692 BROWSER_CONTEXT
*Context
;
5695 // HiiHandle is Current FormSet.
5697 if (mCurrentHiiHandle
== Handle
) {
5702 // Check whether HiiHandle is in BrowserContext.
5704 Link
= GetFirstNode (&gBrowserContextList
);
5705 while (!IsNull (&gBrowserContextList
, Link
)) {
5706 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5707 if (Context
->HiiHandle
== Handle
) {
5709 // HiiHandle is in BrowserContext
5713 Link
= GetNextNode (&gBrowserContextList
, Link
);
5720 Perform Password check.
5721 Passwork may be encrypted by driver that requires the specific check.
5723 @param Form Form where Password Statement is in.
5724 @param Statement Password statement
5725 @param PasswordString Password string to be checked. It may be NULL.
5726 NULL means to restore password.
5727 "" string can be used to checked whether old password does exist.
5729 @return Status Status of Password check.
5734 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5735 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5736 IN EFI_STRING PasswordString OPTIONAL
5740 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5741 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5742 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5743 FORM_BROWSER_STATEMENT
*Question
;
5745 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5746 Question
= GetBrowserStatement(Statement
);
5747 ASSERT (Question
!= NULL
);
5749 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5750 if (ConfigAccess
== NULL
) {
5751 return EFI_UNSUPPORTED
;
5754 if (PasswordString
== NULL
) {
5759 // Check whether has preexisted password.
5761 if (PasswordString
[0] == 0) {
5762 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5765 return EFI_NOT_READY
;
5770 // Check whether the input password is same as preexisted password.
5772 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5775 return EFI_NOT_READY
;
5780 // Prepare password string in HII database
5782 if (PasswordString
!= NULL
) {
5783 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5785 IfrTypeValue
.string
= 0;
5789 // Send password to Configuration Driver for validation
5791 Status
= ConfigAccess
->Callback (
5793 EFI_BROWSER_ACTION_CHANGING
,
5794 Question
->QuestionId
,
5795 Question
->HiiValue
.Type
,
5801 // Remove password string from HII database
5803 if (PasswordString
!= NULL
) {
5804 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5811 Find the registered HotKey based on KeyData.
5813 @param[in] KeyData A pointer to a buffer that describes the keystroke
5814 information for the hot key.
5816 @return The registered HotKey context. If no found, NULL will return.
5819 GetHotKeyFromRegisterList (
5820 IN EFI_INPUT_KEY
*KeyData
5824 BROWSER_HOT_KEY
*HotKey
;
5826 Link
= GetFirstNode (&gBrowserHotKeyList
);
5827 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5828 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5829 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5832 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5839 Configure what scope the hot key will impact.
5840 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5841 If no scope is set, the default scope will be FormSet level.
5842 After all registered hot keys are removed, previous Scope can reset to another level.
5844 @param[in] Scope Scope level to be set.
5846 @retval EFI_SUCCESS Scope is set correctly.
5847 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5848 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5854 IN BROWSER_SETTING_SCOPE Scope
5857 if (Scope
>= MaxLevel
) {
5858 return EFI_INVALID_PARAMETER
;
5862 // When no hot key registered in system or on the first setting,
5863 // Scope can be set.
5865 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5866 gBrowserSettingScope
= Scope
;
5867 mBrowserScopeFirstSet
= FALSE
;
5868 } else if (Scope
!= gBrowserSettingScope
) {
5869 return EFI_UNSUPPORTED
;
5876 Register the hot key with its browser action, or unregistered the hot key.
5877 Only support hot key that is not printable character (control key, function key, etc.).
5878 If the action value is zero, the hot key will be unregistered if it has been registered.
5879 If the same hot key has been registered, the new action and help string will override the previous ones.
5881 @param[in] KeyData A pointer to a buffer that describes the keystroke
5882 information for the hot key. Its type is EFI_INPUT_KEY to
5883 be supported by all ConsoleIn devices.
5884 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5885 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5886 @param[in] HelpString Help string that describes the hot key information.
5887 Its value may be NULL for the unregistered hot key.
5889 @retval EFI_SUCCESS Hot key is registered or unregistered.
5890 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5891 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5892 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5897 IN EFI_INPUT_KEY
*KeyData
,
5899 IN UINT16 DefaultId
,
5900 IN EFI_STRING HelpString OPTIONAL
5903 BROWSER_HOT_KEY
*HotKey
;
5906 // Check input parameters.
5908 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5909 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5910 return EFI_INVALID_PARAMETER
;
5914 // Check whether the input KeyData is in BrowserHotKeyList.
5916 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5919 // Unregister HotKey
5921 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5922 if (HotKey
!= NULL
) {
5924 // The registered HotKey is found.
5925 // Remove it from List, and free its resource.
5927 RemoveEntryList (&HotKey
->Link
);
5928 FreePool (HotKey
->KeyData
);
5929 FreePool (HotKey
->HelpString
);
5933 // The registered HotKey is not found.
5935 return EFI_NOT_FOUND
;
5940 // Register HotKey into List.
5942 if (HotKey
== NULL
) {
5944 // Create new Key, and add it into List.
5946 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5947 ASSERT (HotKey
!= NULL
);
5948 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5949 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5950 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5954 // Fill HotKey information.
5956 HotKey
->Action
= Action
;
5957 HotKey
->DefaultId
= DefaultId
;
5958 if (HotKey
->HelpString
!= NULL
) {
5959 FreePool (HotKey
->HelpString
);
5961 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5967 Register Exit handler function.
5968 When more than one handler function is registered, the latter one will override the previous one.
5969 When NULL handler is specified, the previous Exit handler will be unregistered.
5971 @param[in] Handler Pointer to handler function.
5976 RegiserExitHandler (
5977 IN EXIT_HANDLER Handler
5980 ExitHandlerFunction
= Handler
;
5985 Check whether the browser data has been modified.
5987 @retval TRUE Browser data is modified.
5988 @retval FALSE No browser data is modified.
5993 IsBrowserDataModified (
5998 FORM_BROWSER_FORMSET
*FormSet
;
6000 switch (gBrowserSettingScope
) {
6002 if (gCurrentSelection
== NULL
) {
6005 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6008 if (gCurrentSelection
== NULL
) {
6011 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6014 Link
= GetFirstNode (&gBrowserFormSetList
);
6015 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6016 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6017 if (!ValidateFormSet(FormSet
)) {
6021 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6024 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6034 Execute the action requested by the Action parameter.
6036 @param[in] Action Execute the request action.
6037 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6039 @retval EFI_SUCCESS Execute the request action succss.
6040 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6051 FORM_BROWSER_FORMSET
*FormSet
;
6052 FORM_BROWSER_FORM
*Form
;
6054 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6055 return EFI_NOT_READY
;
6058 Status
= EFI_SUCCESS
;
6061 if (gBrowserSettingScope
< SystemLevel
) {
6062 FormSet
= gCurrentSelection
->FormSet
;
6063 Form
= gCurrentSelection
->Form
;
6067 // Executet the discard action.
6069 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6070 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6071 if (EFI_ERROR (Status
)) {
6077 // Executet the difault action.
6079 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6080 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6081 if (EFI_ERROR (Status
)) {
6084 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6088 // Executet the submit action.
6090 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6091 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6092 if (EFI_ERROR (Status
)) {
6098 // Executet the reset action.
6100 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6101 gResetRequired
= TRUE
;
6105 // Executet the exit action.
6107 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6108 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6109 if (gBrowserSettingScope
== SystemLevel
) {
6110 if (ExitHandlerFunction
!= NULL
) {
6111 ExitHandlerFunction ();
6115 gExitRequired
= TRUE
;
6122 Create reminder to let user to choose save or discard the changed browser data.
6123 Caller can use it to actively check the changed browser data.
6125 @retval BROWSER_NO_CHANGES No browser data is changed.
6126 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6127 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6128 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6138 FORM_BROWSER_FORMSET
*FormSet
;
6139 BOOLEAN IsDataChanged
;
6140 UINT32 DataSavedAction
;
6143 DataSavedAction
= BROWSER_NO_CHANGES
;
6144 IsDataChanged
= FALSE
;
6145 Link
= GetFirstNode (&gBrowserFormSetList
);
6146 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6147 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6148 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6149 if (!ValidateFormSet(FormSet
)) {
6152 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6153 IsDataChanged
= TRUE
;
6159 // No data is changed. No save is required.
6161 if (!IsDataChanged
) {
6162 return DataSavedAction
;
6166 // If data is changed, prompt user to save or discard it.
6169 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6171 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6172 SubmitForm (NULL
, NULL
, SystemLevel
);
6173 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6175 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6176 DiscardForm (NULL
, NULL
, SystemLevel
);
6177 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6179 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6180 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6185 return DataSavedAction
;
6189 Check whether the Reset Required for the browser
6191 @retval TRUE Browser required to reset after exit.
6192 @retval FALSE Browser not need to reset after exit.
6201 return gResetRequired
;