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 while (*EndStr
!= '&') {
2600 // For Buffer type, Skip the ConfigHdr part.
2602 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2606 Progress
= EndStr
+ 1;
2610 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2612 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2614 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2615 // here, just keep the "Fred" string.
2617 EndStr
= StrStr (Progress
, L
"=");
2621 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2622 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2624 EndStr
= StrStr (Progress
, L
"&VALUE=");
2629 // Search in the form list.
2631 Link
= GetFirstNode (&FormSet
->FormListHead
);
2632 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2633 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2634 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2637 // Search in the ConfigReqeust list in this form.
2639 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2640 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2641 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2642 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2644 if (Storage
!= ConfigInfo
->Storage
) {
2648 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2650 // Find the OffsetWidth string in this form.
2657 if (*RetForm
!= NULL
) {
2658 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2659 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2660 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2661 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2663 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2664 *RetQuestion
= Statement
;
2670 if (*RetForm
!= NULL
) {
2676 // restore the OffsetWidth string to the original format.
2678 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2684 return (BOOLEAN
) (*RetForm
!= NULL
);
2688 Popup an save error info and get user input.
2690 @param TitleId The form title id.
2691 @param HiiHandle The hii handle for this package.
2693 @retval UINT32 The user select option for the save fail.
2694 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2698 IN EFI_STRING_ID TitleId
,
2699 IN EFI_HII_HANDLE HiiHandle
2703 CHAR16
*StringBuffer
;
2706 FormTitle
= GetToken (TitleId
, HiiHandle
);
2708 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2709 ASSERT (StringBuffer
!= NULL
);
2713 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2714 L
"Submit Fail For Form: %s.",
2718 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2720 FreePool (StringBuffer
);
2721 FreePool (FormTitle
);
2727 Popup an NO_SUBMIT_IF error info and get user input.
2729 @param TitleId The form title id.
2730 @param HiiHandle The hii handle for this package.
2732 @retval UINT32 The user select option for the save fail.
2733 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2736 ConfirmNoSubmitFail (
2737 IN EFI_STRING_ID TitleId
,
2738 IN EFI_HII_HANDLE HiiHandle
2742 CHAR16
*StringBuffer
;
2745 FormTitle
= GetToken (TitleId
, HiiHandle
);
2747 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2748 ASSERT (StringBuffer
!= NULL
);
2752 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2753 L
"NO_SUBMIT_IF error For Form: %s.",
2757 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2759 FreePool (StringBuffer
);
2760 FreePool (FormTitle
);
2766 Discard data based on the input setting scope (Form, FormSet or System).
2768 @param FormSet FormSet data structure.
2769 @param Form Form data structure.
2770 @param SettingScope Setting Scope for Discard action.
2772 @retval EFI_SUCCESS The function completed successfully.
2773 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2778 IN FORM_BROWSER_FORMSET
*FormSet
,
2779 IN FORM_BROWSER_FORM
*Form
,
2780 IN BROWSER_SETTING_SCOPE SettingScope
2784 FORMSET_STORAGE
*Storage
;
2785 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2786 FORM_BROWSER_FORMSET
*LocalFormSet
;
2787 FORM_BROWSER_FORMSET
*OldFormSet
;
2790 // Check the supported setting level.
2792 if (SettingScope
>= MaxLevel
) {
2793 return EFI_UNSUPPORTED
;
2796 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2798 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2799 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2800 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2801 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2803 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2808 // Skip if there is no RequestElement
2810 if (ConfigInfo
->ElementCount
== 0) {
2815 // Prepare <ConfigResp>
2817 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2820 // Call callback with Changed type to inform the driver.
2822 SendDiscardInfoToDriver (FormSet
, Form
);
2825 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2826 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2829 // Discard Buffer storage or Name/Value storage
2831 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2832 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2833 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2834 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2836 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2841 // Skip if there is no RequestElement
2843 if (Storage
->ElementCount
== 0) {
2847 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2850 Link
= GetFirstNode (&FormSet
->FormListHead
);
2851 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2852 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2853 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2856 // Call callback with Changed type to inform the driver.
2858 SendDiscardInfoToDriver (FormSet
, Form
);
2861 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2862 } else if (SettingScope
== SystemLevel
) {
2864 // System Level Discard.
2866 OldFormSet
= mSystemLevelFormSet
;
2869 // Discard changed value for each FormSet in the maintain list.
2871 Link
= GetFirstNode (&gBrowserFormSetList
);
2872 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2873 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2874 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2875 if (!ValidateFormSet(LocalFormSet
)) {
2879 mSystemLevelFormSet
= LocalFormSet
;
2881 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2882 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2884 // Remove maintain backup list after discard except for the current using FormSet.
2886 CleanBrowserStorage(LocalFormSet
);
2887 RemoveEntryList (&LocalFormSet
->Link
);
2888 DestroyFormSet (LocalFormSet
);
2892 mSystemLevelFormSet
= OldFormSet
;
2899 Submit data for a form.
2901 @param FormSet FormSet data structure.
2902 @param Form Form data structure.
2904 @retval EFI_SUCCESS The function completed successfully.
2905 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2910 IN FORM_BROWSER_FORMSET
*FormSet
,
2911 IN FORM_BROWSER_FORM
*Form
2916 EFI_STRING ConfigResp
;
2917 EFI_STRING Progress
;
2918 BROWSER_STORAGE
*Storage
;
2919 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2921 if (!IsNvUpdateRequiredForForm (Form
)) {
2925 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2926 if (EFI_ERROR (Status
)) {
2930 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2931 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2932 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2933 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2935 Storage
= ConfigInfo
->Storage
;
2936 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2941 // Skip if there is no RequestElement
2943 if (ConfigInfo
->ElementCount
== 0) {
2948 // 1. Prepare <ConfigResp>
2950 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2951 if (EFI_ERROR (Status
)) {
2956 // 2. Set value to hii config routine protocol.
2958 Status
= mHiiConfigRouting
->RouteConfig (
2963 FreePool (ConfigResp
);
2965 if (EFI_ERROR (Status
)) {
2966 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2971 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2973 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2977 // 4. Process the save failed storage.
2979 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2980 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
2981 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2982 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
2983 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
2984 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
2986 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2988 Status
= EFI_SUCCESS
;
2991 Status
= EFI_UNSUPPORTED
;
2995 // Free Form save fail list.
2997 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2998 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2999 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3000 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3005 // 5. Update the NV flag.
3007 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3013 Submit data for a formset.
3015 @param FormSet FormSet data structure.
3016 @param SkipProcessFail Whether skip to process the save failed storage.
3017 If submit formset is called when do system level save,
3018 set this value to true and process the failed formset
3020 if submit formset is called when do formset level save,
3021 set the value to false and process the failed storage
3022 right after process all storages for this formset.
3024 @retval EFI_SUCCESS The function completed successfully.
3025 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3030 IN FORM_BROWSER_FORMSET
*FormSet
,
3031 IN BOOLEAN SkipProcessFail
3036 EFI_STRING ConfigResp
;
3037 EFI_STRING Progress
;
3038 BROWSER_STORAGE
*Storage
;
3039 FORMSET_STORAGE
*FormSetStorage
;
3040 FORM_BROWSER_FORM
*Form
;
3041 BOOLEAN HasInserted
;
3042 FORM_BROWSER_STATEMENT
*Question
;
3044 HasInserted
= FALSE
;
3046 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3051 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3052 if (EFI_ERROR (Status
)) {
3053 if (SkipProcessFail
) {
3055 // Process NO_SUBMIT check first, so insert it at head.
3057 FormSet
->SaveFailForm
= Form
;
3058 FormSet
->SaveFailStatement
= Question
;
3059 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3068 // Submit Buffer storage or Name/Value storage
3070 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3071 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3072 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3073 Storage
= FormSetStorage
->BrowserStorage
;
3074 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3076 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3081 // Skip if there is no RequestElement
3083 if (FormSetStorage
->ElementCount
== 0) {
3088 // 1. Prepare <ConfigResp>
3090 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3091 if (EFI_ERROR (Status
)) {
3096 // 2. Send <ConfigResp> to Routine config Protocol.
3098 Status
= mHiiConfigRouting
->RouteConfig (
3103 if (EFI_ERROR (Status
)) {
3104 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3107 // Call submit formset for system level, save the formset info
3108 // and process later.
3110 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3111 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3112 FormSet
->SaveFailForm
= Form
;
3113 FormSet
->SaveFailStatement
= Question
;
3114 if (SkipProcessFail
) {
3115 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3120 FreePool (ConfigResp
);
3124 FreePool (ConfigResp
);
3126 // 3. Config success, update storage shadow Buffer
3128 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3132 // 4. Has save fail storage need to handle.
3135 if (!SkipProcessFail
) {
3137 // If not in system level, just handl the save failed storage here.
3139 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3140 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3141 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3142 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3143 Storage
= FormSetStorage
->BrowserStorage
;
3144 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3146 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3148 Status
= EFI_SUCCESS
;
3151 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3153 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3154 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3155 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3156 gCurrentSelection
->FormId
= Form
->FormId
;
3157 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3159 Status
= EFI_UNSUPPORTED
;
3163 // Free FormSet save fail list.
3165 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3166 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3167 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3168 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3172 // If in system level, just return error and handle the failed formset later.
3174 Status
= EFI_UNSUPPORTED
;
3179 // 5. Update the NV flag.
3181 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3187 Submit data for all formsets.
3189 @retval EFI_SUCCESS The function completed successfully.
3190 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3200 LIST_ENTRY
*StorageLink
;
3201 BROWSER_STORAGE
*Storage
;
3202 FORMSET_STORAGE
*FormSetStorage
;
3203 FORM_BROWSER_FORM
*Form
;
3204 FORM_BROWSER_FORMSET
*LocalFormSet
;
3205 UINT32 UserSelection
;
3206 FORM_BROWSER_STATEMENT
*Question
;
3208 mSystemSubmit
= TRUE
;
3209 Link
= GetFirstNode (&gBrowserFormSetList
);
3210 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3211 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3212 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3213 if (!ValidateFormSet(LocalFormSet
)) {
3217 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3218 if (EFI_ERROR (Status
)) {
3223 // Remove maintain backup list after save except for the current using FormSet.
3225 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3226 CleanBrowserStorage(LocalFormSet
);
3227 RemoveEntryList (&LocalFormSet
->Link
);
3228 DestroyFormSet (LocalFormSet
);
3231 mSystemSubmit
= FALSE
;
3233 Status
= EFI_SUCCESS
;
3236 // Process the save failed formsets.
3238 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3239 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3240 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3241 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3243 if (!ValidateFormSet(LocalFormSet
)) {
3247 Form
= LocalFormSet
->SaveFailForm
;
3248 Question
= LocalFormSet
->SaveFailStatement
;
3251 // Confirm with user, get user input.
3253 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3255 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3257 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3259 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3262 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3263 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3264 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3265 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3266 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3267 Storage
= FormSetStorage
->BrowserStorage
;
3268 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3270 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3273 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3274 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3275 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3276 Storage
= FormSetStorage
->BrowserStorage
;
3277 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3279 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3283 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3284 CleanBrowserStorage(LocalFormSet
);
3285 RemoveEntryList (&LocalFormSet
->Link
);
3286 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3287 DestroyFormSet (LocalFormSet
);
3289 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3292 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3293 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3296 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3298 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3299 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3300 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3301 gCurrentSelection
->FormId
= Form
->FormId
;
3302 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3304 Status
= EFI_UNSUPPORTED
;
3310 // Clean the list which will not process.
3312 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3313 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3314 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3315 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3317 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3318 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3319 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3320 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3328 Submit data based on the input Setting level (Form, FormSet or System).
3330 @param FormSet FormSet data structure.
3331 @param Form Form data structure.
3332 @param SettingScope Setting Scope for Submit action.
3334 @retval EFI_SUCCESS The function completed successfully.
3335 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3340 IN FORM_BROWSER_FORMSET
*FormSet
,
3341 IN FORM_BROWSER_FORM
*Form
,
3342 IN BROWSER_SETTING_SCOPE SettingScope
3347 switch (SettingScope
) {
3349 Status
= SubmitForForm(FormSet
, Form
);
3353 Status
= SubmitForFormSet (FormSet
, FALSE
);
3357 Status
= SubmitForSystem ();
3361 Status
= EFI_UNSUPPORTED
;
3369 Get Question default value from AltCfg string.
3371 @param FormSet The form set.
3372 @param Question The question.
3373 @param DefaultId The default Id.
3375 @retval EFI_SUCCESS Question is reset to default value.
3379 GetDefaultValueFromAltCfg (
3380 IN FORM_BROWSER_FORMSET
*FormSet
,
3381 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3385 BOOLEAN IsBufferStorage
;
3388 BROWSER_STORAGE
*Storage
;
3389 CHAR16
*ConfigRequest
;
3402 Status
= EFI_NOT_FOUND
;
3405 ConfigRequest
= NULL
;
3409 Storage
= Question
->Storage
;
3411 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3416 // Question Value is provided by Buffer Storage or NameValue Storage
3418 if (Question
->BufferValue
!= NULL
) {
3420 // This Question is password or orderedlist
3422 Dst
= Question
->BufferValue
;
3425 // Other type of Questions
3427 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
3430 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3431 IsBufferStorage
= TRUE
;
3433 IsBufferStorage
= FALSE
;
3435 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
3438 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
3439 // <ConfigHdr> + "&" + <VariableName>
3441 if (IsBufferStorage
) {
3442 Length
= StrLen (Storage
->ConfigHdr
);
3443 Length
+= StrLen (Question
->BlockName
);
3445 Length
= StrLen (Storage
->ConfigHdr
);
3446 Length
+= StrLen (Question
->VariableName
) + 1;
3448 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
3449 ASSERT (ConfigRequest
!= NULL
);
3451 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
3452 if (IsBufferStorage
) {
3453 StrCat (ConfigRequest
, Question
->BlockName
);
3455 StrCat (ConfigRequest
, L
"&");
3456 StrCat (ConfigRequest
, Question
->VariableName
);
3459 Status
= mHiiConfigRouting
->ExtractConfig (
3465 if (EFI_ERROR (Status
)) {
3470 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
3471 // Get the default configuration string according to the default ID.
3473 Status
= mHiiConfigRouting
->GetAltConfig (
3479 &DefaultId
, // it can be NULL to get the current setting.
3484 // The required setting can't be found. So, it is not required to be validated and set.
3486 if (EFI_ERROR (Status
)) {
3490 if (ConfigResp
== NULL
) {
3491 Status
= EFI_NOT_FOUND
;
3496 // Skip <ConfigRequest>
3498 if (IsBufferStorage
) {
3499 Value
= StrStr (ConfigResp
, L
"&VALUE");
3500 ASSERT (Value
!= NULL
);
3506 Value
= StrStr (ConfigResp
, Question
->VariableName
);
3507 ASSERT (Value
!= NULL
);
3509 Value
= Value
+ StrLen (Question
->VariableName
);
3511 if (*Value
!= '=') {
3512 Status
= EFI_NOT_FOUND
;
3516 // Skip '=', point to value
3521 // Suppress <AltResp> if any
3524 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3529 LengthStr
= StrLen (Value
);
3530 if (!IsBufferStorage
&& IsString
) {
3531 StringPtr
= (CHAR16
*) Dst
;
3532 ZeroMem (TemStr
, sizeof (TemStr
));
3533 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
3534 StrnCpy (TemStr
, Value
+ Index
, 4);
3535 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
3538 // Add tailing L'\0' character
3540 StringPtr
[Index
/4] = L
'\0';
3542 ZeroMem (TemStr
, sizeof (TemStr
));
3543 for (Index
= 0; Index
< LengthStr
; Index
++) {
3544 TemStr
[0] = Value
[LengthStr
- Index
- 1];
3545 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
3546 if ((Index
& 1) == 0) {
3547 Dst
[Index
/2] = DigitUint8
;
3549 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
3555 if (ConfigRequest
!= NULL
){
3556 FreePool (ConfigRequest
);
3559 if (ConfigResp
!= NULL
) {
3560 FreePool (ConfigResp
);
3563 if (Result
!= NULL
) {
3571 Get default Id value used for browser.
3573 @param DefaultId The default id value used by hii.
3575 @retval Browser used default value.
3579 GetDefaultIdForCallBack (
3583 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3584 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3585 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3586 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3587 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3588 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3589 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3590 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3591 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3592 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3593 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3594 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3603 Return data element in an Array by its Index.
3605 @param Array The data array.
3606 @param Type Type of the data in this array.
3607 @param Index Zero based index for data in this array.
3609 @retval Value The data to be returned
3621 ASSERT (Array
!= NULL
);
3625 case EFI_IFR_TYPE_NUM_SIZE_8
:
3626 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3629 case EFI_IFR_TYPE_NUM_SIZE_16
:
3630 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3633 case EFI_IFR_TYPE_NUM_SIZE_32
:
3634 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3637 case EFI_IFR_TYPE_NUM_SIZE_64
:
3638 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3650 Set value of a data element in an Array by its Index.
3652 @param Array The data array.
3653 @param Type Type of the data in this array.
3654 @param Index Zero based index for data in this array.
3655 @param Value The value to be set.
3667 ASSERT (Array
!= NULL
);
3670 case EFI_IFR_TYPE_NUM_SIZE_8
:
3671 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3674 case EFI_IFR_TYPE_NUM_SIZE_16
:
3675 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3678 case EFI_IFR_TYPE_NUM_SIZE_32
:
3679 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3682 case EFI_IFR_TYPE_NUM_SIZE_64
:
3683 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3692 Search an Option of a Question by its value.
3694 @param Question The Question
3695 @param OptionValue Value for Option to be searched.
3697 @retval Pointer Pointer to the found Option.
3698 @retval NULL Option not found.
3703 IN FORM_BROWSER_STATEMENT
*Question
,
3704 IN EFI_HII_VALUE
*OptionValue
3708 QUESTION_OPTION
*Option
;
3711 Link
= GetFirstNode (&Question
->OptionListHead
);
3712 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3713 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3715 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3717 // Check the suppressif condition, only a valid option can be return.
3719 if ((Option
->SuppressExpression
== NULL
) ||
3720 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3725 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3733 Reset Question to its default value.
3735 @param FormSet The form set.
3736 @param Form The form.
3737 @param Question The question.
3738 @param DefaultId The Class of the default.
3740 @retval EFI_SUCCESS Question is reset to default value.
3744 GetQuestionDefault (
3745 IN FORM_BROWSER_FORMSET
*FormSet
,
3746 IN FORM_BROWSER_FORM
*Form
,
3747 IN FORM_BROWSER_STATEMENT
*Question
,
3753 QUESTION_DEFAULT
*Default
;
3754 QUESTION_OPTION
*Option
;
3755 EFI_HII_VALUE
*HiiValue
;
3757 EFI_STRING StrValue
;
3758 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3759 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3763 Status
= EFI_NOT_FOUND
;
3767 // Statement don't have storage, skip them
3769 if (Question
->QuestionId
== 0) {
3774 // There are Five ways to specify default value for a Question:
3775 // 1, use call back function (highest priority)
3776 // 2, use ExtractConfig function
3777 // 3, use nested EFI_IFR_DEFAULT
3778 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3779 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3781 HiiValue
= &Question
->HiiValue
;
3784 // Get Question defaut value from call back function.
3786 ConfigAccess
= FormSet
->ConfigAccess
;
3787 Action
= GetDefaultIdForCallBack (DefaultId
);
3788 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3789 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3790 Status
= ConfigAccess
->Callback (
3793 Question
->QuestionId
,
3798 if (!EFI_ERROR (Status
)) {
3799 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3800 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3801 ASSERT (NewString
!= NULL
);
3803 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3804 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3805 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3807 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3810 FreePool (NewString
);
3817 // Get default value from altcfg string.
3819 if (ConfigAccess
!= NULL
) {
3820 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3821 if (!EFI_ERROR (Status
)) {
3827 // EFI_IFR_DEFAULT has highest priority
3829 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3830 Link
= GetFirstNode (&Question
->DefaultListHead
);
3831 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3832 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3834 if (Default
->DefaultId
== DefaultId
) {
3835 if (Default
->ValueExpression
!= NULL
) {
3837 // Default is provided by an Expression, evaluate it
3839 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3840 if (EFI_ERROR (Status
)) {
3844 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3845 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3846 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3847 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3848 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3850 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3851 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3853 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3855 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3856 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3859 // Default value is embedded in EFI_IFR_DEFAULT
3861 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3864 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3865 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3866 if (StrValue
== NULL
) {
3867 return EFI_NOT_FOUND
;
3869 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3870 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3872 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3879 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3884 // EFI_ONE_OF_OPTION
3886 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3887 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3889 // OneOfOption could only provide Standard and Manufacturing default
3891 Link
= GetFirstNode (&Question
->OptionListHead
);
3892 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3893 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3894 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3896 if ((Option
->SuppressExpression
!= NULL
) &&
3897 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3901 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3902 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3904 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3913 // EFI_IFR_CHECKBOX - lowest priority
3915 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3916 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3918 // Checkbox could only provide Standard and Manufacturing default
3920 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3921 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3923 HiiValue
->Value
.b
= TRUE
;
3925 HiiValue
->Value
.b
= FALSE
;
3933 // For Questions without default
3935 Status
= EFI_NOT_FOUND
;
3936 switch (Question
->Operand
) {
3937 case EFI_IFR_NUMERIC_OP
:
3939 // Take minimum value as numeric default value
3941 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3942 HiiValue
->Value
.u64
= Question
->Minimum
;
3943 Status
= EFI_SUCCESS
;
3947 case EFI_IFR_ONE_OF_OP
:
3949 // Take first oneof option as oneof's default value
3951 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3952 Link
= GetFirstNode (&Question
->OptionListHead
);
3953 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3954 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3955 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3957 if ((Option
->SuppressExpression
!= NULL
) &&
3958 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3962 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3963 Status
= EFI_SUCCESS
;
3969 case EFI_IFR_ORDERED_LIST_OP
:
3971 // Take option sequence in IFR as ordered list's default value
3974 Link
= GetFirstNode (&Question
->OptionListHead
);
3975 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3976 Status
= EFI_SUCCESS
;
3977 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3978 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3980 if ((Option
->SuppressExpression
!= NULL
) &&
3981 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3985 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3988 if (Index
>= Question
->MaxContainers
) {
4003 Reset Questions to their initial value or default value in a Form, Formset or System.
4005 GetDefaultValueScope parameter decides which questions will reset
4006 to its default value.
4008 @param FormSet FormSet data structure.
4009 @param Form Form data structure.
4010 @param DefaultId The Class of the default.
4011 @param SettingScope Setting Scope for Default action.
4012 @param GetDefaultValueScope Get default value scope.
4013 @param Storage Get default value only for this storage.
4014 @param RetrieveValueFirst Whether call the retrieve call back to
4015 get the initial value before get default
4018 @retval EFI_SUCCESS The function completed successfully.
4019 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4024 IN FORM_BROWSER_FORMSET
*FormSet
,
4025 IN FORM_BROWSER_FORM
*Form
,
4026 IN UINT16 DefaultId
,
4027 IN BROWSER_SETTING_SCOPE SettingScope
,
4028 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4029 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4030 IN BOOLEAN RetrieveValueFirst
4034 LIST_ENTRY
*FormLink
;
4036 FORM_BROWSER_STATEMENT
*Question
;
4037 FORM_BROWSER_FORMSET
*LocalFormSet
;
4038 FORM_BROWSER_FORMSET
*OldFormSet
;
4040 Status
= EFI_SUCCESS
;
4043 // Check the supported setting level.
4045 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4046 return EFI_UNSUPPORTED
;
4049 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4050 return EFI_UNSUPPORTED
;
4053 if (SettingScope
== FormLevel
) {
4055 // Extract Form default
4057 Link
= GetFirstNode (&Form
->StatementListHead
);
4058 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4059 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4060 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4063 // If get default value only for this storage, check the storage first.
4065 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4070 // If get default value only for no storage question, just skip the question which has storage.
4072 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4077 // If Question is disabled, don't reset it to default
4079 if (Question
->Expression
!= NULL
) {
4080 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4085 if (RetrieveValueFirst
) {
4087 // Call the Retrieve call back to get the initial question value.
4089 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4093 // If not request to get the initial value or get initial value fail, then get default value.
4095 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4096 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4097 if (EFI_ERROR (Status
)) {
4103 // Synchronize Buffer storage's Edit buffer
4105 if ((Question
->Storage
!= NULL
) &&
4106 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4107 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4110 } else if (SettingScope
== FormSetLevel
) {
4111 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4112 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4113 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4114 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4115 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4117 } else if (SettingScope
== SystemLevel
) {
4119 // Preload all Hii formset.
4121 LoadAllHiiFormset();
4123 OldFormSet
= mSystemLevelFormSet
;
4126 // Set Default Value for each FormSet in the maintain list.
4128 Link
= GetFirstNode (&gBrowserFormSetList
);
4129 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4130 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4131 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4132 if (!ValidateFormSet(LocalFormSet
)) {
4136 mSystemLevelFormSet
= LocalFormSet
;
4138 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4141 mSystemLevelFormSet
= OldFormSet
;
4149 Validate whether this question's value has changed.
4151 @param FormSet FormSet data structure.
4152 @param Form Form data structure.
4153 @param Question Question to be initialized.
4154 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4156 @retval TRUE Question's value has changed.
4157 @retval FALSE Question's value has not changed
4161 IsQuestionValueChanged (
4162 IN FORM_BROWSER_FORMSET
*FormSet
,
4163 IN FORM_BROWSER_FORM
*Form
,
4164 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4165 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4168 EFI_HII_VALUE BackUpValue
;
4169 CHAR8
*BackUpBuffer
;
4170 EFI_HII_VALUE BackUpValue2
;
4171 CHAR8
*BackUpBuffer2
;
4173 BOOLEAN ValueChanged
;
4177 // For quetion without storage, always mark it as data not changed.
4179 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4183 BackUpBuffer
= NULL
;
4184 BackUpBuffer2
= NULL
;
4185 ValueChanged
= FALSE
;
4187 switch (Question
->Operand
) {
4188 case EFI_IFR_ORDERED_LIST_OP
:
4189 BufferWidth
= Question
->StorageWidth
;
4190 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4191 ASSERT (BackUpBuffer
!= NULL
);
4194 case EFI_IFR_STRING_OP
:
4195 case EFI_IFR_PASSWORD_OP
:
4196 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4197 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4198 ASSERT (BackUpBuffer
!= NULL
);
4205 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4207 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4208 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4209 ASSERT_EFI_ERROR(Status
);
4211 switch (Question
->Operand
) {
4212 case EFI_IFR_ORDERED_LIST_OP
:
4213 BufferWidth
= Question
->StorageWidth
;
4214 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4215 ASSERT (BackUpBuffer2
!= NULL
);
4218 case EFI_IFR_STRING_OP
:
4219 case EFI_IFR_PASSWORD_OP
:
4220 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4221 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4222 ASSERT (BackUpBuffer2
!= NULL
);
4229 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4231 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4232 ASSERT_EFI_ERROR(Status
);
4234 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4235 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4236 ValueChanged
= TRUE
;
4239 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4240 ASSERT_EFI_ERROR(Status
);
4242 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4243 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4244 ValueChanged
= TRUE
;
4248 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4249 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4251 if (BackUpBuffer
!= NULL
) {
4252 FreePool (BackUpBuffer
);
4255 if (BackUpBuffer2
!= NULL
) {
4256 FreePool (BackUpBuffer2
);
4259 Question
->ValueChanged
= ValueChanged
;
4261 return ValueChanged
;
4265 Initialize Question's Edit copy from Storage.
4267 @param Selection Selection contains the information about
4268 the Selection, form and formset to be displayed.
4269 Selection action may be updated in retrieve callback.
4270 If Selection is NULL, only initialize Question value.
4271 @param FormSet FormSet data structure.
4272 @param Form Form data structure.
4274 @retval EFI_SUCCESS The function completed successfully.
4279 IN OUT UI_MENU_SELECTION
*Selection
,
4280 IN FORM_BROWSER_FORMSET
*FormSet
,
4281 IN FORM_BROWSER_FORM
*Form
4286 FORM_BROWSER_STATEMENT
*Question
;
4288 Link
= GetFirstNode (&Form
->StatementListHead
);
4289 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4290 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4293 // Initialize local copy of Value for each Question
4295 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4296 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4298 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4300 if (EFI_ERROR (Status
)) {
4304 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4305 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4308 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4315 Initialize Question's Edit copy from Storage for the whole Formset.
4317 @param Selection Selection contains the information about
4318 the Selection, form and formset to be displayed.
4319 Selection action may be updated in retrieve callback.
4320 If Selection is NULL, only initialize Question value.
4321 @param FormSet FormSet data structure.
4323 @retval EFI_SUCCESS The function completed successfully.
4328 IN OUT UI_MENU_SELECTION
*Selection
,
4329 IN FORM_BROWSER_FORMSET
*FormSet
4334 FORM_BROWSER_FORM
*Form
;
4336 Link
= GetFirstNode (&FormSet
->FormListHead
);
4337 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4338 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4341 // Initialize local copy of Value for each Form
4343 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4344 if (EFI_ERROR (Status
)) {
4348 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4352 // Finished question initialization.
4354 FormSet
->QuestionInited
= TRUE
;
4360 Remove the Request element from the Config Request.
4362 @param Storage Pointer to the browser storage.
4363 @param RequestElement The pointer to the Request element.
4368 IN OUT BROWSER_STORAGE
*Storage
,
4369 IN CHAR16
*RequestElement
4375 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4377 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4379 if (NewStr
== NULL
) {
4384 // Remove this element from this ConfigRequest.
4387 NewStr
+= StrLen (RequestElement
);
4388 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4390 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4394 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4396 @param Storage Pointer to the browser storage.
4397 @param ConfigRequest The pointer to the Request element.
4401 RemoveConfigRequest (
4402 BROWSER_STORAGE
*Storage
,
4403 CHAR16
*ConfigRequest
4406 CHAR16
*RequestElement
;
4407 CHAR16
*NextRequestElement
;
4411 // No request element in it, just return.
4413 if (ConfigRequest
== NULL
) {
4417 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4419 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4424 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4426 SearchKey
= L
"&OFFSET";
4430 // Find SearchKey storage
4432 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4433 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4434 ASSERT (RequestElement
!= NULL
);
4435 RequestElement
= StrStr (RequestElement
, SearchKey
);
4437 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4440 while (RequestElement
!= NULL
) {
4442 // +1 to avoid find header itself.
4444 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4447 // The last Request element in configRequest string.
4449 if (NextRequestElement
!= NULL
) {
4451 // Replace "&" with '\0'.
4453 *NextRequestElement
= L
'\0';
4456 RemoveElement (Storage
, RequestElement
);
4458 if (NextRequestElement
!= NULL
) {
4460 // Restore '&' with '\0' for later used.
4462 *NextRequestElement
= L
'&';
4465 RequestElement
= NextRequestElement
;
4469 // If no request element remain, just remove the ConfigRequest string.
4471 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4472 FreePool (Storage
->ConfigRequest
);
4473 Storage
->ConfigRequest
= NULL
;
4474 Storage
->SpareStrLen
= 0;
4479 Base on the current formset info, clean the ConfigRequest string in browser storage.
4481 @param FormSet Pointer of the FormSet
4485 CleanBrowserStorage (
4486 IN OUT FORM_BROWSER_FORMSET
*FormSet
4490 FORMSET_STORAGE
*Storage
;
4492 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4493 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4494 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4495 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4497 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4498 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4502 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4503 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4504 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4505 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4506 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4507 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4509 Storage
->BrowserStorage
->Initialized
= FALSE
;
4515 Check whether current element in the ConfigReqeust string.
4517 @param BrowserStorage Storage which includes ConfigReqeust.
4518 @param RequestElement New element need to check.
4520 @retval TRUE The Element is in the ConfigReqeust string.
4521 @retval FALSE The Element not in the configReqeust String.
4526 BROWSER_STORAGE
*BrowserStorage
,
4527 CHAR16
*RequestElement
4530 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4534 Append the Request element to the Config Request.
4536 @param ConfigRequest Current ConfigRequest info.
4537 @param SpareStrLen Current remain free buffer for config reqeust.
4538 @param RequestElement New Request element.
4542 AppendConfigRequest (
4543 IN OUT CHAR16
**ConfigRequest
,
4544 IN OUT UINTN
*SpareStrLen
,
4545 IN CHAR16
*RequestElement
4552 StrLength
= StrLen (RequestElement
);
4555 // Append <RequestElement> to <ConfigRequest>
4557 if (StrLength
> *SpareStrLen
) {
4559 // Old String buffer is not sufficient for RequestElement, allocate a new one
4561 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4562 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4563 ASSERT (NewStr
!= NULL
);
4565 if (*ConfigRequest
!= NULL
) {
4566 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4567 FreePool (*ConfigRequest
);
4569 *ConfigRequest
= NewStr
;
4570 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4573 StrCat (*ConfigRequest
, RequestElement
);
4574 *SpareStrLen
-= StrLength
;
4578 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4580 @param Storage Form set Storage.
4581 @param Request The input request string.
4582 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4584 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4585 @retval FALSE All elements covered by current used elements.
4589 ConfigRequestAdjust (
4590 IN BROWSER_STORAGE
*Storage
,
4592 IN BOOLEAN RespString
4595 CHAR16
*RequestElement
;
4596 CHAR16
*NextRequestElement
;
4597 CHAR16
*NextElementBakup
;
4602 CHAR16
*ConfigRequest
;
4606 NextElementBakup
= NULL
;
4609 if (Request
!= NULL
) {
4610 ConfigRequest
= Request
;
4612 ConfigRequest
= Storage
->ConfigRequest
;
4615 if (Storage
->ConfigRequest
== NULL
) {
4616 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4620 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4622 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4627 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4629 SearchKey
= L
"&OFFSET";
4630 ValueKey
= L
"&VALUE";
4634 // Find SearchKey storage
4636 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4637 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4638 ASSERT (RequestElement
!= NULL
);
4639 RequestElement
= StrStr (RequestElement
, SearchKey
);
4641 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4644 while (RequestElement
!= NULL
) {
4647 // +1 to avoid find header itself.
4649 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4652 // The last Request element in configRequest string.
4654 if (NextRequestElement
!= NULL
) {
4655 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4656 NextElementBakup
= NextRequestElement
;
4657 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4658 ASSERT (NextRequestElement
!= NULL
);
4661 // Replace "&" with '\0'.
4663 *NextRequestElement
= L
'\0';
4665 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4666 NextElementBakup
= NextRequestElement
;
4667 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4668 ASSERT (NextRequestElement
!= NULL
);
4670 // Replace "&" with '\0'.
4672 *NextRequestElement
= L
'\0';
4676 if (!ElementValidation (Storage
, RequestElement
)) {
4678 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4680 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4684 if (NextRequestElement
!= NULL
) {
4686 // Restore '&' with '\0' for later used.
4688 *NextRequestElement
= L
'&';
4691 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4692 RequestElement
= NextElementBakup
;
4694 RequestElement
= NextRequestElement
;
4703 Base on ConfigRequest info to get default value for current formset.
4705 ConfigRequest info include the info about which questions in current formset need to
4706 get default value. This function only get these questions default value.
4708 @param FormSet FormSet data structure.
4709 @param Storage Storage need to update value.
4710 @param ConfigRequest The config request string.
4714 GetDefaultForFormset (
4715 IN FORM_BROWSER_FORMSET
*FormSet
,
4716 IN BROWSER_STORAGE
*Storage
,
4717 IN CHAR16
*ConfigRequest
4722 LIST_ENTRY BackUpList
;
4723 NAME_VALUE_NODE
*Node
;
4725 LIST_ENTRY
*NodeLink
;
4726 NAME_VALUE_NODE
*TmpNode
;
4728 EFI_STRING Progress
;
4732 InitializeListHead(&BackUpList
);
4735 // Back update the edit buffer.
4737 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4738 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4739 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4740 ASSERT (BackUpBuf
!= NULL
);
4741 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4742 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4743 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4744 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4745 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4748 // Only back Node belong to this formset.
4750 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4754 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4755 ASSERT (TmpNode
!= NULL
);
4756 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4757 ASSERT (TmpNode
->Name
!= NULL
);
4758 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4759 ASSERT (TmpNode
->EditValue
!= NULL
);
4761 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4766 // Get default value.
4768 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4771 // Update the question value based on the input ConfigRequest.
4773 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4774 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4775 ASSERT (BackUpBuf
!= NULL
);
4776 BufferSize
= Storage
->Size
;
4777 Status
= mHiiConfigRouting
->BlockToConfig(
4780 Storage
->EditBuffer
,
4785 ASSERT_EFI_ERROR (Status
);
4787 Status
= mHiiConfigRouting
->ConfigToBlock (
4794 ASSERT_EFI_ERROR (Status
);
4796 if (Result
!= NULL
) {
4800 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4801 FreePool (BackUpBuf
);
4802 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4804 // Update question value, only element in ConfigReqeust will be update.
4806 Link
= GetFirstNode (&BackUpList
);
4807 while (!IsNull (&BackUpList
, Link
)) {
4808 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4809 Link
= GetNextNode (&BackUpList
, Link
);
4811 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4815 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4816 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4817 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4818 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4820 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4824 FreePool (TmpNode
->EditValue
);
4825 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4827 RemoveEntryList (&Node
->Link
);
4828 FreePool (Node
->EditValue
);
4829 FreePool (Node
->Name
);
4835 // Restore the Name/Value node.
4837 Link
= GetFirstNode (&BackUpList
);
4838 while (!IsNull (&BackUpList
, Link
)) {
4839 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4840 Link
= GetNextNode (&BackUpList
, Link
);
4845 RemoveEntryList (&Node
->Link
);
4846 FreePool (Node
->EditValue
);
4847 FreePool (Node
->Name
);
4854 Fill storage's edit copy with settings requested from Configuration Driver.
4856 @param FormSet FormSet data structure.
4857 @param Storage Buffer Storage.
4862 IN FORM_BROWSER_FORMSET
*FormSet
,
4863 IN FORMSET_STORAGE
*Storage
4867 EFI_STRING Progress
;
4870 EFI_STRING ConfigRequest
;
4873 ConfigRequest
= NULL
;
4875 switch (Storage
->BrowserStorage
->Type
) {
4876 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4879 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4880 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4881 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4886 case EFI_HII_VARSTORE_BUFFER
:
4887 case EFI_HII_VARSTORE_NAME_VALUE
:
4889 // Skip if there is no RequestElement.
4891 if (Storage
->ElementCount
== 0) {
4896 // Just update the ConfigRequest, if storage already initialized.
4898 if (Storage
->BrowserStorage
->Initialized
) {
4899 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4903 Storage
->BrowserStorage
->Initialized
= TRUE
;
4910 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4912 // Create the config request string to get all fields for this storage.
4913 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4914 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4916 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4917 ConfigRequest
= AllocateZeroPool (StrLen
);
4918 ASSERT (ConfigRequest
!= NULL
);
4922 L
"%s&OFFSET=0&WIDTH=%04x",
4923 Storage
->BrowserStorage
->ConfigHdr
,
4924 Storage
->BrowserStorage
->Size
);
4926 ConfigRequest
= Storage
->ConfigRequest
;
4930 // Request current settings from Configuration Driver
4932 Status
= mHiiConfigRouting
->ExtractConfig (
4940 // If get value fail, extract default from IFR binary
4942 if (EFI_ERROR (Status
)) {
4943 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4946 // Convert Result from <ConfigAltResp> to <ConfigResp>
4948 StrPtr
= StrStr (Result
, L
"&GUID=");
4949 if (StrPtr
!= NULL
) {
4953 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4957 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4960 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4962 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
4964 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4965 if (ConfigRequest
!= NULL
) {
4966 FreePool (ConfigRequest
);
4972 Get Value changed status from old question.
4974 @param NewFormSet FormSet data structure.
4975 @param OldQuestion Old question which has value changed.
4979 SyncStatusForQuestion (
4980 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4981 IN FORM_BROWSER_STATEMENT
*OldQuestion
4985 LIST_ENTRY
*QuestionLink
;
4986 FORM_BROWSER_FORM
*Form
;
4987 FORM_BROWSER_STATEMENT
*Question
;
4990 // For each form in one formset.
4992 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4993 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4994 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4995 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4998 // for each question in one form.
5000 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5001 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5002 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5003 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5005 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5006 Question
->ValueChanged
= TRUE
;
5014 Get Value changed status from old formset.
5016 @param NewFormSet FormSet data structure.
5017 @param OldFormSet FormSet data structure.
5021 SyncStatusForFormSet (
5022 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5023 IN FORM_BROWSER_FORMSET
*OldFormSet
5027 LIST_ENTRY
*QuestionLink
;
5028 FORM_BROWSER_FORM
*Form
;
5029 FORM_BROWSER_STATEMENT
*Question
;
5032 // For each form in one formset.
5034 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5035 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5036 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5037 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5040 // for each question in one form.
5042 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5043 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5044 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5045 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5047 if (!Question
->ValueChanged
) {
5052 // Find the same question in new formset and update the value changed flag.
5054 SyncStatusForQuestion (NewFormSet
, Question
);
5060 Get current setting of Questions.
5062 @param FormSet FormSet data structure.
5066 InitializeCurrentSetting (
5067 IN OUT FORM_BROWSER_FORMSET
*FormSet
5071 FORMSET_STORAGE
*Storage
;
5072 FORM_BROWSER_FORMSET
*OldFormSet
;
5075 // Try to find pre FormSet in the maintain backup list.
5076 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5078 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5079 if (OldFormSet
!= NULL
) {
5080 SyncStatusForFormSet (FormSet
, OldFormSet
);
5081 RemoveEntryList (&OldFormSet
->Link
);
5082 DestroyFormSet (OldFormSet
);
5084 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5087 // Extract default from IFR binary for no storage questions.
5089 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
5092 // Request current settings from Configuration Driver
5094 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5095 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5096 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5098 LoadStorage (FormSet
, Storage
);
5100 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5106 Fetch the Ifr binary data of a FormSet.
5108 @param Handle PackageList Handle
5109 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5110 specified (NULL or zero GUID), take the first
5111 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5112 found in package list.
5113 On output, GUID of the formset found(if not NULL).
5114 @param BinaryLength The length of the FormSet IFR binary.
5115 @param BinaryData The buffer designed to receive the FormSet.
5117 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5118 BufferLength was updated.
5119 @retval EFI_INVALID_PARAMETER The handle is unknown.
5120 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5121 be found with the requested FormId.
5126 IN EFI_HII_HANDLE Handle
,
5127 IN OUT EFI_GUID
*FormSetGuid
,
5128 OUT UINTN
*BinaryLength
,
5129 OUT UINT8
**BinaryData
5133 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5139 UINT32 PackageListLength
;
5140 EFI_HII_PACKAGE_HEADER PackageHeader
;
5142 UINT8 NumberOfClassGuid
;
5143 BOOLEAN ClassGuidMatch
;
5144 EFI_GUID
*ClassGuid
;
5145 EFI_GUID
*ComparingGuid
;
5149 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5152 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5154 if (FormSetGuid
== NULL
) {
5155 ComparingGuid
= &gZeroGuid
;
5157 ComparingGuid
= FormSetGuid
;
5161 // Get HII PackageList
5164 HiiPackageList
= NULL
;
5165 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5166 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5167 HiiPackageList
= AllocatePool (BufferSize
);
5168 ASSERT (HiiPackageList
!= NULL
);
5170 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5172 if (EFI_ERROR (Status
)) {
5175 ASSERT (HiiPackageList
!= NULL
);
5178 // Get Form package from this HII package List
5180 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5182 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5184 ClassGuidMatch
= FALSE
;
5185 while (Offset
< PackageListLength
) {
5186 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5187 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5189 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5191 // Search FormSet in this Form Package
5193 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5194 while (Offset2
< PackageHeader
.Length
) {
5195 OpCodeData
= Package
+ Offset2
;
5197 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5199 // Try to compare against formset GUID
5201 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5202 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5206 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5208 // Try to compare against formset class GUID
5210 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5211 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5212 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5213 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5214 ClassGuidMatch
= TRUE
;
5218 if (ClassGuidMatch
) {
5221 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5222 ClassGuidMatch
= TRUE
;
5227 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5230 if (Offset2
< PackageHeader
.Length
) {
5232 // Target formset found
5238 Offset
+= PackageHeader
.Length
;
5241 if (Offset
>= PackageListLength
) {
5243 // Form package not found in this Package List
5245 FreePool (HiiPackageList
);
5246 return EFI_NOT_FOUND
;
5249 if (FormSetGuid
!= NULL
) {
5251 // Return the FormSet GUID
5253 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5257 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5258 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5259 // of the Form Package.
5261 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5262 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5264 FreePool (HiiPackageList
);
5266 if (*BinaryData
== NULL
) {
5267 return EFI_OUT_OF_RESOURCES
;
5275 Initialize the internal data structure of a FormSet.
5277 @param Handle PackageList Handle
5278 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5279 specified (NULL or zero GUID), take the first
5280 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5281 found in package list.
5282 On output, GUID of the formset found(if not NULL).
5283 @param FormSet FormSet data structure.
5285 @retval EFI_SUCCESS The function completed successfully.
5286 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5291 IN EFI_HII_HANDLE Handle
,
5292 IN OUT EFI_GUID
*FormSetGuid
,
5293 OUT FORM_BROWSER_FORMSET
*FormSet
5297 EFI_HANDLE DriverHandle
;
5299 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5300 if (EFI_ERROR (Status
)) {
5304 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5305 FormSet
->HiiHandle
= Handle
;
5306 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5307 FormSet
->QuestionInited
= FALSE
;
5310 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5312 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5313 if (EFI_ERROR (Status
)) {
5316 FormSet
->DriverHandle
= DriverHandle
;
5317 Status
= gBS
->HandleProtocol (
5319 &gEfiHiiConfigAccessProtocolGuid
,
5320 (VOID
**) &FormSet
->ConfigAccess
5322 if (EFI_ERROR (Status
)) {
5324 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5325 // list, then there will be no configuration action required
5327 FormSet
->ConfigAccess
= NULL
;
5331 // Parse the IFR binary OpCodes
5333 Status
= ParseOpCodes (FormSet
);
5340 Save globals used by previous call to SendForm(). SendForm() may be called from
5341 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5342 So, save globals of previous call to SendForm() and restore them upon exit.
5346 SaveBrowserContext (
5350 BROWSER_CONTEXT
*Context
;
5351 FORM_ENTRY_INFO
*MenuList
;
5353 gBrowserContextCount
++;
5354 if (gBrowserContextCount
== 1) {
5356 // This is not reentry of SendForm(), no context to save
5361 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5362 ASSERT (Context
!= NULL
);
5364 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5367 // Save FormBrowser context
5369 Context
->Selection
= gCurrentSelection
;
5370 Context
->ResetRequired
= gResetRequired
;
5371 Context
->ExitRequired
= gExitRequired
;
5372 Context
->HiiHandle
= mCurrentHiiHandle
;
5373 Context
->FormId
= mCurrentFormId
;
5374 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5377 // Save the menu history data.
5379 InitializeListHead(&Context
->FormHistoryList
);
5380 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5381 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5382 RemoveEntryList (&MenuList
->Link
);
5384 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5388 // Insert to FormBrowser context list
5390 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5395 Restore globals used by previous call to SendForm().
5399 RestoreBrowserContext (
5404 BROWSER_CONTEXT
*Context
;
5405 FORM_ENTRY_INFO
*MenuList
;
5407 ASSERT (gBrowserContextCount
!= 0);
5408 gBrowserContextCount
--;
5409 if (gBrowserContextCount
== 0) {
5411 // This is not reentry of SendForm(), no context to restore
5416 ASSERT (!IsListEmpty (&gBrowserContextList
));
5418 Link
= GetFirstNode (&gBrowserContextList
);
5419 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5422 // Restore FormBrowser context
5424 gCurrentSelection
= Context
->Selection
;
5425 gResetRequired
= Context
->ResetRequired
;
5426 gExitRequired
= Context
->ExitRequired
;
5427 mCurrentHiiHandle
= Context
->HiiHandle
;
5428 mCurrentFormId
= Context
->FormId
;
5429 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5432 // Restore the menu history data.
5434 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5435 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5436 RemoveEntryList (&MenuList
->Link
);
5438 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5442 // Remove from FormBrowser context list
5444 RemoveEntryList (&Context
->Link
);
5445 gBS
->FreePool (Context
);
5449 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5451 @param Handle The Hii Handle.
5453 @return the found FormSet context. If no found, NULL will return.
5456 FORM_BROWSER_FORMSET
*
5457 GetFormSetFromHiiHandle (
5458 EFI_HII_HANDLE Handle
5462 FORM_BROWSER_FORMSET
*FormSet
;
5464 Link
= GetFirstNode (&gBrowserFormSetList
);
5465 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5466 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5467 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5468 if (!ValidateFormSet(FormSet
)) {
5471 if (FormSet
->HiiHandle
== Handle
) {
5480 Check whether the input HII handle is the FormSet that is being used.
5482 @param Handle The Hii Handle.
5484 @retval TRUE HII handle is being used.
5485 @retval FALSE HII handle is not being used.
5489 IsHiiHandleInBrowserContext (
5490 EFI_HII_HANDLE Handle
5494 BROWSER_CONTEXT
*Context
;
5497 // HiiHandle is Current FormSet.
5499 if (mCurrentHiiHandle
== Handle
) {
5504 // Check whether HiiHandle is in BrowserContext.
5506 Link
= GetFirstNode (&gBrowserContextList
);
5507 while (!IsNull (&gBrowserContextList
, Link
)) {
5508 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5509 if (Context
->HiiHandle
== Handle
) {
5511 // HiiHandle is in BrowserContext
5515 Link
= GetNextNode (&gBrowserContextList
, Link
);
5522 Perform Password check.
5523 Passwork may be encrypted by driver that requires the specific check.
5525 @param Form Form where Password Statement is in.
5526 @param Statement Password statement
5527 @param PasswordString Password string to be checked. It may be NULL.
5528 NULL means to restore password.
5529 "" string can be used to checked whether old password does exist.
5531 @return Status Status of Password check.
5536 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5537 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5538 IN EFI_STRING PasswordString OPTIONAL
5542 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5543 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5544 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5545 FORM_BROWSER_STATEMENT
*Question
;
5547 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5548 Question
= GetBrowserStatement(Statement
);
5549 ASSERT (Question
!= NULL
);
5551 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5552 if (ConfigAccess
== NULL
) {
5553 return EFI_UNSUPPORTED
;
5556 if (PasswordString
== NULL
) {
5561 // Check whether has preexisted password.
5563 if (PasswordString
[0] == 0) {
5564 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5567 return EFI_NOT_READY
;
5572 // Check whether the input password is same as preexisted password.
5574 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5577 return EFI_NOT_READY
;
5582 // Prepare password string in HII database
5584 if (PasswordString
!= NULL
) {
5585 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5587 IfrTypeValue
.string
= 0;
5591 // Send password to Configuration Driver for validation
5593 Status
= ConfigAccess
->Callback (
5595 EFI_BROWSER_ACTION_CHANGING
,
5596 Question
->QuestionId
,
5597 Question
->HiiValue
.Type
,
5603 // Remove password string from HII database
5605 if (PasswordString
!= NULL
) {
5606 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5613 Find the registered HotKey based on KeyData.
5615 @param[in] KeyData A pointer to a buffer that describes the keystroke
5616 information for the hot key.
5618 @return The registered HotKey context. If no found, NULL will return.
5621 GetHotKeyFromRegisterList (
5622 IN EFI_INPUT_KEY
*KeyData
5626 BROWSER_HOT_KEY
*HotKey
;
5628 Link
= GetFirstNode (&gBrowserHotKeyList
);
5629 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5630 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5631 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5634 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5641 Configure what scope the hot key will impact.
5642 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5643 If no scope is set, the default scope will be FormSet level.
5644 After all registered hot keys are removed, previous Scope can reset to another level.
5646 @param[in] Scope Scope level to be set.
5648 @retval EFI_SUCCESS Scope is set correctly.
5649 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5650 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5656 IN BROWSER_SETTING_SCOPE Scope
5659 if (Scope
>= MaxLevel
) {
5660 return EFI_INVALID_PARAMETER
;
5664 // When no hot key registered in system or on the first setting,
5665 // Scope can be set.
5667 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5668 gBrowserSettingScope
= Scope
;
5669 mBrowserScopeFirstSet
= FALSE
;
5670 } else if (Scope
!= gBrowserSettingScope
) {
5671 return EFI_UNSUPPORTED
;
5678 Register the hot key with its browser action, or unregistered the hot key.
5679 Only support hot key that is not printable character (control key, function key, etc.).
5680 If the action value is zero, the hot key will be unregistered if it has been registered.
5681 If the same hot key has been registered, the new action and help string will override the previous ones.
5683 @param[in] KeyData A pointer to a buffer that describes the keystroke
5684 information for the hot key. Its type is EFI_INPUT_KEY to
5685 be supported by all ConsoleIn devices.
5686 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5687 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5688 @param[in] HelpString Help string that describes the hot key information.
5689 Its value may be NULL for the unregistered hot key.
5691 @retval EFI_SUCCESS Hot key is registered or unregistered.
5692 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5693 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5694 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5699 IN EFI_INPUT_KEY
*KeyData
,
5701 IN UINT16 DefaultId
,
5702 IN EFI_STRING HelpString OPTIONAL
5705 BROWSER_HOT_KEY
*HotKey
;
5708 // Check input parameters.
5710 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5711 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5712 return EFI_INVALID_PARAMETER
;
5716 // Check whether the input KeyData is in BrowserHotKeyList.
5718 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5721 // Unregister HotKey
5723 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5724 if (HotKey
!= NULL
) {
5726 // The registered HotKey is found.
5727 // Remove it from List, and free its resource.
5729 RemoveEntryList (&HotKey
->Link
);
5730 FreePool (HotKey
->KeyData
);
5731 FreePool (HotKey
->HelpString
);
5735 // The registered HotKey is not found.
5737 return EFI_NOT_FOUND
;
5742 // Register HotKey into List.
5744 if (HotKey
== NULL
) {
5746 // Create new Key, and add it into List.
5748 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5749 ASSERT (HotKey
!= NULL
);
5750 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5751 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5752 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5756 // Fill HotKey information.
5758 HotKey
->Action
= Action
;
5759 HotKey
->DefaultId
= DefaultId
;
5760 if (HotKey
->HelpString
!= NULL
) {
5761 FreePool (HotKey
->HelpString
);
5763 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5769 Register Exit handler function.
5770 When more than one handler function is registered, the latter one will override the previous one.
5771 When NULL handler is specified, the previous Exit handler will be unregistered.
5773 @param[in] Handler Pointer to handler function.
5778 RegiserExitHandler (
5779 IN EXIT_HANDLER Handler
5782 ExitHandlerFunction
= Handler
;
5787 Check whether the browser data has been modified.
5789 @retval TRUE Browser data is modified.
5790 @retval FALSE No browser data is modified.
5795 IsBrowserDataModified (
5800 FORM_BROWSER_FORMSET
*FormSet
;
5802 switch (gBrowserSettingScope
) {
5804 if (gCurrentSelection
== NULL
) {
5807 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5810 if (gCurrentSelection
== NULL
) {
5813 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5816 Link
= GetFirstNode (&gBrowserFormSetList
);
5817 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5818 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5819 if (!ValidateFormSet(FormSet
)) {
5823 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5826 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5836 Execute the action requested by the Action parameter.
5838 @param[in] Action Execute the request action.
5839 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5841 @retval EFI_SUCCESS Execute the request action succss.
5842 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5853 FORM_BROWSER_FORMSET
*FormSet
;
5854 FORM_BROWSER_FORM
*Form
;
5856 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5857 return EFI_NOT_READY
;
5860 Status
= EFI_SUCCESS
;
5863 if (gBrowserSettingScope
< SystemLevel
) {
5864 FormSet
= gCurrentSelection
->FormSet
;
5865 Form
= gCurrentSelection
->Form
;
5869 // Executet the discard action.
5871 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5872 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5873 if (EFI_ERROR (Status
)) {
5879 // Executet the difault action.
5881 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5882 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5883 if (EFI_ERROR (Status
)) {
5886 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5890 // Executet the submit action.
5892 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5893 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5894 if (EFI_ERROR (Status
)) {
5900 // Executet the reset action.
5902 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5903 gResetRequired
= TRUE
;
5907 // Executet the exit action.
5909 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5910 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5911 if (gBrowserSettingScope
== SystemLevel
) {
5912 if (ExitHandlerFunction
!= NULL
) {
5913 ExitHandlerFunction ();
5917 gExitRequired
= TRUE
;
5924 Create reminder to let user to choose save or discard the changed browser data.
5925 Caller can use it to actively check the changed browser data.
5927 @retval BROWSER_NO_CHANGES No browser data is changed.
5928 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5929 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5930 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5940 FORM_BROWSER_FORMSET
*FormSet
;
5941 BOOLEAN IsDataChanged
;
5942 UINT32 DataSavedAction
;
5945 DataSavedAction
= BROWSER_NO_CHANGES
;
5946 IsDataChanged
= FALSE
;
5947 Link
= GetFirstNode (&gBrowserFormSetList
);
5948 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5949 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5950 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5951 if (!ValidateFormSet(FormSet
)) {
5954 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5955 IsDataChanged
= TRUE
;
5961 // No data is changed. No save is required.
5963 if (!IsDataChanged
) {
5964 return DataSavedAction
;
5968 // If data is changed, prompt user to save or discard it.
5971 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5973 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5974 SubmitForm (NULL
, NULL
, SystemLevel
);
5975 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5977 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5978 DiscardForm (NULL
, NULL
, SystemLevel
);
5979 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5981 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5982 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5987 return DataSavedAction
;
5991 Check whether the Reset Required for the browser
5993 @retval TRUE Browser required to reset after exit.
5994 @retval FALSE Browser not need to reset after exit.
6003 return gResetRequired
;