2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
31 BROWSER_EXTENSION2_VERSION_1_1
,
35 IsBrowserDataModified
,
43 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
44 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
45 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
46 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
48 UINTN gBrowserContextCount
= 0;
49 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
50 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
51 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
52 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
53 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
55 BOOLEAN mSystemSubmit
= FALSE
;
56 BOOLEAN gResetRequired
;
57 BOOLEAN gExitRequired
;
58 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
59 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
60 EXIT_HANDLER ExitHandlerFunction
= NULL
;
61 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
64 // Browser Global Strings
67 CHAR16
*mUnknownString
= L
"!";
69 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
71 extern EFI_GUID mCurrentFormSetGuid
;
72 extern EFI_HII_HANDLE mCurrentHiiHandle
;
73 extern UINT16 mCurrentFormId
;
74 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
77 Create a menu with specified formset GUID and form ID, and add it as a child
78 of the given parent menu.
80 @param HiiHandle Hii handle related to this formset.
81 @param FormSetGuid The Formset Guid of menu to be added.
82 @param FormId The Form ID of menu to be added.
83 @param QuestionId The question id of this menu to be added.
85 @return A pointer to the newly added menu or NULL if memory is insufficient.
90 IN EFI_HII_HANDLE HiiHandle
,
91 IN EFI_GUID
*FormSetGuid
,
96 FORM_ENTRY_INFO
*MenuList
;
98 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
99 if (MenuList
== NULL
) {
103 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
105 MenuList
->HiiHandle
= HiiHandle
;
106 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
107 MenuList
->FormId
= FormId
;
108 MenuList
->QuestionId
= QuestionId
;
111 // If parent is not specified, it is the root Form of a Formset
113 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
119 Return the form id for the input hiihandle and formset.
121 @param HiiHandle HiiHandle for FormSet.
122 @param FormSetGuid The Formset GUID of the menu to search.
124 @return First form's id for this form set.
129 IN EFI_HII_HANDLE HiiHandle
,
130 IN EFI_GUID
*FormSetGuid
134 FORM_BROWSER_FORM
*Form
;
136 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
137 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
143 Search Menu with given FormSetGuid and FormId in all cached menu list.
145 @param HiiHandle HiiHandle for FormSet.
146 @param FormSetGuid The Formset GUID of the menu to search.
147 @param FormId The Form ID of menu to search.
149 @return A pointer to menu found or NULL if not found.
154 IN EFI_HII_HANDLE HiiHandle
,
155 IN EFI_GUID
*FormSetGuid
,
160 FORM_ENTRY_INFO
*MenuList
;
161 FORM_ENTRY_INFO
*RetMenu
;
162 EFI_FORM_ID FirstFormId
;
166 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
167 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
168 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
169 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
172 // If already find the menu, free the menus behind it.
174 if (RetMenu
!= NULL
) {
175 RemoveEntryList (&MenuList
->Link
);
181 // Find the same FromSet.
183 if (MenuList
->HiiHandle
== HiiHandle
) {
184 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
186 // FormSetGuid is not specified.
189 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
190 if (MenuList
->FormId
== FormId
) {
192 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
193 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
194 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
206 Find parent menu for current menu.
208 @param CurrentMenu Current Menu
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.
210 In form level, just find the parent menu;
211 In formset level, find the parent menu which has different
214 @retval The parent menu for current menu.
218 IN FORM_ENTRY_INFO
*CurrentMenu
,
219 IN BROWSER_SETTING_SCOPE SettingLevel
222 FORM_ENTRY_INFO
*ParentMenu
;
225 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
227 if (CurrentMenu
== NULL
) {
232 Link
= &CurrentMenu
->Link
;
234 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
235 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
237 if (SettingLevel
== FormLevel
) {
239 // For FormLevel, just find the parent menu, return.
244 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
246 // For SystemLevel, must find the menu which has different formset.
251 Link
= Link
->BackLink
;
255 // Not find the parent menu, just return NULL.
257 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
265 Free Menu list linked list.
267 @param MenuListHead One Menu list point in the menu list.
272 LIST_ENTRY
*MenuListHead
275 FORM_ENTRY_INFO
*MenuList
;
277 while (!IsListEmpty (MenuListHead
)) {
278 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
279 RemoveEntryList (&MenuList
->Link
);
286 Copy current Menu list to the new menu list.
288 @param NewMenuListHead New create Menu list.
289 @param CurrentMenuListHead Current Menu list.
294 OUT LIST_ENTRY
*NewMenuListHead
,
295 IN LIST_ENTRY
*CurrentMenuListHead
299 FORM_ENTRY_INFO
*MenuList
;
300 FORM_ENTRY_INFO
*NewMenuEntry
;
303 // If new menu list not empty, free it first.
305 UiFreeMenuList (NewMenuListHead
);
307 Link
= GetFirstNode (CurrentMenuListHead
);
308 while (!IsNull (CurrentMenuListHead
, Link
)) {
309 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
310 Link
= GetNextNode (CurrentMenuListHead
, Link
);
312 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
313 ASSERT (NewMenuEntry
!= NULL
);
314 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
315 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
316 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
317 NewMenuEntry
->FormId
= MenuList
->FormId
;
318 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
320 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
325 Load all hii formset to the browser.
333 FORM_BROWSER_FORMSET
*LocalFormSet
;
334 EFI_HII_HANDLE
*HiiHandles
;
338 FORM_BROWSER_FORMSET
*OldFormset
;
340 OldFormset
= mSystemLevelFormSet
;
343 // Get all the Hii handles
345 HiiHandles
= HiiGetHiiHandles (NULL
);
346 ASSERT (HiiHandles
!= NULL
);
349 // Search for formset of each class type
351 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
353 // Check HiiHandles[Index] does exist in global maintain list.
355 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
360 // Initilize FormSet Setting
362 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
363 ASSERT (LocalFormSet
!= NULL
);
364 mSystemLevelFormSet
= LocalFormSet
;
366 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
367 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
368 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
369 DestroyFormSet (LocalFormSet
);
372 InitializeCurrentSetting (LocalFormSet
);
375 // Initilize Questions' Value
377 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
378 if (EFI_ERROR (Status
)) {
379 DestroyFormSet (LocalFormSet
);
385 // Free resources, and restore gOldFormSet and gClassOfVfr
387 FreePool (HiiHandles
);
389 mSystemLevelFormSet
= OldFormset
;
393 Pop up the error info.
395 @param BrowserStatus The input browser status.
396 @param HiiHandle The Hiihandle for this opcode.
397 @param OpCode The opcode use to get the erro info and timeout value.
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
403 IN UINT32 BrowserStatus
,
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
406 IN CHAR16
*ErrorString
409 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
410 USER_INPUT UserInputData
;
414 if (OpCode
!= NULL
) {
415 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
416 ASSERT (Statement
!= NULL
);
417 Statement
->OpCode
= OpCode
;
418 gDisplayFormData
.HighLightedStatement
= Statement
;
422 // Used to compatible with old display engine.
423 // New display engine not use this field.
425 gDisplayFormData
.ErrorString
= ErrorString
;
426 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
428 if (HiiHandle
!= NULL
) {
429 gDisplayFormData
.HiiHandle
= HiiHandle
;
432 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
434 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
435 gDisplayFormData
.ErrorString
= NULL
;
437 if (OpCode
!= NULL
) {
438 FreePool (Statement
);
441 return UserInputData
.Action
;
445 This is the routine which an external caller uses to direct the browser
446 where to obtain it's information.
449 @param This The Form Browser protocol instanse.
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
451 display a list of the formsets for the handles specified.
452 @param HandleCount The number of Handles specified in Handle.
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
454 field in the EFI_IFR_FORM_SET op-code for the specified
455 forms-based package. If FormSetGuid is NULL, then this
456 function will display the first found forms package.
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first
458 displayable page. If this field has a value of 0x0000, then
459 the forms browser will render the specified forms in their encoded order.
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
462 @param ActionRequest Points to the action recommended by the form.
464 @retval EFI_SUCCESS The function completed successfully.
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
466 @retval EFI_NOT_FOUND No valid forms could be found to display.
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
473 IN EFI_HII_HANDLE
*Handles
,
474 IN UINTN HandleCount
,
475 IN EFI_GUID
*FormSetGuid
, OPTIONAL
476 IN UINT16 FormId
, OPTIONAL
477 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
482 UI_MENU_SELECTION
*Selection
;
484 FORM_BROWSER_FORMSET
*FormSet
;
485 FORM_ENTRY_INFO
*MenuList
;
488 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
490 if (mFormDisplay
== NULL
) {
491 return EFI_UNSUPPORTED
;
495 // Save globals used by SendForm()
497 SaveBrowserContext ();
499 gResetRequired
= FALSE
;
500 gExitRequired
= FALSE
;
501 Status
= EFI_SUCCESS
;
503 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
505 for (Index
= 0; Index
< HandleCount
; Index
++) {
506 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
507 ASSERT (Selection
!= NULL
);
509 Selection
->Handle
= Handles
[Index
];
510 if (FormSetGuid
!= NULL
) {
511 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
512 Selection
->FormId
= FormId
;
514 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
518 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
519 ASSERT (FormSet
!= NULL
);
522 // Validate the HiiHandle
523 // if validate failed, find the first validate parent HiiHandle.
525 if (!ValidateHiiHandle(Selection
->Handle
)) {
526 FindNextMenu (Selection
, FormSetLevel
);
530 // Initialize internal data structures of FormSet
532 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
533 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
534 DestroyFormSet (FormSet
);
537 Selection
->FormSet
= FormSet
;
538 mSystemLevelFormSet
= FormSet
;
541 // Display this formset
543 gCurrentSelection
= Selection
;
545 Status
= SetupBrowser (Selection
);
547 gCurrentSelection
= NULL
;
548 mSystemLevelFormSet
= NULL
;
551 // If no data is changed, don't need to save current FormSet into the maintain list.
553 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
554 CleanBrowserStorage(FormSet
);
555 RemoveEntryList (&FormSet
->Link
);
556 DestroyFormSet (FormSet
);
559 if (EFI_ERROR (Status
)) {
562 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
564 FreePool (Selection
);
567 if (ActionRequest
!= NULL
) {
568 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
569 if (gResetRequired
) {
570 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
574 mFormDisplay
->ExitDisplay();
577 // Clear the menu history data.
579 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
580 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
581 RemoveEntryList (&MenuList
->Link
);
586 // Restore globals used by SendForm()
588 RestoreBrowserContext ();
594 Get or set data to the storage.
596 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
597 @param ResultsData A string returned from an IFR browser or
598 equivalent. The results string will have no
599 routing information in them.
600 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
601 (if RetrieveData = TRUE) data from the uncommitted
602 browser state information or set (if RetrieveData
603 = FALSE) data in the uncommitted browser state
605 @param Storage The pointer to the storage.
607 @retval EFI_SUCCESS The results have been distributed or are awaiting
613 IN OUT UINTN
*ResultsDataSize
,
614 IN OUT EFI_STRING
*ResultsData
,
615 IN BOOLEAN RetrieveData
,
616 IN BROWSER_STORAGE
*Storage
627 // Generate <ConfigResp>
629 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
630 if (EFI_ERROR (Status
)) {
635 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
636 // Also need to consider add "\0" at first time.
638 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
639 BufferSize
= StrSize (StrPtr
);
643 // Copy the data if the input buffer is bigger enough.
645 if (*ResultsDataSize
>= BufferSize
) {
646 StrCpy (*ResultsData
, StrPtr
);
649 *ResultsDataSize
= BufferSize
;
650 FreePool (ConfigResp
);
653 // Prepare <ConfigResp>
655 TmpSize
= StrLen (*ResultsData
);
656 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
657 ConfigResp
= AllocateZeroPool (BufferSize
);
658 ASSERT (ConfigResp
!= NULL
);
660 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
661 StrCat (ConfigResp
, L
"&");
662 StrCat (ConfigResp
, *ResultsData
);
665 // Update Browser uncommited data
667 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
668 FreePool (ConfigResp
);
669 if (EFI_ERROR (Status
)) {
678 This routine called this service in the browser to retrieve or set certain uncommitted
679 state information that resides in the open formsets.
681 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
683 @param ResultsDataSize A pointer to the size of the buffer associated
685 @param ResultsData A string returned from an IFR browser or
686 equivalent. The results string will have no
687 routing information in them.
688 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
689 (if RetrieveData = TRUE) data from the uncommitted
690 browser state information or set (if RetrieveData
691 = FALSE) data in the uncommitted browser state
693 @param VariableGuid An optional field to indicate the target variable
695 @param VariableName An optional field to indicate the target
696 human-readable variable name.
698 @retval EFI_SUCCESS The results have been distributed or are awaiting
700 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
701 contain the results data.
707 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
708 IN OUT UINTN
*ResultsDataSize
,
709 IN OUT EFI_STRING ResultsData
,
710 IN BOOLEAN RetrieveData
,
711 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
712 IN CONST CHAR16
*VariableName OPTIONAL
717 BROWSER_STORAGE
*Storage
;
718 FORMSET_STORAGE
*FormsetStorage
;
722 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
723 return EFI_INVALID_PARAMETER
;
726 TotalSize
= *ResultsDataSize
;
729 Status
= EFI_SUCCESS
;
731 if (VariableGuid
!= NULL
) {
733 // Try to find target storage in the current formset.
735 Link
= GetFirstNode (&gBrowserStorageList
);
736 while (!IsNull (&gBrowserStorageList
, Link
)) {
737 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
738 Link
= GetNextNode (&gBrowserStorageList
, Link
);
740 // Check the current storage.
742 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
746 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
747 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
749 // Buffer storage require both GUID and Name
751 if (VariableName
== NULL
) {
752 return EFI_NOT_FOUND
;
755 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
760 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
761 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
762 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
763 return EFI_NOT_FOUND
;
766 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
771 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
772 if (EFI_ERROR (Status
)) {
776 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
777 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
781 // Different formsets may have same varstore, so here just set the flag
782 // not exit the circle.
789 return EFI_NOT_FOUND
;
793 // GUID/Name is not specified, take the first storage in FormSet
795 if (mSystemLevelFormSet
== NULL
) {
796 return EFI_NOT_READY
;
800 // Generate <ConfigResp>
802 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
803 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
804 return EFI_UNSUPPORTED
;
807 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
809 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
810 if (EFI_ERROR (Status
)) {
816 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
817 *ResultsDataSize
= TotalSize
;
826 Callback function for SimpleTextInEx protocol install events
828 @param Event the event that is signaled.
829 @param Context not used here.
834 FormDisplayCallback (
841 if (mFormDisplay
!= NULL
) {
845 Status
= gBS
->LocateProtocol (
846 &gEdkiiFormDisplayEngineProtocolGuid
,
848 (VOID
**) &mFormDisplay
853 Initialize Setup Browser driver.
855 @param ImageHandle The image handle.
856 @param SystemTable The system table.
858 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
859 @return Other value if failed to initialize the Setup Browser module.
865 IN EFI_HANDLE ImageHandle
,
866 IN EFI_SYSTEM_TABLE
*SystemTable
873 // Locate required Hii relative protocols
875 Status
= gBS
->LocateProtocol (
876 &gEfiHiiDatabaseProtocolGuid
,
878 (VOID
**) &mHiiDatabase
880 ASSERT_EFI_ERROR (Status
);
882 Status
= gBS
->LocateProtocol (
883 &gEfiHiiConfigRoutingProtocolGuid
,
885 (VOID
**) &mHiiConfigRouting
887 ASSERT_EFI_ERROR (Status
);
889 Status
= gBS
->LocateProtocol (
890 &gEfiDevicePathFromTextProtocolGuid
,
892 (VOID
**) &mPathFromText
896 // Install FormBrowser2 protocol
898 mPrivateData
.Handle
= NULL
;
899 Status
= gBS
->InstallProtocolInterface (
900 &mPrivateData
.Handle
,
901 &gEfiFormBrowser2ProtocolGuid
,
902 EFI_NATIVE_INTERFACE
,
903 &mPrivateData
.FormBrowser2
905 ASSERT_EFI_ERROR (Status
);
908 // Install FormBrowserEx2 protocol
910 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
911 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
912 mPrivateData
.Handle
= NULL
;
913 Status
= gBS
->InstallProtocolInterface (
914 &mPrivateData
.Handle
,
915 &gEdkiiFormBrowserEx2ProtocolGuid
,
916 EFI_NATIVE_INTERFACE
,
917 &mPrivateData
.FormBrowserEx2
919 ASSERT_EFI_ERROR (Status
);
921 Status
= gBS
->InstallProtocolInterface (
922 &mPrivateData
.Handle
,
923 &gEfiFormBrowserExProtocolGuid
,
924 EFI_NATIVE_INTERFACE
,
925 &mPrivateData
.FormBrowserEx
927 ASSERT_EFI_ERROR (Status
);
929 InitializeDisplayFormData ();
931 Status
= gBS
->LocateProtocol (
932 &gEdkiiFormDisplayEngineProtocolGuid
,
934 (VOID
**) &mFormDisplay
937 if (EFI_ERROR (Status
)) {
938 EfiCreateProtocolNotifyEvent (
939 &gEdkiiFormDisplayEngineProtocolGuid
,
952 Create a new string in HII Package List.
954 @param String The String to be added
955 @param HiiHandle The package list in the HII database to insert the
958 @return The output string.
964 IN EFI_HII_HANDLE HiiHandle
967 EFI_STRING_ID StringId
;
969 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
970 ASSERT (StringId
!= 0);
977 Delete a string from HII Package List.
979 @param StringId Id of the string in HII database.
980 @param HiiHandle The HII package list handle.
982 @retval EFI_SUCCESS The string was deleted successfully.
987 IN EFI_STRING_ID StringId
,
988 IN EFI_HII_HANDLE HiiHandle
993 NullChar
= CHAR_NULL
;
994 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1000 Get the string based on the StringId and HII Package List Handle.
1002 @param Token The String's ID.
1003 @param HiiHandle The package list in the HII database to search for
1004 the specified string.
1006 @return The output string.
1011 IN EFI_STRING_ID Token
,
1012 IN EFI_HII_HANDLE HiiHandle
1017 if (HiiHandle
== NULL
) {
1021 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1022 if (String
== NULL
) {
1023 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1024 ASSERT (String
!= NULL
);
1026 return (CHAR16
*) String
;
1031 Allocate new memory and then copy the Unicode string Source to Destination.
1033 @param Dest Location to copy string
1034 @param Src String to copy
1039 IN OUT CHAR16
**Dest
,
1043 if (*Dest
!= NULL
) {
1046 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1047 ASSERT (*Dest
!= NULL
);
1052 Allocate new memory and concatinate Source on the end of Destination.
1054 @param Dest String to added to the end of.
1055 @param Src String to concatinate.
1060 IN OUT CHAR16
**Dest
,
1067 if (*Dest
== NULL
) {
1068 NewStringCpy (Dest
, Src
);
1072 TmpSize
= StrSize (*Dest
);
1073 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1074 ASSERT (NewString
!= NULL
);
1076 StrCpy (NewString
, *Dest
);
1077 StrCat (NewString
, Src
);
1084 Get Value for given Name from a NameValue Storage.
1086 @param Storage The NameValue Storage.
1087 @param Name The Name.
1088 @param Value The retured Value.
1089 @param GetValueFrom Where to get source value, from EditValue or Value.
1091 @retval EFI_SUCCESS Value found for given Name.
1092 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1097 IN BROWSER_STORAGE
*Storage
,
1099 IN OUT CHAR16
**Value
,
1100 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1104 NAME_VALUE_NODE
*Node
;
1106 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1107 return EFI_INVALID_PARAMETER
;
1112 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1113 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1114 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1116 if (StrCmp (Name
, Node
->Name
) == 0) {
1117 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1118 NewStringCpy (Value
, Node
->EditValue
);
1120 NewStringCpy (Value
, Node
->Value
);
1125 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1128 return EFI_NOT_FOUND
;
1133 Set Value of given Name in a NameValue Storage.
1135 @param Storage The NameValue Storage.
1136 @param Name The Name.
1137 @param Value The Value to set.
1138 @param SetValueTo Whether update editValue or Value.
1139 @param ReturnNode The node use the input name.
1141 @retval EFI_SUCCESS Value found for given Name.
1142 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1147 IN BROWSER_STORAGE
*Storage
,
1150 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1151 OUT NAME_VALUE_NODE
**ReturnNode
1155 NAME_VALUE_NODE
*Node
;
1158 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1159 return EFI_INVALID_PARAMETER
;
1162 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1163 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1164 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1166 if (StrCmp (Name
, Node
->Name
) == 0) {
1167 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1168 Buffer
= Node
->EditValue
;
1170 Buffer
= Node
->Value
;
1172 if (Buffer
!= NULL
) {
1175 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1176 ASSERT (Buffer
!= NULL
);
1177 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1178 Node
->EditValue
= Buffer
;
1180 Node
->Value
= Buffer
;
1183 if (ReturnNode
!= NULL
) {
1190 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1193 return EFI_NOT_FOUND
;
1198 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1200 @param Storage The Storage to be conveted.
1201 @param ConfigResp The returned <ConfigResp>.
1202 @param ConfigRequest The ConfigRequest string.
1203 @param GetEditBuf Get the data from editbuffer or buffer.
1205 @retval EFI_SUCCESS Convert success.
1206 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1210 StorageToConfigResp (
1211 IN BROWSER_STORAGE
*Storage
,
1212 IN CHAR16
**ConfigResp
,
1213 IN CHAR16
*ConfigRequest
,
1214 IN BOOLEAN GetEditBuf
1218 EFI_STRING Progress
;
1220 NAME_VALUE_NODE
*Node
;
1223 Status
= EFI_SUCCESS
;
1225 switch (Storage
->Type
) {
1226 case EFI_HII_VARSTORE_BUFFER
:
1227 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1228 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1229 Status
= mHiiConfigRouting
->BlockToConfig (
1239 case EFI_HII_VARSTORE_NAME_VALUE
:
1241 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1243 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1244 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1245 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1247 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1248 NewStringCat (ConfigResp
, L
"&");
1249 NewStringCat (ConfigResp
, Node
->Name
);
1250 NewStringCat (ConfigResp
, L
"=");
1252 NewStringCat (ConfigResp
, Node
->EditValue
);
1254 NewStringCat (ConfigResp
, Node
->Value
);
1257 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1261 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1263 Status
= EFI_INVALID_PARAMETER
;
1272 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1274 @param Storage The Storage to receive the settings.
1275 @param ConfigResp The <ConfigResp> to be converted.
1277 @retval EFI_SUCCESS Convert success.
1278 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1282 ConfigRespToStorage (
1283 IN BROWSER_STORAGE
*Storage
,
1284 IN CHAR16
*ConfigResp
1288 EFI_STRING Progress
;
1294 Status
= EFI_SUCCESS
;
1296 switch (Storage
->Type
) {
1297 case EFI_HII_VARSTORE_BUFFER
:
1298 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1299 BufferSize
= Storage
->Size
;
1300 Status
= mHiiConfigRouting
->ConfigToBlock (
1303 Storage
->EditBuffer
,
1309 case EFI_HII_VARSTORE_NAME_VALUE
:
1310 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1311 if (StrPtr
== NULL
) {
1314 StrPtr
= StrStr (ConfigResp
, L
"&");
1315 while (StrPtr
!= NULL
) {
1319 StrPtr
= StrPtr
+ 1;
1321 StrPtr
= StrStr (StrPtr
, L
"=");
1322 if (StrPtr
== NULL
) {
1330 StrPtr
= StrPtr
+ 1;
1332 StrPtr
= StrStr (StrPtr
, L
"&");
1333 if (StrPtr
!= NULL
) {
1336 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1340 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1342 Status
= EFI_INVALID_PARAMETER
;
1351 Get Question's current Value.
1353 @param FormSet FormSet data structure.
1354 @param Form Form data structure.
1355 @param Question Question to be initialized.
1356 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1358 @retval EFI_SUCCESS The function completed successfully.
1363 IN FORM_BROWSER_FORMSET
*FormSet
,
1364 IN FORM_BROWSER_FORM
*Form
,
1365 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1366 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1375 BROWSER_STORAGE
*Storage
;
1376 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1377 CHAR16
*ConfigRequest
;
1385 BOOLEAN IsBufferStorage
;
1390 Status
= EFI_SUCCESS
;
1394 if (GetValueFrom
>= GetSetValueWithMax
) {
1395 return EFI_INVALID_PARAMETER
;
1399 // Question value is provided by an Expression, evaluate it
1401 if (Question
->ValueExpression
!= NULL
) {
1402 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1403 if (!EFI_ERROR (Status
)) {
1404 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1405 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1406 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1407 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1408 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1410 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1411 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1413 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1415 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1416 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1422 // Get question value by read expression.
1424 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1425 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1426 if (!EFI_ERROR (Status
) &&
1427 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1429 // Only update question value to the valid result.
1431 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1432 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1433 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1434 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1435 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1437 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1438 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1440 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1442 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1443 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1449 // Question value is provided by RTC
1451 Storage
= Question
->Storage
;
1452 QuestionValue
= &Question
->HiiValue
.Value
;
1453 if (Storage
== NULL
) {
1455 // It's a Question without storage, or RTC date/time
1457 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1459 // Date and time define the same Flags bit
1461 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1462 case QF_DATE_STORAGE_TIME
:
1463 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1466 case QF_DATE_STORAGE_WAKEUP
:
1467 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1470 case QF_DATE_STORAGE_NORMAL
:
1473 // For date/time without storage
1478 if (EFI_ERROR (Status
)) {
1482 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1483 QuestionValue
->date
.Year
= EfiTime
.Year
;
1484 QuestionValue
->date
.Month
= EfiTime
.Month
;
1485 QuestionValue
->date
.Day
= EfiTime
.Day
;
1487 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1488 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1489 QuestionValue
->time
.Second
= EfiTime
.Second
;
1497 // Question value is provided by EFI variable
1499 StorageWidth
= Question
->StorageWidth
;
1500 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1501 if (Question
->BufferValue
!= NULL
) {
1502 Dst
= Question
->BufferValue
;
1504 Dst
= (UINT8
*) QuestionValue
;
1507 Status
= gRT
->GetVariable (
1508 Question
->VariableName
,
1515 // Always return success, even this EFI variable doesn't exist
1521 // Question Value is provided by Buffer Storage or NameValue Storage
1523 if (Question
->BufferValue
!= NULL
) {
1525 // This Question is password or orderedlist
1527 Dst
= Question
->BufferValue
;
1530 // Other type of Questions
1532 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1535 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1536 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1537 IsBufferStorage
= TRUE
;
1539 IsBufferStorage
= FALSE
;
1541 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1542 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1543 if (IsBufferStorage
) {
1544 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1546 // Copy from storage Edit buffer
1548 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1551 // Copy from storage Edit buffer
1553 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1557 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1558 if (EFI_ERROR (Status
)) {
1562 ASSERT (Value
!= NULL
);
1563 LengthStr
= StrLen (Value
);
1564 Status
= EFI_SUCCESS
;
1567 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1568 // Add string tail char L'\0' into Length
1570 Length
= StorageWidth
+ sizeof (CHAR16
);
1571 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1572 Status
= EFI_BUFFER_TOO_SMALL
;
1574 StringPtr
= (CHAR16
*) Dst
;
1575 ZeroMem (TemStr
, sizeof (TemStr
));
1576 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1577 StrnCpy (TemStr
, Value
+ Index
, 4);
1578 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1581 // Add tailing L'\0' character
1583 StringPtr
[Index
/4] = L
'\0';
1586 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1587 Status
= EFI_BUFFER_TOO_SMALL
;
1589 ZeroMem (TemStr
, sizeof (TemStr
));
1590 for (Index
= 0; Index
< LengthStr
; Index
++) {
1591 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1592 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1593 if ((Index
& 1) == 0) {
1594 Dst
[Index
/2] = DigitUint8
;
1596 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1606 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1607 // <ConfigHdr> + "&" + <VariableName>
1609 if (IsBufferStorage
) {
1610 Length
= StrLen (Storage
->ConfigHdr
);
1611 Length
+= StrLen (Question
->BlockName
);
1613 Length
= StrLen (Storage
->ConfigHdr
);
1614 Length
+= StrLen (Question
->VariableName
) + 1;
1616 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1617 ASSERT (ConfigRequest
!= NULL
);
1619 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1620 if (IsBufferStorage
) {
1621 StrCat (ConfigRequest
, Question
->BlockName
);
1623 StrCat (ConfigRequest
, L
"&");
1624 StrCat (ConfigRequest
, Question
->VariableName
);
1628 // Request current settings from Configuration Driver
1630 Status
= mHiiConfigRouting
->ExtractConfig (
1636 FreePool (ConfigRequest
);
1637 if (EFI_ERROR (Status
)) {
1642 // Skip <ConfigRequest>
1644 if (IsBufferStorage
) {
1645 Value
= StrStr (Result
, L
"&VALUE");
1646 if (Value
== NULL
) {
1648 return EFI_NOT_FOUND
;
1655 Value
= Result
+ Length
;
1657 if (*Value
!= '=') {
1659 return EFI_NOT_FOUND
;
1662 // Skip '=', point to value
1667 // Suppress <AltResp> if any
1670 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1675 LengthStr
= StrLen (Value
);
1676 Status
= EFI_SUCCESS
;
1677 if (!IsBufferStorage
&& IsString
) {
1679 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1680 // Add string tail char L'\0' into Length
1682 Length
= StorageWidth
+ sizeof (CHAR16
);
1683 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1684 Status
= EFI_BUFFER_TOO_SMALL
;
1686 StringPtr
= (CHAR16
*) Dst
;
1687 ZeroMem (TemStr
, sizeof (TemStr
));
1688 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1689 StrnCpy (TemStr
, Value
+ Index
, 4);
1690 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1693 // Add tailing L'\0' character
1695 StringPtr
[Index
/4] = L
'\0';
1698 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1699 Status
= EFI_BUFFER_TOO_SMALL
;
1701 ZeroMem (TemStr
, sizeof (TemStr
));
1702 for (Index
= 0; Index
< LengthStr
; Index
++) {
1703 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1704 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1705 if ((Index
& 1) == 0) {
1706 Dst
[Index
/2] = DigitUint8
;
1708 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1714 if (EFI_ERROR (Status
)) {
1720 // Synchronize Edit Buffer
1722 if (IsBufferStorage
) {
1723 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1725 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1728 if (Result
!= NULL
) {
1738 Save Question Value to edit copy(cached) or Storage(uncached).
1740 @param FormSet FormSet data structure.
1741 @param Form Form data structure.
1742 @param Question Pointer to the Question.
1743 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1745 @retval EFI_SUCCESS The function completed successfully.
1750 IN FORM_BROWSER_FORMSET
*FormSet
,
1751 IN FORM_BROWSER_FORM
*Form
,
1752 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1753 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1763 BROWSER_STORAGE
*Storage
;
1764 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1769 BOOLEAN IsBufferStorage
;
1775 NAME_VALUE_NODE
*Node
;
1777 Status
= EFI_SUCCESS
;
1780 if (SetValueTo
>= GetSetValueWithMax
) {
1781 return EFI_INVALID_PARAMETER
;
1785 // If Question value is provided by an Expression, then it is read only
1787 if (Question
->ValueExpression
!= NULL
) {
1792 // Before set question value, evaluate its write expression.
1794 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1795 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1796 if (EFI_ERROR (Status
)) {
1802 // Question value is provided by RTC
1804 Storage
= Question
->Storage
;
1805 QuestionValue
= &Question
->HiiValue
.Value
;
1806 if (Storage
== NULL
) {
1808 // It's a Question without storage, or RTC date/time
1810 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1812 // Date and time define the same Flags bit
1814 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1815 case QF_DATE_STORAGE_TIME
:
1816 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1819 case QF_DATE_STORAGE_WAKEUP
:
1820 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1823 case QF_DATE_STORAGE_NORMAL
:
1826 // For date/time without storage
1831 if (EFI_ERROR (Status
)) {
1835 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1836 EfiTime
.Year
= QuestionValue
->date
.Year
;
1837 EfiTime
.Month
= QuestionValue
->date
.Month
;
1838 EfiTime
.Day
= QuestionValue
->date
.Day
;
1840 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1841 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1842 EfiTime
.Second
= QuestionValue
->time
.Second
;
1845 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1846 Status
= gRT
->SetTime (&EfiTime
);
1848 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1856 // Question value is provided by EFI variable
1858 StorageWidth
= Question
->StorageWidth
;
1859 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1860 if (Question
->BufferValue
!= NULL
) {
1861 Src
= Question
->BufferValue
;
1863 Src
= (UINT8
*) QuestionValue
;
1866 Status
= gRT
->SetVariable (
1867 Question
->VariableName
,
1869 Storage
->Attributes
,
1877 // Question Value is provided by Buffer Storage or NameValue Storage
1879 if (Question
->BufferValue
!= NULL
) {
1880 Src
= Question
->BufferValue
;
1882 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1885 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1886 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1887 IsBufferStorage
= TRUE
;
1889 IsBufferStorage
= FALSE
;
1891 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1893 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1894 if (IsBufferStorage
) {
1895 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1897 // Copy to storage edit buffer
1899 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1900 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1902 // Copy to storage edit buffer
1904 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1909 // Allocate enough string buffer.
1912 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1913 Value
= AllocateZeroPool (BufferLen
);
1914 ASSERT (Value
!= NULL
);
1916 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1918 TemName
= (CHAR16
*) Src
;
1920 for (; *TemName
!= L
'\0'; TemName
++) {
1921 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1924 BufferLen
= StorageWidth
* 2 + 1;
1925 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1926 ASSERT (Value
!= NULL
);
1928 // Convert Buffer to Hex String
1930 TemBuffer
= Src
+ StorageWidth
- 1;
1932 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1933 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1937 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1939 if (EFI_ERROR (Status
)) {
1943 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1945 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1946 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1948 if (IsBufferStorage
) {
1949 Length
= StrLen (Question
->BlockName
) + 7;
1951 Length
= StrLen (Question
->VariableName
) + 2;
1953 if (!IsBufferStorage
&& IsString
) {
1954 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1956 Length
+= (StorageWidth
* 2);
1958 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1959 ASSERT (ConfigResp
!= NULL
);
1961 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1962 if (IsBufferStorage
) {
1963 StrCat (ConfigResp
, Question
->BlockName
);
1964 StrCat (ConfigResp
, L
"&VALUE=");
1966 StrCat (ConfigResp
, L
"&");
1967 StrCat (ConfigResp
, Question
->VariableName
);
1968 StrCat (ConfigResp
, L
"=");
1971 Value
= ConfigResp
+ StrLen (ConfigResp
);
1973 if (!IsBufferStorage
&& IsString
) {
1975 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1977 TemName
= (CHAR16
*) Src
;
1979 for (; *TemName
!= L
'\0'; TemName
++) {
1980 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1984 // Convert Buffer to Hex String
1986 TemBuffer
= Src
+ StorageWidth
- 1;
1988 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1989 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1994 // Convert to lower char.
1996 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1997 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1998 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2003 // Submit Question Value to Configuration Driver
2005 Status
= mHiiConfigRouting
->RouteConfig (
2010 if (EFI_ERROR (Status
)) {
2011 FreePool (ConfigResp
);
2014 FreePool (ConfigResp
);
2017 // Sync storage, from editbuffer to buffer.
2019 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2027 Perform nosubmitif check for a Form.
2029 @param FormSet FormSet data structure.
2030 @param Form Form data structure.
2031 @param Question The Question to be validated.
2032 @param Type Validation type: NoSubmit
2034 @retval EFI_SUCCESS Form validation pass.
2035 @retval other Form validation failed.
2040 IN FORM_BROWSER_FORMSET
*FormSet
,
2041 IN FORM_BROWSER_FORM
*Form
,
2042 IN FORM_BROWSER_STATEMENT
*Question
,
2048 LIST_ENTRY
*ListHead
;
2049 FORM_EXPRESSION
*Expression
;
2050 UINT32 BrowserStatus
;
2053 BrowserStatus
= BROWSER_SUCCESS
;
2057 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2058 ListHead
= &Question
->InconsistentListHead
;
2061 case EFI_HII_EXPRESSION_WARNING_IF
:
2062 ListHead
= &Question
->WarningListHead
;
2065 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2066 ListHead
= &Question
->NoSubmitListHead
;
2071 return EFI_UNSUPPORTED
;
2074 Link
= GetFirstNode (ListHead
);
2075 while (!IsNull (ListHead
, Link
)) {
2076 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2079 // Evaluate the expression
2081 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2082 if (EFI_ERROR (Status
)) {
2086 if (IsTrue (&Expression
->Result
)) {
2088 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2089 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2092 case EFI_HII_EXPRESSION_WARNING_IF
:
2093 BrowserStatus
= BROWSER_WARNING_IF
;
2096 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2097 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2099 // This code only used to compatible with old display engine,
2100 // New display engine will not use this field.
2102 if (Expression
->Error
!= 0) {
2103 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2112 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2114 // If in system submit process and for no_submit_if check, not popup this error message.
2115 // Will process this fail again later in not system submit process.
2117 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2120 if (ErrorStr
!= NULL
) {
2121 FreePool (ErrorStr
);
2124 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2127 return EFI_NOT_READY
;
2131 Link
= GetNextNode (ListHead
, Link
);
2138 Perform question check.
2140 If one question has more than one check, process form high priority to low.
2141 Only one error info will be popup.
2143 @param FormSet FormSet data structure.
2144 @param Form Form data structure.
2145 @param Question The Question to be validated.
2147 @retval EFI_SUCCESS Form validation pass.
2148 @retval other Form validation failed.
2152 ValueChangedValidation (
2153 IN FORM_BROWSER_FORMSET
*FormSet
,
2154 IN FORM_BROWSER_FORM
*Form
,
2155 IN FORM_BROWSER_STATEMENT
*Question
2160 Status
= EFI_SUCCESS
;
2163 // Do the inconsistentif check.
2165 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2166 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2167 if (EFI_ERROR (Status
)) {
2173 // Do the warningif check.
2175 if (!IsListEmpty (&Question
->WarningListHead
)) {
2176 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2183 Perform NoSubmit check for each Form in FormSet.
2185 @param FormSet FormSet data structure.
2186 @param CurrentForm Current input form data structure.
2187 @param Statement The statement for this check.
2189 @retval EFI_SUCCESS Form validation pass.
2190 @retval other Form validation failed.
2195 IN FORM_BROWSER_FORMSET
*FormSet
,
2196 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2197 OUT FORM_BROWSER_STATEMENT
**Statement
2202 FORM_BROWSER_STATEMENT
*Question
;
2203 FORM_BROWSER_FORM
*Form
;
2204 LIST_ENTRY
*LinkForm
;
2206 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2207 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2208 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2209 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2211 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2215 Link
= GetFirstNode (&Form
->StatementListHead
);
2216 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2217 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2218 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2219 if (EFI_ERROR (Status
)) {
2220 if (*CurrentForm
== NULL
) {
2221 *CurrentForm
= Form
;
2223 if (Statement
!= NULL
) {
2224 *Statement
= Question
;
2229 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2237 Fill storage's edit copy with settings requested from Configuration Driver.
2239 @param Storage The storage which need to sync.
2240 @param ConfigRequest The config request string which used to sync storage.
2241 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2242 editbuffer to buffer
2243 if TRUE, copy the editbuffer to the buffer.
2244 if FALSE, copy the buffer to the editbuffer.
2246 @retval EFI_SUCCESS The function completed successfully.
2250 SynchronizeStorage (
2251 OUT BROWSER_STORAGE
*Storage
,
2252 IN CHAR16
*ConfigRequest
,
2253 IN BOOLEAN SyncOrRestore
2257 EFI_STRING Progress
;
2261 NAME_VALUE_NODE
*Node
;
2265 Status
= EFI_SUCCESS
;
2268 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2269 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2270 BufferSize
= Storage
->Size
;
2272 if (SyncOrRestore
) {
2273 Src
= Storage
->EditBuffer
;
2274 Dst
= Storage
->Buffer
;
2276 Src
= Storage
->Buffer
;
2277 Dst
= Storage
->EditBuffer
;
2280 if (ConfigRequest
!= NULL
) {
2281 Status
= mHiiConfigRouting
->BlockToConfig(
2289 if (EFI_ERROR (Status
)) {
2293 Status
= mHiiConfigRouting
->ConfigToBlock (
2300 if (Result
!= NULL
) {
2304 CopyMem (Dst
, Src
, BufferSize
);
2306 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2307 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2308 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2309 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2311 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2312 (ConfigRequest
== NULL
)) {
2313 if (SyncOrRestore
) {
2314 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2316 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2320 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2328 When discard the question value, call the callback function with Changed type
2329 to inform the hii driver.
2331 @param FormSet FormSet data structure.
2332 @param Form Form data structure.
2336 SendDiscardInfoToDriver (
2337 IN FORM_BROWSER_FORMSET
*FormSet
,
2338 IN FORM_BROWSER_FORM
*Form
2342 FORM_BROWSER_STATEMENT
*Question
;
2343 EFI_IFR_TYPE_VALUE
*TypeValue
;
2344 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2346 if (FormSet
->ConfigAccess
== NULL
) {
2350 Link
= GetFirstNode (&Form
->StatementListHead
);
2351 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2352 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2353 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2355 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2359 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2363 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2367 if (!Question
->ValueChanged
) {
2372 // Restore the question value before call the CHANGED callback type.
2374 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2376 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2377 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2379 TypeValue
= &Question
->HiiValue
.Value
;
2382 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2383 FormSet
->ConfigAccess
->Callback (
2384 FormSet
->ConfigAccess
,
2385 EFI_BROWSER_ACTION_CHANGED
,
2386 Question
->QuestionId
,
2387 Question
->HiiValue
.Type
,
2395 Validate the FormSet. If the formset is not validate, remove it from the list.
2397 @param FormSet The input FormSet which need to validate.
2399 @retval TRUE The handle is validate.
2400 @retval FALSE The handle is invalidate.
2405 EFI_HII_HANDLE HiiHandle
2408 EFI_HII_HANDLE
*HiiHandles
;
2412 if (HiiHandle
== NULL
) {
2418 HiiHandles
= HiiGetHiiHandles (NULL
);
2419 ASSERT (HiiHandles
!= NULL
);
2421 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2422 if (HiiHandles
[Index
] == HiiHandle
) {
2428 FreePool (HiiHandles
);
2434 Validate the FormSet. If the formset is not validate, remove it from the list.
2436 @param FormSet The input FormSet which need to validate.
2438 @retval TRUE The handle is validate.
2439 @retval FALSE The handle is invalidate.
2444 FORM_BROWSER_FORMSET
*FormSet
2449 ASSERT (FormSet
!= NULL
);
2451 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2453 CleanBrowserStorage(FormSet
);
2454 RemoveEntryList (&FormSet
->Link
);
2455 DestroyFormSet (FormSet
);
2461 Check whether need to enable the reset flag in form level.
2462 Also clean all ValueChanged flag in question.
2464 @param SetFlag Whether need to set the Reset Flag.
2465 @param FormSet FormSet data structure.
2466 @param Form Form data structure.
2472 IN FORM_BROWSER_FORMSET
*FormSet
,
2473 IN FORM_BROWSER_FORM
*Form
2477 FORM_BROWSER_STATEMENT
*Question
;
2480 Link
= GetFirstNode (&Form
->StatementListHead
);
2481 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2482 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2483 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2485 if (!Question
->ValueChanged
) {
2489 OldValue
= Question
->ValueChanged
;
2492 // Compare the buffer and editbuffer data to see whether the data has been saved.
2494 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2497 // Only the changed data has been saved, then need to set the reset flag.
2499 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2500 gResetRequired
= TRUE
;
2506 Check whether need to enable the reset flag.
2507 Also clean ValueChanged flag for all statements.
2509 Form level or formset level, only one.
2511 @param SetFlag Whether need to set the Reset Flag.
2512 @param FormSet FormSet data structure.
2513 @param Form Form data structure.
2517 ValueChangeResetFlagUpdate (
2519 IN FORM_BROWSER_FORMSET
*FormSet
,
2520 IN FORM_BROWSER_FORM
*Form
2523 FORM_BROWSER_FORM
*CurrentForm
;
2527 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2531 Link
= GetFirstNode (&FormSet
->FormListHead
);
2532 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2533 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2534 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2536 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2541 Base on the return Progress string to find the form.
2543 Base on the first return Offset/Width (Name) string to find the form
2544 which keep this string.
2546 @param FormSet FormSet data structure.
2547 @param Storage Storage which has this Progress string.
2548 @param Progress The Progress string which has the first fail string.
2549 @param RetForm The return form for this progress string.
2550 @param RetQuestion The return question for the error progress string.
2552 @retval TRUE Find the error form and statement for this error progress string.
2553 @retval FALSE Not find the error form.
2557 FindQuestionFromProgress (
2558 IN FORM_BROWSER_FORMSET
*FormSet
,
2559 IN BROWSER_STORAGE
*Storage
,
2560 IN EFI_STRING Progress
,
2561 OUT FORM_BROWSER_FORM
**RetForm
,
2562 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2566 LIST_ENTRY
*LinkStorage
;
2567 LIST_ENTRY
*LinkStatement
;
2568 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2569 FORM_BROWSER_FORM
*Form
;
2571 FORM_BROWSER_STATEMENT
*Statement
;
2573 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2577 *RetQuestion
= NULL
;
2580 // Skip the first "&" or the ConfigHdr part.
2582 if (*Progress
== '&') {
2586 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2588 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2590 // For Name/Value type, Skip the ConfigHdr part.
2592 EndStr
= StrStr (Progress
, L
"PATH=");
2593 ASSERT (EndStr
!= NULL
);
2594 while (*EndStr
!= '&') {
2601 // For Buffer type, Skip the ConfigHdr part.
2603 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2604 ASSERT (EndStr
!= NULL
);
2608 Progress
= EndStr
+ 1;
2612 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2614 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2616 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2617 // here, just keep the "Fred" string.
2619 EndStr
= StrStr (Progress
, L
"=");
2620 ASSERT (EndStr
!= NULL
);
2624 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2625 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2627 EndStr
= StrStr (Progress
, L
"&VALUE=");
2628 ASSERT (EndStr
!= NULL
);
2633 // Search in the form list.
2635 Link
= GetFirstNode (&FormSet
->FormListHead
);
2636 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2637 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2638 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2641 // Search in the ConfigReqeust list in this form.
2643 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2644 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2645 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2646 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2648 if (Storage
!= ConfigInfo
->Storage
) {
2652 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2654 // Find the OffsetWidth string in this form.
2661 if (*RetForm
!= NULL
) {
2662 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2663 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2664 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2665 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2667 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2668 *RetQuestion
= Statement
;
2674 if (*RetForm
!= NULL
) {
2680 // restore the OffsetWidth string to the original format.
2682 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2688 return (BOOLEAN
) (*RetForm
!= NULL
);
2692 Popup an save error info and get user input.
2694 @param TitleId The form title id.
2695 @param HiiHandle The hii handle for this package.
2697 @retval UINT32 The user select option for the save fail.
2698 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2702 IN EFI_STRING_ID TitleId
,
2703 IN EFI_HII_HANDLE HiiHandle
2707 CHAR16
*StringBuffer
;
2710 FormTitle
= GetToken (TitleId
, HiiHandle
);
2712 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2713 ASSERT (StringBuffer
!= NULL
);
2717 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2718 L
"Submit Fail For Form: %s.",
2722 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2724 FreePool (StringBuffer
);
2725 FreePool (FormTitle
);
2731 Popup an NO_SUBMIT_IF error info and get user input.
2733 @param TitleId The form title id.
2734 @param HiiHandle The hii handle for this package.
2736 @retval UINT32 The user select option for the save fail.
2737 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2740 ConfirmNoSubmitFail (
2741 IN EFI_STRING_ID TitleId
,
2742 IN EFI_HII_HANDLE HiiHandle
2746 CHAR16
*StringBuffer
;
2749 FormTitle
= GetToken (TitleId
, HiiHandle
);
2751 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2752 ASSERT (StringBuffer
!= NULL
);
2756 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2757 L
"NO_SUBMIT_IF error For Form: %s.",
2761 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2763 FreePool (StringBuffer
);
2764 FreePool (FormTitle
);
2770 Discard data based on the input setting scope (Form, FormSet or System).
2772 @param FormSet FormSet data structure.
2773 @param Form Form data structure.
2774 @param SettingScope Setting Scope for Discard action.
2776 @retval EFI_SUCCESS The function completed successfully.
2777 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2782 IN FORM_BROWSER_FORMSET
*FormSet
,
2783 IN FORM_BROWSER_FORM
*Form
,
2784 IN BROWSER_SETTING_SCOPE SettingScope
2788 FORMSET_STORAGE
*Storage
;
2789 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2790 FORM_BROWSER_FORMSET
*LocalFormSet
;
2791 FORM_BROWSER_FORMSET
*OldFormSet
;
2794 // Check the supported setting level.
2796 if (SettingScope
>= MaxLevel
) {
2797 return EFI_UNSUPPORTED
;
2800 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2802 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2803 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2804 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2805 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2807 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2812 // Skip if there is no RequestElement
2814 if (ConfigInfo
->ElementCount
== 0) {
2819 // Prepare <ConfigResp>
2821 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2824 // Call callback with Changed type to inform the driver.
2826 SendDiscardInfoToDriver (FormSet
, Form
);
2829 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2830 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2833 // Discard Buffer storage or Name/Value storage
2835 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2836 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2837 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2838 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2840 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2845 // Skip if there is no RequestElement
2847 if (Storage
->ElementCount
== 0) {
2851 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2854 Link
= GetFirstNode (&FormSet
->FormListHead
);
2855 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2856 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2857 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2860 // Call callback with Changed type to inform the driver.
2862 SendDiscardInfoToDriver (FormSet
, Form
);
2865 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2866 } else if (SettingScope
== SystemLevel
) {
2868 // System Level Discard.
2870 OldFormSet
= mSystemLevelFormSet
;
2873 // Discard changed value for each FormSet in the maintain list.
2875 Link
= GetFirstNode (&gBrowserFormSetList
);
2876 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2877 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2878 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2879 if (!ValidateFormSet(LocalFormSet
)) {
2883 mSystemLevelFormSet
= LocalFormSet
;
2885 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2886 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2888 // Remove maintain backup list after discard except for the current using FormSet.
2890 CleanBrowserStorage(LocalFormSet
);
2891 RemoveEntryList (&LocalFormSet
->Link
);
2892 DestroyFormSet (LocalFormSet
);
2896 mSystemLevelFormSet
= OldFormSet
;
2903 Submit data for a form.
2905 @param FormSet FormSet data structure.
2906 @param Form Form data structure.
2908 @retval EFI_SUCCESS The function completed successfully.
2909 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2914 IN FORM_BROWSER_FORMSET
*FormSet
,
2915 IN FORM_BROWSER_FORM
*Form
2920 EFI_STRING ConfigResp
;
2921 EFI_STRING Progress
;
2922 BROWSER_STORAGE
*Storage
;
2923 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2925 if (!IsNvUpdateRequiredForForm (Form
)) {
2929 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2930 if (EFI_ERROR (Status
)) {
2934 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2935 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2936 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2937 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2939 Storage
= ConfigInfo
->Storage
;
2940 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2945 // Skip if there is no RequestElement
2947 if (ConfigInfo
->ElementCount
== 0) {
2952 // 1. Prepare <ConfigResp>
2954 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2955 if (EFI_ERROR (Status
)) {
2960 // 2. Set value to hii config routine protocol.
2962 Status
= mHiiConfigRouting
->RouteConfig (
2967 FreePool (ConfigResp
);
2969 if (EFI_ERROR (Status
)) {
2970 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2975 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2977 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2981 // 4. Process the save failed storage.
2983 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2984 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
2985 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2986 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
2987 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
2988 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
2990 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2992 Status
= EFI_SUCCESS
;
2995 Status
= EFI_UNSUPPORTED
;
2999 // Free Form save fail list.
3001 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3002 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3003 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3004 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3009 // 5. Update the NV flag.
3011 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3017 Submit data for a formset.
3019 @param FormSet FormSet data structure.
3020 @param SkipProcessFail Whether skip to process the save failed storage.
3021 If submit formset is called when do system level save,
3022 set this value to true and process the failed formset
3024 if submit formset is called when do formset level save,
3025 set the value to false and process the failed storage
3026 right after process all storages for this formset.
3028 @retval EFI_SUCCESS The function completed successfully.
3029 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3034 IN FORM_BROWSER_FORMSET
*FormSet
,
3035 IN BOOLEAN SkipProcessFail
3040 EFI_STRING ConfigResp
;
3041 EFI_STRING Progress
;
3042 BROWSER_STORAGE
*Storage
;
3043 FORMSET_STORAGE
*FormSetStorage
;
3044 FORM_BROWSER_FORM
*Form
;
3045 BOOLEAN HasInserted
;
3046 FORM_BROWSER_STATEMENT
*Question
;
3048 HasInserted
= FALSE
;
3050 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3055 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3056 if (EFI_ERROR (Status
)) {
3057 if (SkipProcessFail
) {
3059 // Process NO_SUBMIT check first, so insert it at head.
3061 FormSet
->SaveFailForm
= Form
;
3062 FormSet
->SaveFailStatement
= Question
;
3063 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3072 // Submit Buffer storage or Name/Value storage
3074 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3075 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3076 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3077 Storage
= FormSetStorage
->BrowserStorage
;
3078 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3080 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3085 // Skip if there is no RequestElement
3087 if (FormSetStorage
->ElementCount
== 0) {
3092 // 1. Prepare <ConfigResp>
3094 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3095 if (EFI_ERROR (Status
)) {
3100 // 2. Send <ConfigResp> to Routine config Protocol.
3102 Status
= mHiiConfigRouting
->RouteConfig (
3107 if (EFI_ERROR (Status
)) {
3108 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3111 // Call submit formset for system level, save the formset info
3112 // and process later.
3114 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3115 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3116 FormSet
->SaveFailForm
= Form
;
3117 FormSet
->SaveFailStatement
= Question
;
3118 if (SkipProcessFail
) {
3119 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3124 FreePool (ConfigResp
);
3128 FreePool (ConfigResp
);
3130 // 3. Config success, update storage shadow Buffer
3132 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3136 // 4. Has save fail storage need to handle.
3139 if (!SkipProcessFail
) {
3141 // If not in system level, just handl the save failed storage here.
3143 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3144 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3145 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3146 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3147 Storage
= FormSetStorage
->BrowserStorage
;
3148 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3150 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3152 Status
= EFI_SUCCESS
;
3155 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3157 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3158 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3159 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3160 gCurrentSelection
->FormId
= Form
->FormId
;
3161 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3163 Status
= EFI_UNSUPPORTED
;
3167 // Free FormSet save fail list.
3169 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3170 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3171 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3172 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3176 // If in system level, just return error and handle the failed formset later.
3178 Status
= EFI_UNSUPPORTED
;
3183 // 5. Update the NV flag.
3185 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3191 Submit data for all formsets.
3193 @retval EFI_SUCCESS The function completed successfully.
3194 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3204 LIST_ENTRY
*StorageLink
;
3205 BROWSER_STORAGE
*Storage
;
3206 FORMSET_STORAGE
*FormSetStorage
;
3207 FORM_BROWSER_FORM
*Form
;
3208 FORM_BROWSER_FORMSET
*LocalFormSet
;
3209 UINT32 UserSelection
;
3210 FORM_BROWSER_STATEMENT
*Question
;
3212 mSystemSubmit
= TRUE
;
3213 Link
= GetFirstNode (&gBrowserFormSetList
);
3214 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3215 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3216 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3217 if (!ValidateFormSet(LocalFormSet
)) {
3221 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3222 if (EFI_ERROR (Status
)) {
3227 // Remove maintain backup list after save except for the current using FormSet.
3229 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3230 CleanBrowserStorage(LocalFormSet
);
3231 RemoveEntryList (&LocalFormSet
->Link
);
3232 DestroyFormSet (LocalFormSet
);
3235 mSystemSubmit
= FALSE
;
3237 Status
= EFI_SUCCESS
;
3240 // Process the save failed formsets.
3242 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3243 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3244 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3245 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3247 if (!ValidateFormSet(LocalFormSet
)) {
3251 Form
= LocalFormSet
->SaveFailForm
;
3252 Question
= LocalFormSet
->SaveFailStatement
;
3255 // Confirm with user, get user input.
3257 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3259 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3261 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3263 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3266 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3267 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3268 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3269 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3270 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3271 Storage
= FormSetStorage
->BrowserStorage
;
3272 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3274 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3277 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3278 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3279 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3280 Storage
= FormSetStorage
->BrowserStorage
;
3281 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3283 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3287 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3288 CleanBrowserStorage(LocalFormSet
);
3289 RemoveEntryList (&LocalFormSet
->Link
);
3290 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3291 DestroyFormSet (LocalFormSet
);
3293 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3296 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3297 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3300 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3302 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3303 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3304 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3305 gCurrentSelection
->FormId
= Form
->FormId
;
3306 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3308 Status
= EFI_UNSUPPORTED
;
3314 // Clean the list which will not process.
3316 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3317 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3318 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3319 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3321 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3322 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3323 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3324 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3332 Submit data based on the input Setting level (Form, FormSet or System).
3334 @param FormSet FormSet data structure.
3335 @param Form Form data structure.
3336 @param SettingScope Setting Scope for Submit action.
3338 @retval EFI_SUCCESS The function completed successfully.
3339 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3344 IN FORM_BROWSER_FORMSET
*FormSet
,
3345 IN FORM_BROWSER_FORM
*Form
,
3346 IN BROWSER_SETTING_SCOPE SettingScope
3351 switch (SettingScope
) {
3353 Status
= SubmitForForm(FormSet
, Form
);
3357 Status
= SubmitForFormSet (FormSet
, FALSE
);
3361 Status
= SubmitForSystem ();
3365 Status
= EFI_UNSUPPORTED
;
3373 Get Question default value from AltCfg string.
3375 @param FormSet The form set.
3376 @param Question The question.
3377 @param DefaultId The default Id.
3379 @retval EFI_SUCCESS Question is reset to default value.
3383 GetDefaultValueFromAltCfg (
3384 IN FORM_BROWSER_FORMSET
*FormSet
,
3385 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3389 BOOLEAN IsBufferStorage
;
3392 BROWSER_STORAGE
*Storage
;
3393 CHAR16
*ConfigRequest
;
3406 Status
= EFI_NOT_FOUND
;
3409 ConfigRequest
= NULL
;
3413 Storage
= Question
->Storage
;
3415 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3420 // Question Value is provided by Buffer Storage or NameValue Storage
3422 if (Question
->BufferValue
!= NULL
) {
3424 // This Question is password or orderedlist
3426 Dst
= Question
->BufferValue
;
3429 // Other type of Questions
3431 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
3434 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3435 IsBufferStorage
= TRUE
;
3437 IsBufferStorage
= FALSE
;
3439 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
3442 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
3443 // <ConfigHdr> + "&" + <VariableName>
3445 if (IsBufferStorage
) {
3446 Length
= StrLen (Storage
->ConfigHdr
);
3447 Length
+= StrLen (Question
->BlockName
);
3449 Length
= StrLen (Storage
->ConfigHdr
);
3450 Length
+= StrLen (Question
->VariableName
) + 1;
3452 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
3453 ASSERT (ConfigRequest
!= NULL
);
3455 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
3456 if (IsBufferStorage
) {
3457 StrCat (ConfigRequest
, Question
->BlockName
);
3459 StrCat (ConfigRequest
, L
"&");
3460 StrCat (ConfigRequest
, Question
->VariableName
);
3463 Status
= mHiiConfigRouting
->ExtractConfig (
3469 if (EFI_ERROR (Status
)) {
3474 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
3475 // Get the default configuration string according to the default ID.
3477 Status
= mHiiConfigRouting
->GetAltConfig (
3483 &DefaultId
, // it can be NULL to get the current setting.
3488 // The required setting can't be found. So, it is not required to be validated and set.
3490 if (EFI_ERROR (Status
)) {
3494 if (ConfigResp
== NULL
) {
3495 Status
= EFI_NOT_FOUND
;
3500 // Skip <ConfigRequest>
3502 if (IsBufferStorage
) {
3503 Value
= StrStr (ConfigResp
, L
"&VALUE");
3504 ASSERT (Value
!= NULL
);
3510 Value
= StrStr (ConfigResp
, Question
->VariableName
);
3511 ASSERT (Value
!= NULL
);
3513 Value
= Value
+ StrLen (Question
->VariableName
);
3515 if (*Value
!= '=') {
3516 Status
= EFI_NOT_FOUND
;
3520 // Skip '=', point to value
3525 // Suppress <AltResp> if any
3528 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3533 LengthStr
= StrLen (Value
);
3534 if (!IsBufferStorage
&& IsString
) {
3535 StringPtr
= (CHAR16
*) Dst
;
3536 ZeroMem (TemStr
, sizeof (TemStr
));
3537 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
3538 StrnCpy (TemStr
, Value
+ Index
, 4);
3539 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
3542 // Add tailing L'\0' character
3544 StringPtr
[Index
/4] = L
'\0';
3546 ZeroMem (TemStr
, sizeof (TemStr
));
3547 for (Index
= 0; Index
< LengthStr
; Index
++) {
3548 TemStr
[0] = Value
[LengthStr
- Index
- 1];
3549 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
3550 if ((Index
& 1) == 0) {
3551 Dst
[Index
/2] = DigitUint8
;
3553 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
3559 if (ConfigRequest
!= NULL
){
3560 FreePool (ConfigRequest
);
3563 if (ConfigResp
!= NULL
) {
3564 FreePool (ConfigResp
);
3567 if (Result
!= NULL
) {
3575 Get default Id value used for browser.
3577 @param DefaultId The default id value used by hii.
3579 @retval Browser used default value.
3583 GetDefaultIdForCallBack (
3587 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3588 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3589 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3590 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3591 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3592 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3593 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3594 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3595 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3596 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3597 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3598 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3607 Return data element in an Array by its Index.
3609 @param Array The data array.
3610 @param Type Type of the data in this array.
3611 @param Index Zero based index for data in this array.
3613 @retval Value The data to be returned
3625 ASSERT (Array
!= NULL
);
3629 case EFI_IFR_TYPE_NUM_SIZE_8
:
3630 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3633 case EFI_IFR_TYPE_NUM_SIZE_16
:
3634 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3637 case EFI_IFR_TYPE_NUM_SIZE_32
:
3638 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3641 case EFI_IFR_TYPE_NUM_SIZE_64
:
3642 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3654 Set value of a data element in an Array by its Index.
3656 @param Array The data array.
3657 @param Type Type of the data in this array.
3658 @param Index Zero based index for data in this array.
3659 @param Value The value to be set.
3671 ASSERT (Array
!= NULL
);
3674 case EFI_IFR_TYPE_NUM_SIZE_8
:
3675 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3678 case EFI_IFR_TYPE_NUM_SIZE_16
:
3679 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3682 case EFI_IFR_TYPE_NUM_SIZE_32
:
3683 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3686 case EFI_IFR_TYPE_NUM_SIZE_64
:
3687 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3696 Search an Option of a Question by its value.
3698 @param Question The Question
3699 @param OptionValue Value for Option to be searched.
3701 @retval Pointer Pointer to the found Option.
3702 @retval NULL Option not found.
3707 IN FORM_BROWSER_STATEMENT
*Question
,
3708 IN EFI_HII_VALUE
*OptionValue
3712 QUESTION_OPTION
*Option
;
3715 Link
= GetFirstNode (&Question
->OptionListHead
);
3716 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3717 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3719 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3721 // Check the suppressif condition, only a valid option can be return.
3723 if ((Option
->SuppressExpression
== NULL
) ||
3724 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3729 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3737 Reset Question to its default value.
3739 @param FormSet The form set.
3740 @param Form The form.
3741 @param Question The question.
3742 @param DefaultId The Class of the default.
3744 @retval EFI_SUCCESS Question is reset to default value.
3748 GetQuestionDefault (
3749 IN FORM_BROWSER_FORMSET
*FormSet
,
3750 IN FORM_BROWSER_FORM
*Form
,
3751 IN FORM_BROWSER_STATEMENT
*Question
,
3757 QUESTION_DEFAULT
*Default
;
3758 QUESTION_OPTION
*Option
;
3759 EFI_HII_VALUE
*HiiValue
;
3761 EFI_STRING StrValue
;
3762 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3763 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3767 Status
= EFI_NOT_FOUND
;
3771 // Statement don't have storage, skip them
3773 if (Question
->QuestionId
== 0) {
3778 // There are Five ways to specify default value for a Question:
3779 // 1, use call back function (highest priority)
3780 // 2, use ExtractConfig function
3781 // 3, use nested EFI_IFR_DEFAULT
3782 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3783 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3785 HiiValue
= &Question
->HiiValue
;
3788 // Get Question defaut value from call back function.
3790 ConfigAccess
= FormSet
->ConfigAccess
;
3791 Action
= GetDefaultIdForCallBack (DefaultId
);
3792 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3793 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3794 Status
= ConfigAccess
->Callback (
3797 Question
->QuestionId
,
3802 if (!EFI_ERROR (Status
)) {
3803 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3804 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3805 ASSERT (NewString
!= NULL
);
3807 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3808 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3809 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3811 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3814 FreePool (NewString
);
3821 // Get default value from altcfg string.
3823 if (ConfigAccess
!= NULL
) {
3824 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3825 if (!EFI_ERROR (Status
)) {
3831 // EFI_IFR_DEFAULT has highest priority
3833 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3834 Link
= GetFirstNode (&Question
->DefaultListHead
);
3835 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3836 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3838 if (Default
->DefaultId
== DefaultId
) {
3839 if (Default
->ValueExpression
!= NULL
) {
3841 // Default is provided by an Expression, evaluate it
3843 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3844 if (EFI_ERROR (Status
)) {
3848 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3849 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3850 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3851 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3852 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3854 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3855 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3857 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3859 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3860 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3863 // Default value is embedded in EFI_IFR_DEFAULT
3865 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3868 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3869 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3870 if (StrValue
== NULL
) {
3871 return EFI_NOT_FOUND
;
3873 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3874 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3876 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3883 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3888 // EFI_ONE_OF_OPTION
3890 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3891 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3893 // OneOfOption could only provide Standard and Manufacturing default
3895 Link
= GetFirstNode (&Question
->OptionListHead
);
3896 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3897 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3898 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3900 if ((Option
->SuppressExpression
!= NULL
) &&
3901 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3905 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3906 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3908 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3917 // EFI_IFR_CHECKBOX - lowest priority
3919 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3920 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3922 // Checkbox could only provide Standard and Manufacturing default
3924 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3925 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3927 HiiValue
->Value
.b
= TRUE
;
3929 HiiValue
->Value
.b
= FALSE
;
3937 // For Questions without default
3939 Status
= EFI_NOT_FOUND
;
3940 switch (Question
->Operand
) {
3941 case EFI_IFR_NUMERIC_OP
:
3943 // Take minimum value as numeric default value
3945 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3946 HiiValue
->Value
.u64
= Question
->Minimum
;
3947 Status
= EFI_SUCCESS
;
3951 case EFI_IFR_ONE_OF_OP
:
3953 // Take first oneof option as oneof's default value
3955 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3956 Link
= GetFirstNode (&Question
->OptionListHead
);
3957 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3958 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3959 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3961 if ((Option
->SuppressExpression
!= NULL
) &&
3962 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3966 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3967 Status
= EFI_SUCCESS
;
3973 case EFI_IFR_ORDERED_LIST_OP
:
3975 // Take option sequence in IFR as ordered list's default value
3978 Link
= GetFirstNode (&Question
->OptionListHead
);
3979 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3980 Status
= EFI_SUCCESS
;
3981 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3982 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3984 if ((Option
->SuppressExpression
!= NULL
) &&
3985 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3989 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3992 if (Index
>= Question
->MaxContainers
) {
4007 Reset Questions to their initial value or default value in a Form, Formset or System.
4009 GetDefaultValueScope parameter decides which questions will reset
4010 to its default value.
4012 @param FormSet FormSet data structure.
4013 @param Form Form data structure.
4014 @param DefaultId The Class of the default.
4015 @param SettingScope Setting Scope for Default action.
4016 @param GetDefaultValueScope Get default value scope.
4017 @param Storage Get default value only for this storage.
4018 @param RetrieveValueFirst Whether call the retrieve call back to
4019 get the initial value before get default
4022 @retval EFI_SUCCESS The function completed successfully.
4023 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4028 IN FORM_BROWSER_FORMSET
*FormSet
,
4029 IN FORM_BROWSER_FORM
*Form
,
4030 IN UINT16 DefaultId
,
4031 IN BROWSER_SETTING_SCOPE SettingScope
,
4032 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4033 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4034 IN BOOLEAN RetrieveValueFirst
4038 LIST_ENTRY
*FormLink
;
4040 FORM_BROWSER_STATEMENT
*Question
;
4041 FORM_BROWSER_FORMSET
*LocalFormSet
;
4042 FORM_BROWSER_FORMSET
*OldFormSet
;
4044 Status
= EFI_SUCCESS
;
4047 // Check the supported setting level.
4049 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4050 return EFI_UNSUPPORTED
;
4053 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4054 return EFI_UNSUPPORTED
;
4057 if (SettingScope
== FormLevel
) {
4059 // Extract Form default
4061 Link
= GetFirstNode (&Form
->StatementListHead
);
4062 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4063 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4064 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4067 // If get default value only for this storage, check the storage first.
4069 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4074 // If get default value only for no storage question, just skip the question which has storage.
4076 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4081 // If Question is disabled, don't reset it to default
4083 if (Question
->Expression
!= NULL
) {
4084 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4089 if (RetrieveValueFirst
) {
4091 // Call the Retrieve call back to get the initial question value.
4093 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4097 // If not request to get the initial value or get initial value fail, then get default value.
4099 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4100 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4101 if (EFI_ERROR (Status
)) {
4107 // Synchronize Buffer storage's Edit buffer
4109 if ((Question
->Storage
!= NULL
) &&
4110 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4111 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4114 } else if (SettingScope
== FormSetLevel
) {
4115 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4116 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4117 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4118 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4119 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4121 } else if (SettingScope
== SystemLevel
) {
4123 // Preload all Hii formset.
4125 LoadAllHiiFormset();
4127 OldFormSet
= mSystemLevelFormSet
;
4130 // Set Default Value for each FormSet in the maintain list.
4132 Link
= GetFirstNode (&gBrowserFormSetList
);
4133 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4134 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4135 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4136 if (!ValidateFormSet(LocalFormSet
)) {
4140 mSystemLevelFormSet
= LocalFormSet
;
4142 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4145 mSystemLevelFormSet
= OldFormSet
;
4153 Validate whether this question's value has changed.
4155 @param FormSet FormSet data structure.
4156 @param Form Form data structure.
4157 @param Question Question to be initialized.
4158 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4160 @retval TRUE Question's value has changed.
4161 @retval FALSE Question's value has not changed
4165 IsQuestionValueChanged (
4166 IN FORM_BROWSER_FORMSET
*FormSet
,
4167 IN FORM_BROWSER_FORM
*Form
,
4168 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4169 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4172 EFI_HII_VALUE BackUpValue
;
4173 CHAR8
*BackUpBuffer
;
4174 EFI_HII_VALUE BackUpValue2
;
4175 CHAR8
*BackUpBuffer2
;
4177 BOOLEAN ValueChanged
;
4181 // For quetion without storage, always mark it as data not changed.
4183 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4187 BackUpBuffer
= NULL
;
4188 BackUpBuffer2
= NULL
;
4189 ValueChanged
= FALSE
;
4191 switch (Question
->Operand
) {
4192 case EFI_IFR_ORDERED_LIST_OP
:
4193 BufferWidth
= Question
->StorageWidth
;
4194 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4195 ASSERT (BackUpBuffer
!= NULL
);
4198 case EFI_IFR_STRING_OP
:
4199 case EFI_IFR_PASSWORD_OP
:
4200 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4201 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4202 ASSERT (BackUpBuffer
!= NULL
);
4209 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4211 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4212 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4213 ASSERT_EFI_ERROR(Status
);
4215 switch (Question
->Operand
) {
4216 case EFI_IFR_ORDERED_LIST_OP
:
4217 BufferWidth
= Question
->StorageWidth
;
4218 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4219 ASSERT (BackUpBuffer2
!= NULL
);
4222 case EFI_IFR_STRING_OP
:
4223 case EFI_IFR_PASSWORD_OP
:
4224 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4225 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4226 ASSERT (BackUpBuffer2
!= NULL
);
4233 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4235 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4236 ASSERT_EFI_ERROR(Status
);
4238 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4239 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4240 ValueChanged
= TRUE
;
4243 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4244 ASSERT_EFI_ERROR(Status
);
4246 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4247 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4248 ValueChanged
= TRUE
;
4252 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4253 if (BackUpBuffer
!= NULL
) {
4254 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4255 FreePool (BackUpBuffer
);
4258 if (BackUpBuffer2
!= NULL
) {
4259 FreePool (BackUpBuffer2
);
4262 Question
->ValueChanged
= ValueChanged
;
4264 return ValueChanged
;
4268 Initialize Question's Edit copy from Storage.
4270 @param Selection Selection contains the information about
4271 the Selection, form and formset to be displayed.
4272 Selection action may be updated in retrieve callback.
4273 If Selection is NULL, only initialize Question value.
4274 @param FormSet FormSet data structure.
4275 @param Form Form data structure.
4277 @retval EFI_SUCCESS The function completed successfully.
4282 IN OUT UI_MENU_SELECTION
*Selection
,
4283 IN FORM_BROWSER_FORMSET
*FormSet
,
4284 IN FORM_BROWSER_FORM
*Form
4289 FORM_BROWSER_STATEMENT
*Question
;
4291 Link
= GetFirstNode (&Form
->StatementListHead
);
4292 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4293 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4296 // Initialize local copy of Value for each Question
4298 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4299 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4301 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4303 if (EFI_ERROR (Status
)) {
4307 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4308 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4311 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4318 Initialize Question's Edit copy from Storage for the whole Formset.
4320 @param Selection Selection contains the information about
4321 the Selection, form and formset to be displayed.
4322 Selection action may be updated in retrieve callback.
4323 If Selection is NULL, only initialize Question value.
4324 @param FormSet FormSet data structure.
4326 @retval EFI_SUCCESS The function completed successfully.
4331 IN OUT UI_MENU_SELECTION
*Selection
,
4332 IN FORM_BROWSER_FORMSET
*FormSet
4337 FORM_BROWSER_FORM
*Form
;
4339 Link
= GetFirstNode (&FormSet
->FormListHead
);
4340 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4341 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4344 // Initialize local copy of Value for each Form
4346 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4347 if (EFI_ERROR (Status
)) {
4351 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4355 // Finished question initialization.
4357 FormSet
->QuestionInited
= TRUE
;
4363 Remove the Request element from the Config Request.
4365 @param Storage Pointer to the browser storage.
4366 @param RequestElement The pointer to the Request element.
4371 IN OUT BROWSER_STORAGE
*Storage
,
4372 IN CHAR16
*RequestElement
4378 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4380 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4382 if (NewStr
== NULL
) {
4387 // Remove this element from this ConfigRequest.
4390 NewStr
+= StrLen (RequestElement
);
4391 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4393 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4397 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4399 @param Storage Pointer to the browser storage.
4400 @param ConfigRequest The pointer to the Request element.
4404 RemoveConfigRequest (
4405 BROWSER_STORAGE
*Storage
,
4406 CHAR16
*ConfigRequest
4409 CHAR16
*RequestElement
;
4410 CHAR16
*NextRequestElement
;
4414 // No request element in it, just return.
4416 if (ConfigRequest
== NULL
) {
4420 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4422 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4427 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4429 SearchKey
= L
"&OFFSET";
4433 // Find SearchKey storage
4435 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4436 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4437 ASSERT (RequestElement
!= NULL
);
4438 RequestElement
= StrStr (RequestElement
, SearchKey
);
4440 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4443 while (RequestElement
!= NULL
) {
4445 // +1 to avoid find header itself.
4447 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4450 // The last Request element in configRequest string.
4452 if (NextRequestElement
!= NULL
) {
4454 // Replace "&" with '\0'.
4456 *NextRequestElement
= L
'\0';
4459 RemoveElement (Storage
, RequestElement
);
4461 if (NextRequestElement
!= NULL
) {
4463 // Restore '&' with '\0' for later used.
4465 *NextRequestElement
= L
'&';
4468 RequestElement
= NextRequestElement
;
4472 // If no request element remain, just remove the ConfigRequest string.
4474 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4475 FreePool (Storage
->ConfigRequest
);
4476 Storage
->ConfigRequest
= NULL
;
4477 Storage
->SpareStrLen
= 0;
4482 Base on the current formset info, clean the ConfigRequest string in browser storage.
4484 @param FormSet Pointer of the FormSet
4488 CleanBrowserStorage (
4489 IN OUT FORM_BROWSER_FORMSET
*FormSet
4493 FORMSET_STORAGE
*Storage
;
4495 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4496 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4497 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4498 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4500 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4501 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4505 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4506 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4507 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4508 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4509 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4510 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4512 Storage
->BrowserStorage
->Initialized
= FALSE
;
4518 Check whether current element in the ConfigReqeust string.
4520 @param BrowserStorage Storage which includes ConfigReqeust.
4521 @param RequestElement New element need to check.
4523 @retval TRUE The Element is in the ConfigReqeust string.
4524 @retval FALSE The Element not in the configReqeust String.
4529 BROWSER_STORAGE
*BrowserStorage
,
4530 CHAR16
*RequestElement
4533 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4537 Append the Request element to the Config Request.
4539 @param ConfigRequest Current ConfigRequest info.
4540 @param SpareStrLen Current remain free buffer for config reqeust.
4541 @param RequestElement New Request element.
4545 AppendConfigRequest (
4546 IN OUT CHAR16
**ConfigRequest
,
4547 IN OUT UINTN
*SpareStrLen
,
4548 IN CHAR16
*RequestElement
4555 StrLength
= StrLen (RequestElement
);
4558 // Append <RequestElement> to <ConfigRequest>
4560 if (StrLength
> *SpareStrLen
) {
4562 // Old String buffer is not sufficient for RequestElement, allocate a new one
4564 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4565 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4566 ASSERT (NewStr
!= NULL
);
4568 if (*ConfigRequest
!= NULL
) {
4569 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4570 FreePool (*ConfigRequest
);
4572 *ConfigRequest
= NewStr
;
4573 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4576 StrCat (*ConfigRequest
, RequestElement
);
4577 *SpareStrLen
-= StrLength
;
4581 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4583 @param Storage Form set Storage.
4584 @param Request The input request string.
4585 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4587 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4588 @retval FALSE All elements covered by current used elements.
4592 ConfigRequestAdjust (
4593 IN BROWSER_STORAGE
*Storage
,
4595 IN BOOLEAN RespString
4598 CHAR16
*RequestElement
;
4599 CHAR16
*NextRequestElement
;
4600 CHAR16
*NextElementBakup
;
4605 CHAR16
*ConfigRequest
;
4609 NextElementBakup
= NULL
;
4612 if (Request
!= NULL
) {
4613 ConfigRequest
= Request
;
4615 ConfigRequest
= Storage
->ConfigRequest
;
4618 if (Storage
->ConfigRequest
== NULL
) {
4619 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4623 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4625 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4630 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4632 SearchKey
= L
"&OFFSET";
4633 ValueKey
= L
"&VALUE";
4637 // Find SearchKey storage
4639 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4640 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4641 ASSERT (RequestElement
!= NULL
);
4642 RequestElement
= StrStr (RequestElement
, SearchKey
);
4644 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4647 while (RequestElement
!= NULL
) {
4650 // +1 to avoid find header itself.
4652 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4655 // The last Request element in configRequest string.
4657 if (NextRequestElement
!= NULL
) {
4658 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4659 NextElementBakup
= NextRequestElement
;
4660 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4661 ASSERT (NextRequestElement
!= NULL
);
4664 // Replace "&" with '\0'.
4666 *NextRequestElement
= L
'\0';
4668 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4669 NextElementBakup
= NextRequestElement
;
4670 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4671 ASSERT (NextRequestElement
!= NULL
);
4673 // Replace "&" with '\0'.
4675 *NextRequestElement
= L
'\0';
4679 if (!ElementValidation (Storage
, RequestElement
)) {
4681 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4683 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4687 if (NextRequestElement
!= NULL
) {
4689 // Restore '&' with '\0' for later used.
4691 *NextRequestElement
= L
'&';
4694 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4695 RequestElement
= NextElementBakup
;
4697 RequestElement
= NextRequestElement
;
4706 Base on ConfigRequest info to get default value for current formset.
4708 ConfigRequest info include the info about which questions in current formset need to
4709 get default value. This function only get these questions default value.
4711 @param FormSet FormSet data structure.
4712 @param Storage Storage need to update value.
4713 @param ConfigRequest The config request string.
4717 GetDefaultForFormset (
4718 IN FORM_BROWSER_FORMSET
*FormSet
,
4719 IN BROWSER_STORAGE
*Storage
,
4720 IN CHAR16
*ConfigRequest
4725 LIST_ENTRY BackUpList
;
4726 NAME_VALUE_NODE
*Node
;
4728 LIST_ENTRY
*NodeLink
;
4729 NAME_VALUE_NODE
*TmpNode
;
4731 EFI_STRING Progress
;
4735 InitializeListHead(&BackUpList
);
4738 // Back update the edit buffer.
4740 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4741 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4742 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4743 ASSERT (BackUpBuf
!= NULL
);
4744 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4745 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4746 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4747 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4748 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4751 // Only back Node belong to this formset.
4753 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4757 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4758 ASSERT (TmpNode
!= NULL
);
4759 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4760 ASSERT (TmpNode
->Name
!= NULL
);
4761 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4762 ASSERT (TmpNode
->EditValue
!= NULL
);
4764 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4769 // Get default value.
4771 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4774 // Update the question value based on the input ConfigRequest.
4776 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4777 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4778 ASSERT (BackUpBuf
!= NULL
);
4779 BufferSize
= Storage
->Size
;
4780 Status
= mHiiConfigRouting
->BlockToConfig(
4783 Storage
->EditBuffer
,
4788 ASSERT_EFI_ERROR (Status
);
4790 Status
= mHiiConfigRouting
->ConfigToBlock (
4797 ASSERT_EFI_ERROR (Status
);
4799 if (Result
!= NULL
) {
4803 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4804 FreePool (BackUpBuf
);
4805 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4807 // Update question value, only element in ConfigReqeust will be update.
4809 Link
= GetFirstNode (&BackUpList
);
4810 while (!IsNull (&BackUpList
, Link
)) {
4811 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4812 Link
= GetNextNode (&BackUpList
, Link
);
4814 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4818 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4819 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4820 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4821 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4823 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4827 FreePool (TmpNode
->EditValue
);
4828 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4830 RemoveEntryList (&Node
->Link
);
4831 FreePool (Node
->EditValue
);
4832 FreePool (Node
->Name
);
4838 // Restore the Name/Value node.
4840 Link
= GetFirstNode (&BackUpList
);
4841 while (!IsNull (&BackUpList
, Link
)) {
4842 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4843 Link
= GetNextNode (&BackUpList
, Link
);
4848 RemoveEntryList (&Node
->Link
);
4849 FreePool (Node
->EditValue
);
4850 FreePool (Node
->Name
);
4857 Fill storage's edit copy with settings requested from Configuration Driver.
4859 @param FormSet FormSet data structure.
4860 @param Storage Buffer Storage.
4865 IN FORM_BROWSER_FORMSET
*FormSet
,
4866 IN FORMSET_STORAGE
*Storage
4870 EFI_STRING Progress
;
4873 EFI_STRING ConfigRequest
;
4876 ConfigRequest
= NULL
;
4878 switch (Storage
->BrowserStorage
->Type
) {
4879 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4882 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4883 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4884 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4889 case EFI_HII_VARSTORE_BUFFER
:
4890 case EFI_HII_VARSTORE_NAME_VALUE
:
4892 // Skip if there is no RequestElement.
4894 if (Storage
->ElementCount
== 0) {
4899 // Just update the ConfigRequest, if storage already initialized.
4901 if (Storage
->BrowserStorage
->Initialized
) {
4902 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4906 Storage
->BrowserStorage
->Initialized
= TRUE
;
4913 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4915 // Create the config request string to get all fields for this storage.
4916 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4917 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4919 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4920 ConfigRequest
= AllocateZeroPool (StrLen
);
4921 ASSERT (ConfigRequest
!= NULL
);
4925 L
"%s&OFFSET=0&WIDTH=%04x",
4926 Storage
->BrowserStorage
->ConfigHdr
,
4927 Storage
->BrowserStorage
->Size
);
4929 ConfigRequest
= Storage
->ConfigRequest
;
4933 // Request current settings from Configuration Driver
4935 Status
= mHiiConfigRouting
->ExtractConfig (
4943 // If get value fail, extract default from IFR binary
4945 if (EFI_ERROR (Status
)) {
4946 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4949 // Convert Result from <ConfigAltResp> to <ConfigResp>
4951 StrPtr
= StrStr (Result
, L
"&GUID=");
4952 if (StrPtr
!= NULL
) {
4956 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4960 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4963 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4965 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
4967 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4968 if (ConfigRequest
!= NULL
) {
4969 FreePool (ConfigRequest
);
4975 Get Value changed status from old question.
4977 @param NewFormSet FormSet data structure.
4978 @param OldQuestion Old question which has value changed.
4982 SyncStatusForQuestion (
4983 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4984 IN FORM_BROWSER_STATEMENT
*OldQuestion
4988 LIST_ENTRY
*QuestionLink
;
4989 FORM_BROWSER_FORM
*Form
;
4990 FORM_BROWSER_STATEMENT
*Question
;
4993 // For each form in one formset.
4995 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4996 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4997 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4998 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5001 // for each question in one form.
5003 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5004 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5005 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5006 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5008 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5009 Question
->ValueChanged
= TRUE
;
5017 Get Value changed status from old formset.
5019 @param NewFormSet FormSet data structure.
5020 @param OldFormSet FormSet data structure.
5024 SyncStatusForFormSet (
5025 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5026 IN FORM_BROWSER_FORMSET
*OldFormSet
5030 LIST_ENTRY
*QuestionLink
;
5031 FORM_BROWSER_FORM
*Form
;
5032 FORM_BROWSER_STATEMENT
*Question
;
5035 // For each form in one formset.
5037 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5038 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5039 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5040 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5043 // for each question in one form.
5045 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5046 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5047 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5048 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5050 if (!Question
->ValueChanged
) {
5055 // Find the same question in new formset and update the value changed flag.
5057 SyncStatusForQuestion (NewFormSet
, Question
);
5063 Get current setting of Questions.
5065 @param FormSet FormSet data structure.
5069 InitializeCurrentSetting (
5070 IN OUT FORM_BROWSER_FORMSET
*FormSet
5074 FORMSET_STORAGE
*Storage
;
5075 FORM_BROWSER_FORMSET
*OldFormSet
;
5078 // Try to find pre FormSet in the maintain backup list.
5079 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5081 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5082 if (OldFormSet
!= NULL
) {
5083 SyncStatusForFormSet (FormSet
, OldFormSet
);
5084 RemoveEntryList (&OldFormSet
->Link
);
5085 DestroyFormSet (OldFormSet
);
5087 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5090 // Extract default from IFR binary for no storage questions.
5092 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
5095 // Request current settings from Configuration Driver
5097 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5098 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5099 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5101 LoadStorage (FormSet
, Storage
);
5103 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5109 Fetch the Ifr binary data of a FormSet.
5111 @param Handle PackageList Handle
5112 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5113 specified (NULL or zero GUID), take the first
5114 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5115 found in package list.
5116 On output, GUID of the formset found(if not NULL).
5117 @param BinaryLength The length of the FormSet IFR binary.
5118 @param BinaryData The buffer designed to receive the FormSet.
5120 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5121 BufferLength was updated.
5122 @retval EFI_INVALID_PARAMETER The handle is unknown.
5123 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5124 be found with the requested FormId.
5129 IN EFI_HII_HANDLE Handle
,
5130 IN OUT EFI_GUID
*FormSetGuid
,
5131 OUT UINTN
*BinaryLength
,
5132 OUT UINT8
**BinaryData
5136 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5142 UINT32 PackageListLength
;
5143 EFI_HII_PACKAGE_HEADER PackageHeader
;
5145 UINT8 NumberOfClassGuid
;
5146 BOOLEAN ClassGuidMatch
;
5147 EFI_GUID
*ClassGuid
;
5148 EFI_GUID
*ComparingGuid
;
5152 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5155 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5157 if (FormSetGuid
== NULL
) {
5158 ComparingGuid
= &gZeroGuid
;
5160 ComparingGuid
= FormSetGuid
;
5164 // Get HII PackageList
5167 HiiPackageList
= NULL
;
5168 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5169 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5170 HiiPackageList
= AllocatePool (BufferSize
);
5171 ASSERT (HiiPackageList
!= NULL
);
5173 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5175 if (EFI_ERROR (Status
)) {
5178 ASSERT (HiiPackageList
!= NULL
);
5181 // Get Form package from this HII package List
5183 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5185 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5187 ClassGuidMatch
= FALSE
;
5188 while (Offset
< PackageListLength
) {
5189 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5190 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5192 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5194 // Search FormSet in this Form Package
5196 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5197 while (Offset2
< PackageHeader
.Length
) {
5198 OpCodeData
= Package
+ Offset2
;
5200 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5202 // Try to compare against formset GUID
5204 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5205 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5209 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5211 // Try to compare against formset class GUID
5213 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5214 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5215 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5216 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5217 ClassGuidMatch
= TRUE
;
5221 if (ClassGuidMatch
) {
5224 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5225 ClassGuidMatch
= TRUE
;
5230 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5233 if (Offset2
< PackageHeader
.Length
) {
5235 // Target formset found
5241 Offset
+= PackageHeader
.Length
;
5244 if (Offset
>= PackageListLength
) {
5246 // Form package not found in this Package List
5248 FreePool (HiiPackageList
);
5249 return EFI_NOT_FOUND
;
5252 if (FormSetGuid
!= NULL
) {
5254 // Return the FormSet GUID
5256 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5260 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5261 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5262 // of the Form Package.
5264 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5265 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5267 FreePool (HiiPackageList
);
5269 if (*BinaryData
== NULL
) {
5270 return EFI_OUT_OF_RESOURCES
;
5278 Initialize the internal data structure of a FormSet.
5280 @param Handle PackageList Handle
5281 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5282 specified (NULL or zero GUID), take the first
5283 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5284 found in package list.
5285 On output, GUID of the formset found(if not NULL).
5286 @param FormSet FormSet data structure.
5288 @retval EFI_SUCCESS The function completed successfully.
5289 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5294 IN EFI_HII_HANDLE Handle
,
5295 IN OUT EFI_GUID
*FormSetGuid
,
5296 OUT FORM_BROWSER_FORMSET
*FormSet
5300 EFI_HANDLE DriverHandle
;
5302 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5303 if (EFI_ERROR (Status
)) {
5307 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5308 FormSet
->HiiHandle
= Handle
;
5309 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5310 FormSet
->QuestionInited
= FALSE
;
5313 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5315 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5316 if (EFI_ERROR (Status
)) {
5319 FormSet
->DriverHandle
= DriverHandle
;
5320 Status
= gBS
->HandleProtocol (
5322 &gEfiHiiConfigAccessProtocolGuid
,
5323 (VOID
**) &FormSet
->ConfigAccess
5325 if (EFI_ERROR (Status
)) {
5327 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5328 // list, then there will be no configuration action required
5330 FormSet
->ConfigAccess
= NULL
;
5334 // Parse the IFR binary OpCodes
5336 Status
= ParseOpCodes (FormSet
);
5343 Save globals used by previous call to SendForm(). SendForm() may be called from
5344 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5345 So, save globals of previous call to SendForm() and restore them upon exit.
5349 SaveBrowserContext (
5353 BROWSER_CONTEXT
*Context
;
5354 FORM_ENTRY_INFO
*MenuList
;
5356 gBrowserContextCount
++;
5357 if (gBrowserContextCount
== 1) {
5359 // This is not reentry of SendForm(), no context to save
5364 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5365 ASSERT (Context
!= NULL
);
5367 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5370 // Save FormBrowser context
5372 Context
->Selection
= gCurrentSelection
;
5373 Context
->ResetRequired
= gResetRequired
;
5374 Context
->ExitRequired
= gExitRequired
;
5375 Context
->HiiHandle
= mCurrentHiiHandle
;
5376 Context
->FormId
= mCurrentFormId
;
5377 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5380 // Save the menu history data.
5382 InitializeListHead(&Context
->FormHistoryList
);
5383 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5384 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5385 RemoveEntryList (&MenuList
->Link
);
5387 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5391 // Insert to FormBrowser context list
5393 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5398 Restore globals used by previous call to SendForm().
5402 RestoreBrowserContext (
5407 BROWSER_CONTEXT
*Context
;
5408 FORM_ENTRY_INFO
*MenuList
;
5410 ASSERT (gBrowserContextCount
!= 0);
5411 gBrowserContextCount
--;
5412 if (gBrowserContextCount
== 0) {
5414 // This is not reentry of SendForm(), no context to restore
5419 ASSERT (!IsListEmpty (&gBrowserContextList
));
5421 Link
= GetFirstNode (&gBrowserContextList
);
5422 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5425 // Restore FormBrowser context
5427 gCurrentSelection
= Context
->Selection
;
5428 gResetRequired
= Context
->ResetRequired
;
5429 gExitRequired
= Context
->ExitRequired
;
5430 mCurrentHiiHandle
= Context
->HiiHandle
;
5431 mCurrentFormId
= Context
->FormId
;
5432 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5435 // Restore the menu history data.
5437 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5438 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5439 RemoveEntryList (&MenuList
->Link
);
5441 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5445 // Remove from FormBrowser context list
5447 RemoveEntryList (&Context
->Link
);
5448 gBS
->FreePool (Context
);
5452 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5454 @param Handle The Hii Handle.
5456 @return the found FormSet context. If no found, NULL will return.
5459 FORM_BROWSER_FORMSET
*
5460 GetFormSetFromHiiHandle (
5461 EFI_HII_HANDLE Handle
5465 FORM_BROWSER_FORMSET
*FormSet
;
5467 Link
= GetFirstNode (&gBrowserFormSetList
);
5468 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5469 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5470 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5471 if (!ValidateFormSet(FormSet
)) {
5474 if (FormSet
->HiiHandle
== Handle
) {
5483 Check whether the input HII handle is the FormSet that is being used.
5485 @param Handle The Hii Handle.
5487 @retval TRUE HII handle is being used.
5488 @retval FALSE HII handle is not being used.
5492 IsHiiHandleInBrowserContext (
5493 EFI_HII_HANDLE Handle
5497 BROWSER_CONTEXT
*Context
;
5500 // HiiHandle is Current FormSet.
5502 if (mCurrentHiiHandle
== Handle
) {
5507 // Check whether HiiHandle is in BrowserContext.
5509 Link
= GetFirstNode (&gBrowserContextList
);
5510 while (!IsNull (&gBrowserContextList
, Link
)) {
5511 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5512 if (Context
->HiiHandle
== Handle
) {
5514 // HiiHandle is in BrowserContext
5518 Link
= GetNextNode (&gBrowserContextList
, Link
);
5525 Perform Password check.
5526 Passwork may be encrypted by driver that requires the specific check.
5528 @param Form Form where Password Statement is in.
5529 @param Statement Password statement
5530 @param PasswordString Password string to be checked. It may be NULL.
5531 NULL means to restore password.
5532 "" string can be used to checked whether old password does exist.
5534 @return Status Status of Password check.
5539 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5540 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5541 IN EFI_STRING PasswordString OPTIONAL
5545 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5546 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5547 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5548 FORM_BROWSER_STATEMENT
*Question
;
5550 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5551 Question
= GetBrowserStatement(Statement
);
5552 ASSERT (Question
!= NULL
);
5554 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5555 if (ConfigAccess
== NULL
) {
5556 return EFI_UNSUPPORTED
;
5559 if (PasswordString
== NULL
) {
5564 // Check whether has preexisted password.
5566 if (PasswordString
[0] == 0) {
5567 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5570 return EFI_NOT_READY
;
5575 // Check whether the input password is same as preexisted password.
5577 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5580 return EFI_NOT_READY
;
5585 // Prepare password string in HII database
5587 if (PasswordString
!= NULL
) {
5588 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5590 IfrTypeValue
.string
= 0;
5594 // Send password to Configuration Driver for validation
5596 Status
= ConfigAccess
->Callback (
5598 EFI_BROWSER_ACTION_CHANGING
,
5599 Question
->QuestionId
,
5600 Question
->HiiValue
.Type
,
5606 // Remove password string from HII database
5608 if (PasswordString
!= NULL
) {
5609 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5616 Find the registered HotKey based on KeyData.
5618 @param[in] KeyData A pointer to a buffer that describes the keystroke
5619 information for the hot key.
5621 @return The registered HotKey context. If no found, NULL will return.
5624 GetHotKeyFromRegisterList (
5625 IN EFI_INPUT_KEY
*KeyData
5629 BROWSER_HOT_KEY
*HotKey
;
5631 Link
= GetFirstNode (&gBrowserHotKeyList
);
5632 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5633 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5634 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5637 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5644 Configure what scope the hot key will impact.
5645 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5646 If no scope is set, the default scope will be FormSet level.
5647 After all registered hot keys are removed, previous Scope can reset to another level.
5649 @param[in] Scope Scope level to be set.
5651 @retval EFI_SUCCESS Scope is set correctly.
5652 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5653 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5659 IN BROWSER_SETTING_SCOPE Scope
5662 if (Scope
>= MaxLevel
) {
5663 return EFI_INVALID_PARAMETER
;
5667 // When no hot key registered in system or on the first setting,
5668 // Scope can be set.
5670 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5671 gBrowserSettingScope
= Scope
;
5672 mBrowserScopeFirstSet
= FALSE
;
5673 } else if (Scope
!= gBrowserSettingScope
) {
5674 return EFI_UNSUPPORTED
;
5681 Register the hot key with its browser action, or unregistered the hot key.
5682 Only support hot key that is not printable character (control key, function key, etc.).
5683 If the action value is zero, the hot key will be unregistered if it has been registered.
5684 If the same hot key has been registered, the new action and help string will override the previous ones.
5686 @param[in] KeyData A pointer to a buffer that describes the keystroke
5687 information for the hot key. Its type is EFI_INPUT_KEY to
5688 be supported by all ConsoleIn devices.
5689 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5690 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5691 @param[in] HelpString Help string that describes the hot key information.
5692 Its value may be NULL for the unregistered hot key.
5694 @retval EFI_SUCCESS Hot key is registered or unregistered.
5695 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5696 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5697 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5702 IN EFI_INPUT_KEY
*KeyData
,
5704 IN UINT16 DefaultId
,
5705 IN EFI_STRING HelpString OPTIONAL
5708 BROWSER_HOT_KEY
*HotKey
;
5711 // Check input parameters.
5713 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5714 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5715 return EFI_INVALID_PARAMETER
;
5719 // Check whether the input KeyData is in BrowserHotKeyList.
5721 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5724 // Unregister HotKey
5726 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5727 if (HotKey
!= NULL
) {
5729 // The registered HotKey is found.
5730 // Remove it from List, and free its resource.
5732 RemoveEntryList (&HotKey
->Link
);
5733 FreePool (HotKey
->KeyData
);
5734 FreePool (HotKey
->HelpString
);
5738 // The registered HotKey is not found.
5740 return EFI_NOT_FOUND
;
5745 // Register HotKey into List.
5747 if (HotKey
== NULL
) {
5749 // Create new Key, and add it into List.
5751 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5752 ASSERT (HotKey
!= NULL
);
5753 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5754 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5755 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5759 // Fill HotKey information.
5761 HotKey
->Action
= Action
;
5762 HotKey
->DefaultId
= DefaultId
;
5763 if (HotKey
->HelpString
!= NULL
) {
5764 FreePool (HotKey
->HelpString
);
5766 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5772 Register Exit handler function.
5773 When more than one handler function is registered, the latter one will override the previous one.
5774 When NULL handler is specified, the previous Exit handler will be unregistered.
5776 @param[in] Handler Pointer to handler function.
5781 RegiserExitHandler (
5782 IN EXIT_HANDLER Handler
5785 ExitHandlerFunction
= Handler
;
5790 Check whether the browser data has been modified.
5792 @retval TRUE Browser data is modified.
5793 @retval FALSE No browser data is modified.
5798 IsBrowserDataModified (
5803 FORM_BROWSER_FORMSET
*FormSet
;
5805 switch (gBrowserSettingScope
) {
5807 if (gCurrentSelection
== NULL
) {
5810 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5813 if (gCurrentSelection
== NULL
) {
5816 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5819 Link
= GetFirstNode (&gBrowserFormSetList
);
5820 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5821 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5822 if (!ValidateFormSet(FormSet
)) {
5826 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5829 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5839 Execute the action requested by the Action parameter.
5841 @param[in] Action Execute the request action.
5842 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5844 @retval EFI_SUCCESS Execute the request action succss.
5845 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5856 FORM_BROWSER_FORMSET
*FormSet
;
5857 FORM_BROWSER_FORM
*Form
;
5859 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5860 return EFI_NOT_READY
;
5863 Status
= EFI_SUCCESS
;
5866 if (gBrowserSettingScope
< SystemLevel
) {
5867 FormSet
= gCurrentSelection
->FormSet
;
5868 Form
= gCurrentSelection
->Form
;
5872 // Executet the discard action.
5874 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5875 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5876 if (EFI_ERROR (Status
)) {
5882 // Executet the difault action.
5884 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5885 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5886 if (EFI_ERROR (Status
)) {
5889 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5893 // Executet the submit action.
5895 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5896 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5897 if (EFI_ERROR (Status
)) {
5903 // Executet the reset action.
5905 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5906 gResetRequired
= TRUE
;
5910 // Executet the exit action.
5912 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5913 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5914 if (gBrowserSettingScope
== SystemLevel
) {
5915 if (ExitHandlerFunction
!= NULL
) {
5916 ExitHandlerFunction ();
5920 gExitRequired
= TRUE
;
5927 Create reminder to let user to choose save or discard the changed browser data.
5928 Caller can use it to actively check the changed browser data.
5930 @retval BROWSER_NO_CHANGES No browser data is changed.
5931 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5932 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5933 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5943 FORM_BROWSER_FORMSET
*FormSet
;
5944 BOOLEAN IsDataChanged
;
5945 UINT32 DataSavedAction
;
5948 DataSavedAction
= BROWSER_NO_CHANGES
;
5949 IsDataChanged
= FALSE
;
5950 Link
= GetFirstNode (&gBrowserFormSetList
);
5951 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5952 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5953 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5954 if (!ValidateFormSet(FormSet
)) {
5957 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5958 IsDataChanged
= TRUE
;
5964 // No data is changed. No save is required.
5966 if (!IsDataChanged
) {
5967 return DataSavedAction
;
5971 // If data is changed, prompt user to save or discard it.
5974 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5976 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5977 SubmitForm (NULL
, NULL
, SystemLevel
);
5978 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5980 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5981 DiscardForm (NULL
, NULL
, SystemLevel
);
5982 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5984 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5985 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5990 return DataSavedAction
;
5994 Check whether the Reset Required for the browser
5996 @retval TRUE Browser required to reset after exit.
5997 @retval FALSE Browser not need to reset after exit.
6006 return gResetRequired
;