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 (
839 if (mFormDisplay
!= NULL
) {
843 gBS
->LocateProtocol (
844 &gEdkiiFormDisplayEngineProtocolGuid
,
846 (VOID
**) &mFormDisplay
851 Initialize Setup Browser driver.
853 @param ImageHandle The image handle.
854 @param SystemTable The system table.
856 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
857 @return Other value if failed to initialize the Setup Browser module.
863 IN EFI_HANDLE ImageHandle
,
864 IN EFI_SYSTEM_TABLE
*SystemTable
871 // Locate required Hii relative protocols
873 Status
= gBS
->LocateProtocol (
874 &gEfiHiiDatabaseProtocolGuid
,
876 (VOID
**) &mHiiDatabase
878 ASSERT_EFI_ERROR (Status
);
880 Status
= gBS
->LocateProtocol (
881 &gEfiHiiConfigRoutingProtocolGuid
,
883 (VOID
**) &mHiiConfigRouting
885 ASSERT_EFI_ERROR (Status
);
887 Status
= gBS
->LocateProtocol (
888 &gEfiDevicePathFromTextProtocolGuid
,
890 (VOID
**) &mPathFromText
894 // Install FormBrowser2 protocol
896 mPrivateData
.Handle
= NULL
;
897 Status
= gBS
->InstallProtocolInterface (
898 &mPrivateData
.Handle
,
899 &gEfiFormBrowser2ProtocolGuid
,
900 EFI_NATIVE_INTERFACE
,
901 &mPrivateData
.FormBrowser2
903 ASSERT_EFI_ERROR (Status
);
906 // Install FormBrowserEx2 protocol
908 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
909 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
910 mPrivateData
.Handle
= NULL
;
911 Status
= gBS
->InstallProtocolInterface (
912 &mPrivateData
.Handle
,
913 &gEdkiiFormBrowserEx2ProtocolGuid
,
914 EFI_NATIVE_INTERFACE
,
915 &mPrivateData
.FormBrowserEx2
917 ASSERT_EFI_ERROR (Status
);
919 Status
= gBS
->InstallProtocolInterface (
920 &mPrivateData
.Handle
,
921 &gEfiFormBrowserExProtocolGuid
,
922 EFI_NATIVE_INTERFACE
,
923 &mPrivateData
.FormBrowserEx
925 ASSERT_EFI_ERROR (Status
);
927 InitializeDisplayFormData ();
929 Status
= gBS
->LocateProtocol (
930 &gEdkiiFormDisplayEngineProtocolGuid
,
932 (VOID
**) &mFormDisplay
935 if (EFI_ERROR (Status
)) {
936 EfiCreateProtocolNotifyEvent (
937 &gEdkiiFormDisplayEngineProtocolGuid
,
950 Create a new string in HII Package List.
952 @param String The String to be added
953 @param HiiHandle The package list in the HII database to insert the
956 @return The output string.
962 IN EFI_HII_HANDLE HiiHandle
965 EFI_STRING_ID StringId
;
967 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
968 ASSERT (StringId
!= 0);
975 Delete a string from HII Package List.
977 @param StringId Id of the string in HII database.
978 @param HiiHandle The HII package list handle.
980 @retval EFI_SUCCESS The string was deleted successfully.
985 IN EFI_STRING_ID StringId
,
986 IN EFI_HII_HANDLE HiiHandle
991 NullChar
= CHAR_NULL
;
992 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
998 Get the string based on the StringId and HII Package List Handle.
1000 @param Token The String's ID.
1001 @param HiiHandle The package list in the HII database to search for
1002 the specified string.
1004 @return The output string.
1009 IN EFI_STRING_ID Token
,
1010 IN EFI_HII_HANDLE HiiHandle
1015 if (HiiHandle
== NULL
) {
1019 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1020 if (String
== NULL
) {
1021 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1022 ASSERT (String
!= NULL
);
1024 return (CHAR16
*) String
;
1029 Allocate new memory and then copy the Unicode string Source to Destination.
1031 @param Dest Location to copy string
1032 @param Src String to copy
1037 IN OUT CHAR16
**Dest
,
1041 if (*Dest
!= NULL
) {
1044 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1045 ASSERT (*Dest
!= NULL
);
1050 Allocate new memory and concatinate Source on the end of Destination.
1052 @param Dest String to added to the end of.
1053 @param Src String to concatinate.
1058 IN OUT CHAR16
**Dest
,
1065 if (*Dest
== NULL
) {
1066 NewStringCpy (Dest
, Src
);
1070 TmpSize
= StrSize (*Dest
);
1071 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1072 ASSERT (NewString
!= NULL
);
1074 StrCpy (NewString
, *Dest
);
1075 StrCat (NewString
, Src
);
1082 Get Value for given Name from a NameValue Storage.
1084 @param Storage The NameValue Storage.
1085 @param Name The Name.
1086 @param Value The retured Value.
1087 @param GetValueFrom Where to get source value, from EditValue or Value.
1089 @retval EFI_SUCCESS Value found for given Name.
1090 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1095 IN BROWSER_STORAGE
*Storage
,
1097 IN OUT CHAR16
**Value
,
1098 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1102 NAME_VALUE_NODE
*Node
;
1104 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1105 return EFI_INVALID_PARAMETER
;
1110 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1111 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1112 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1114 if (StrCmp (Name
, Node
->Name
) == 0) {
1115 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1116 NewStringCpy (Value
, Node
->EditValue
);
1118 NewStringCpy (Value
, Node
->Value
);
1123 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1126 return EFI_NOT_FOUND
;
1131 Set Value of given Name in a NameValue Storage.
1133 @param Storage The NameValue Storage.
1134 @param Name The Name.
1135 @param Value The Value to set.
1136 @param SetValueTo Whether update editValue or Value.
1137 @param ReturnNode The node use the input name.
1139 @retval EFI_SUCCESS Value found for given Name.
1140 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1145 IN BROWSER_STORAGE
*Storage
,
1148 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1149 OUT NAME_VALUE_NODE
**ReturnNode
1153 NAME_VALUE_NODE
*Node
;
1156 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1157 return EFI_INVALID_PARAMETER
;
1160 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1161 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1162 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1164 if (StrCmp (Name
, Node
->Name
) == 0) {
1165 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1166 Buffer
= Node
->EditValue
;
1168 Buffer
= Node
->Value
;
1170 if (Buffer
!= NULL
) {
1173 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1174 ASSERT (Buffer
!= NULL
);
1175 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1176 Node
->EditValue
= Buffer
;
1178 Node
->Value
= Buffer
;
1181 if (ReturnNode
!= NULL
) {
1188 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1191 return EFI_NOT_FOUND
;
1196 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1198 @param Storage The Storage to be conveted.
1199 @param ConfigResp The returned <ConfigResp>.
1200 @param ConfigRequest The ConfigRequest string.
1201 @param GetEditBuf Get the data from editbuffer or buffer.
1203 @retval EFI_SUCCESS Convert success.
1204 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1208 StorageToConfigResp (
1209 IN BROWSER_STORAGE
*Storage
,
1210 IN CHAR16
**ConfigResp
,
1211 IN CHAR16
*ConfigRequest
,
1212 IN BOOLEAN GetEditBuf
1216 EFI_STRING Progress
;
1218 NAME_VALUE_NODE
*Node
;
1221 Status
= EFI_SUCCESS
;
1223 switch (Storage
->Type
) {
1224 case EFI_HII_VARSTORE_BUFFER
:
1225 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1226 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1227 Status
= mHiiConfigRouting
->BlockToConfig (
1237 case EFI_HII_VARSTORE_NAME_VALUE
:
1239 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1241 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1242 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1243 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1245 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1246 NewStringCat (ConfigResp
, L
"&");
1247 NewStringCat (ConfigResp
, Node
->Name
);
1248 NewStringCat (ConfigResp
, L
"=");
1250 NewStringCat (ConfigResp
, Node
->EditValue
);
1252 NewStringCat (ConfigResp
, Node
->Value
);
1255 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1259 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1261 Status
= EFI_INVALID_PARAMETER
;
1270 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1272 @param Storage The Storage to receive the settings.
1273 @param ConfigResp The <ConfigResp> to be converted.
1275 @retval EFI_SUCCESS Convert success.
1276 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1280 ConfigRespToStorage (
1281 IN BROWSER_STORAGE
*Storage
,
1282 IN CHAR16
*ConfigResp
1286 EFI_STRING Progress
;
1292 Status
= EFI_SUCCESS
;
1294 switch (Storage
->Type
) {
1295 case EFI_HII_VARSTORE_BUFFER
:
1296 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1297 BufferSize
= Storage
->Size
;
1298 Status
= mHiiConfigRouting
->ConfigToBlock (
1301 Storage
->EditBuffer
,
1307 case EFI_HII_VARSTORE_NAME_VALUE
:
1308 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1309 if (StrPtr
== NULL
) {
1312 StrPtr
= StrStr (ConfigResp
, L
"&");
1313 while (StrPtr
!= NULL
) {
1317 StrPtr
= StrPtr
+ 1;
1319 StrPtr
= StrStr (StrPtr
, L
"=");
1320 if (StrPtr
== NULL
) {
1328 StrPtr
= StrPtr
+ 1;
1330 StrPtr
= StrStr (StrPtr
, L
"&");
1331 if (StrPtr
!= NULL
) {
1334 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1338 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1340 Status
= EFI_INVALID_PARAMETER
;
1348 Convert the buffer value to HiiValue.
1350 @param Question The question.
1351 @param Value Unicode buffer save the question value.
1353 @retval Status whether convert the value success.
1358 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1363 BOOLEAN IsBufferStorage
;
1375 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1376 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1377 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1378 IsBufferStorage
= TRUE
;
1380 IsBufferStorage
= FALSE
;
1384 // Question Value is provided by Buffer Storage or NameValue Storage
1386 if (Question
->BufferValue
!= NULL
) {
1388 // This Question is password or orderedlist
1390 Dst
= Question
->BufferValue
;
1393 // Other type of Questions
1395 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1399 // Temp cut at the end of this section, end with '\0' or '&'.
1402 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1405 TempChar
= *StringPtr
;
1408 LengthStr
= StrLen (Value
);
1409 Status
= EFI_SUCCESS
;
1410 if (!IsBufferStorage
&& IsString
) {
1412 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1413 // Add string tail char L'\0' into Length
1415 Length
= Question
->StorageWidth
+ sizeof (CHAR16
);
1416 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1417 Status
= EFI_BUFFER_TOO_SMALL
;
1419 DstBuf
= (CHAR16
*) Dst
;
1420 ZeroMem (TemStr
, sizeof (TemStr
));
1421 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1422 StrnCpy (TemStr
, Value
+ Index
, 4);
1423 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1426 // Add tailing L'\0' character
1428 DstBuf
[Index
/4] = L
'\0';
1431 if (Question
->StorageWidth
< ((LengthStr
+ 1) / 2)) {
1432 Status
= EFI_BUFFER_TOO_SMALL
;
1434 ZeroMem (TemStr
, sizeof (TemStr
));
1435 for (Index
= 0; Index
< LengthStr
; Index
++) {
1436 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1437 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1438 if ((Index
& 1) == 0) {
1439 Dst
[Index
/2] = DigitUint8
;
1441 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1447 *StringPtr
= TempChar
;
1453 Get Question's current Value.
1455 @param FormSet FormSet data structure.
1456 @param Form Form data structure.
1457 @param Question Question to be initialized.
1458 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1460 @retval EFI_SUCCESS The function completed successfully.
1465 IN FORM_BROWSER_FORMSET
*FormSet
,
1466 IN FORM_BROWSER_FORM
*Form
,
1467 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1468 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1477 BROWSER_STORAGE
*Storage
;
1478 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1479 CHAR16
*ConfigRequest
;
1484 BOOLEAN IsBufferStorage
;
1486 Status
= EFI_SUCCESS
;
1490 if (GetValueFrom
>= GetSetValueWithMax
) {
1491 return EFI_INVALID_PARAMETER
;
1495 // Question value is provided by an Expression, evaluate it
1497 if (Question
->ValueExpression
!= NULL
) {
1498 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1499 if (!EFI_ERROR (Status
)) {
1500 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1501 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1502 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1503 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1504 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1506 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1507 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1509 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1511 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1512 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1518 // Get question value by read expression.
1520 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1521 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1522 if (!EFI_ERROR (Status
) &&
1523 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1525 // Only update question value to the valid result.
1527 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1528 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1529 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1530 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1531 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1533 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1534 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1536 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1538 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1539 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1545 // Question value is provided by RTC
1547 Storage
= Question
->Storage
;
1548 QuestionValue
= &Question
->HiiValue
.Value
;
1549 if (Storage
== NULL
) {
1551 // It's a Question without storage, or RTC date/time
1553 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1555 // Date and time define the same Flags bit
1557 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1558 case QF_DATE_STORAGE_TIME
:
1559 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1562 case QF_DATE_STORAGE_WAKEUP
:
1563 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1566 case QF_DATE_STORAGE_NORMAL
:
1569 // For date/time without storage
1574 if (EFI_ERROR (Status
)) {
1578 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1579 QuestionValue
->date
.Year
= EfiTime
.Year
;
1580 QuestionValue
->date
.Month
= EfiTime
.Month
;
1581 QuestionValue
->date
.Day
= EfiTime
.Day
;
1583 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1584 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1585 QuestionValue
->time
.Second
= EfiTime
.Second
;
1593 // Question value is provided by EFI variable
1595 StorageWidth
= Question
->StorageWidth
;
1596 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1597 if (Question
->BufferValue
!= NULL
) {
1598 Dst
= Question
->BufferValue
;
1600 Dst
= (UINT8
*) QuestionValue
;
1603 Status
= gRT
->GetVariable (
1604 Question
->VariableName
,
1611 // Always return success, even this EFI variable doesn't exist
1617 // Question Value is provided by Buffer Storage or NameValue Storage
1619 if (Question
->BufferValue
!= NULL
) {
1621 // This Question is password or orderedlist
1623 Dst
= Question
->BufferValue
;
1626 // Other type of Questions
1628 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1631 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1632 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1633 IsBufferStorage
= TRUE
;
1635 IsBufferStorage
= FALSE
;
1637 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1638 if (IsBufferStorage
) {
1639 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1641 // Copy from storage Edit buffer
1643 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1646 // Copy from storage Edit buffer
1648 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1652 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1653 if (EFI_ERROR (Status
)) {
1657 ASSERT (Value
!= NULL
);
1658 Status
= BufferToValue (Question
, Value
);
1663 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1664 // <ConfigHdr> + "&" + <VariableName>
1666 if (IsBufferStorage
) {
1667 Length
= StrLen (Storage
->ConfigHdr
);
1668 Length
+= StrLen (Question
->BlockName
);
1670 Length
= StrLen (Storage
->ConfigHdr
);
1671 Length
+= StrLen (Question
->VariableName
) + 1;
1673 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1674 ASSERT (ConfigRequest
!= NULL
);
1676 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1677 if (IsBufferStorage
) {
1678 StrCat (ConfigRequest
, Question
->BlockName
);
1680 StrCat (ConfigRequest
, L
"&");
1681 StrCat (ConfigRequest
, Question
->VariableName
);
1685 // Request current settings from Configuration Driver
1687 Status
= mHiiConfigRouting
->ExtractConfig (
1693 FreePool (ConfigRequest
);
1694 if (EFI_ERROR (Status
)) {
1699 // Skip <ConfigRequest>
1701 if (IsBufferStorage
) {
1702 Value
= StrStr (Result
, L
"&VALUE");
1703 if (Value
== NULL
) {
1705 return EFI_NOT_FOUND
;
1712 Value
= Result
+ Length
;
1714 if (*Value
!= '=') {
1716 return EFI_NOT_FOUND
;
1719 // Skip '=', point to value
1723 Status
= BufferToValue (Question
, Value
);
1724 if (EFI_ERROR (Status
)) {
1730 // Synchronize Edit Buffer
1732 if (IsBufferStorage
) {
1733 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1735 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1738 if (Result
!= NULL
) {
1748 Save Question Value to edit copy(cached) or Storage(uncached).
1750 @param FormSet FormSet data structure.
1751 @param Form Form data structure.
1752 @param Question Pointer to the Question.
1753 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1755 @retval EFI_SUCCESS The function completed successfully.
1760 IN FORM_BROWSER_FORMSET
*FormSet
,
1761 IN FORM_BROWSER_FORM
*Form
,
1762 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1763 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1773 BROWSER_STORAGE
*Storage
;
1774 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1779 BOOLEAN IsBufferStorage
;
1785 NAME_VALUE_NODE
*Node
;
1787 Status
= EFI_SUCCESS
;
1790 if (SetValueTo
>= GetSetValueWithMax
) {
1791 return EFI_INVALID_PARAMETER
;
1795 // If Question value is provided by an Expression, then it is read only
1797 if (Question
->ValueExpression
!= NULL
) {
1802 // Before set question value, evaluate its write expression.
1804 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1805 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1806 if (EFI_ERROR (Status
)) {
1812 // Question value is provided by RTC
1814 Storage
= Question
->Storage
;
1815 QuestionValue
= &Question
->HiiValue
.Value
;
1816 if (Storage
== NULL
) {
1818 // It's a Question without storage, or RTC date/time
1820 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1822 // Date and time define the same Flags bit
1824 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1825 case QF_DATE_STORAGE_TIME
:
1826 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1829 case QF_DATE_STORAGE_WAKEUP
:
1830 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1833 case QF_DATE_STORAGE_NORMAL
:
1836 // For date/time without storage
1841 if (EFI_ERROR (Status
)) {
1845 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1846 EfiTime
.Year
= QuestionValue
->date
.Year
;
1847 EfiTime
.Month
= QuestionValue
->date
.Month
;
1848 EfiTime
.Day
= QuestionValue
->date
.Day
;
1850 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1851 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1852 EfiTime
.Second
= QuestionValue
->time
.Second
;
1855 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1856 Status
= gRT
->SetTime (&EfiTime
);
1858 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1866 // Question value is provided by EFI variable
1868 StorageWidth
= Question
->StorageWidth
;
1869 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1870 if (Question
->BufferValue
!= NULL
) {
1871 Src
= Question
->BufferValue
;
1873 Src
= (UINT8
*) QuestionValue
;
1876 Status
= gRT
->SetVariable (
1877 Question
->VariableName
,
1879 Storage
->Attributes
,
1887 // Question Value is provided by Buffer Storage or NameValue Storage
1889 if (Question
->BufferValue
!= NULL
) {
1890 Src
= Question
->BufferValue
;
1892 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1895 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1896 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1897 IsBufferStorage
= TRUE
;
1899 IsBufferStorage
= FALSE
;
1901 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1903 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1904 if (IsBufferStorage
) {
1905 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1907 // Copy to storage edit buffer
1909 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1910 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1912 // Copy to storage edit buffer
1914 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1919 // Allocate enough string buffer.
1922 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1923 Value
= AllocateZeroPool (BufferLen
);
1924 ASSERT (Value
!= NULL
);
1926 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1928 TemName
= (CHAR16
*) Src
;
1930 for (; *TemName
!= L
'\0'; TemName
++) {
1931 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1934 BufferLen
= StorageWidth
* 2 + 1;
1935 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1936 ASSERT (Value
!= NULL
);
1938 // Convert Buffer to Hex String
1940 TemBuffer
= Src
+ StorageWidth
- 1;
1942 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1943 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1947 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1949 if (EFI_ERROR (Status
)) {
1953 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1955 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1956 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1958 if (IsBufferStorage
) {
1959 Length
= StrLen (Question
->BlockName
) + 7;
1961 Length
= StrLen (Question
->VariableName
) + 2;
1963 if (!IsBufferStorage
&& IsString
) {
1964 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1966 Length
+= (StorageWidth
* 2);
1968 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1969 ASSERT (ConfigResp
!= NULL
);
1971 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1972 if (IsBufferStorage
) {
1973 StrCat (ConfigResp
, Question
->BlockName
);
1974 StrCat (ConfigResp
, L
"&VALUE=");
1976 StrCat (ConfigResp
, L
"&");
1977 StrCat (ConfigResp
, Question
->VariableName
);
1978 StrCat (ConfigResp
, L
"=");
1981 Value
= ConfigResp
+ StrLen (ConfigResp
);
1983 if (!IsBufferStorage
&& IsString
) {
1985 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1987 TemName
= (CHAR16
*) Src
;
1989 for (; *TemName
!= L
'\0'; TemName
++) {
1990 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1994 // Convert Buffer to Hex String
1996 TemBuffer
= Src
+ StorageWidth
- 1;
1998 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1999 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2004 // Convert to lower char.
2006 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2007 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2008 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2013 // Submit Question Value to Configuration Driver
2015 Status
= mHiiConfigRouting
->RouteConfig (
2020 if (EFI_ERROR (Status
)) {
2021 FreePool (ConfigResp
);
2024 FreePool (ConfigResp
);
2027 // Sync storage, from editbuffer to buffer.
2029 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2037 Perform nosubmitif check for a Form.
2039 @param FormSet FormSet data structure.
2040 @param Form Form data structure.
2041 @param Question The Question to be validated.
2042 @param Type Validation type: NoSubmit
2044 @retval EFI_SUCCESS Form validation pass.
2045 @retval other Form validation failed.
2050 IN FORM_BROWSER_FORMSET
*FormSet
,
2051 IN FORM_BROWSER_FORM
*Form
,
2052 IN FORM_BROWSER_STATEMENT
*Question
,
2058 LIST_ENTRY
*ListHead
;
2059 FORM_EXPRESSION
*Expression
;
2060 UINT32 BrowserStatus
;
2063 BrowserStatus
= BROWSER_SUCCESS
;
2067 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2068 ListHead
= &Question
->InconsistentListHead
;
2071 case EFI_HII_EXPRESSION_WARNING_IF
:
2072 ListHead
= &Question
->WarningListHead
;
2075 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2076 ListHead
= &Question
->NoSubmitListHead
;
2081 return EFI_UNSUPPORTED
;
2084 Link
= GetFirstNode (ListHead
);
2085 while (!IsNull (ListHead
, Link
)) {
2086 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2089 // Evaluate the expression
2091 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2092 if (EFI_ERROR (Status
)) {
2096 if (IsTrue (&Expression
->Result
)) {
2098 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2099 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2102 case EFI_HII_EXPRESSION_WARNING_IF
:
2103 BrowserStatus
= BROWSER_WARNING_IF
;
2106 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2107 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2109 // This code only used to compatible with old display engine,
2110 // New display engine will not use this field.
2112 if (Expression
->Error
!= 0) {
2113 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2122 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2124 // If in system submit process and for no_submit_if check, not popup this error message.
2125 // Will process this fail again later in not system submit process.
2127 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2130 if (ErrorStr
!= NULL
) {
2131 FreePool (ErrorStr
);
2134 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2137 return EFI_NOT_READY
;
2141 Link
= GetNextNode (ListHead
, Link
);
2148 Perform question check.
2150 If one question has more than one check, process form high priority to low.
2151 Only one error info will be popup.
2153 @param FormSet FormSet data structure.
2154 @param Form Form data structure.
2155 @param Question The Question to be validated.
2157 @retval EFI_SUCCESS Form validation pass.
2158 @retval other Form validation failed.
2162 ValueChangedValidation (
2163 IN FORM_BROWSER_FORMSET
*FormSet
,
2164 IN FORM_BROWSER_FORM
*Form
,
2165 IN FORM_BROWSER_STATEMENT
*Question
2170 Status
= EFI_SUCCESS
;
2173 // Do the inconsistentif check.
2175 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2176 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2177 if (EFI_ERROR (Status
)) {
2183 // Do the warningif check.
2185 if (!IsListEmpty (&Question
->WarningListHead
)) {
2186 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2193 Perform NoSubmit check for each Form in FormSet.
2195 @param FormSet FormSet data structure.
2196 @param CurrentForm Current input form data structure.
2197 @param Statement The statement for this check.
2199 @retval EFI_SUCCESS Form validation pass.
2200 @retval other Form validation failed.
2205 IN FORM_BROWSER_FORMSET
*FormSet
,
2206 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2207 OUT FORM_BROWSER_STATEMENT
**Statement
2212 FORM_BROWSER_STATEMENT
*Question
;
2213 FORM_BROWSER_FORM
*Form
;
2214 LIST_ENTRY
*LinkForm
;
2216 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2217 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2218 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2219 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2221 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2225 Link
= GetFirstNode (&Form
->StatementListHead
);
2226 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2227 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2228 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2229 if (EFI_ERROR (Status
)) {
2230 if (*CurrentForm
== NULL
) {
2231 *CurrentForm
= Form
;
2233 if (Statement
!= NULL
) {
2234 *Statement
= Question
;
2239 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2247 Fill storage's edit copy with settings requested from Configuration Driver.
2249 @param Storage The storage which need to sync.
2250 @param ConfigRequest The config request string which used to sync storage.
2251 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2252 editbuffer to buffer
2253 if TRUE, copy the editbuffer to the buffer.
2254 if FALSE, copy the buffer to the editbuffer.
2256 @retval EFI_SUCCESS The function completed successfully.
2260 SynchronizeStorage (
2261 OUT BROWSER_STORAGE
*Storage
,
2262 IN CHAR16
*ConfigRequest
,
2263 IN BOOLEAN SyncOrRestore
2267 EFI_STRING Progress
;
2271 NAME_VALUE_NODE
*Node
;
2275 Status
= EFI_SUCCESS
;
2278 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2279 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2280 BufferSize
= Storage
->Size
;
2282 if (SyncOrRestore
) {
2283 Src
= Storage
->EditBuffer
;
2284 Dst
= Storage
->Buffer
;
2286 Src
= Storage
->Buffer
;
2287 Dst
= Storage
->EditBuffer
;
2290 if (ConfigRequest
!= NULL
) {
2291 Status
= mHiiConfigRouting
->BlockToConfig(
2299 if (EFI_ERROR (Status
)) {
2303 Status
= mHiiConfigRouting
->ConfigToBlock (
2310 if (Result
!= NULL
) {
2314 CopyMem (Dst
, Src
, BufferSize
);
2316 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2317 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2318 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2319 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2321 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2322 (ConfigRequest
== NULL
)) {
2323 if (SyncOrRestore
) {
2324 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2326 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2330 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2338 When discard the question value, call the callback function with Changed type
2339 to inform the hii driver.
2341 @param FormSet FormSet data structure.
2342 @param Form Form data structure.
2346 SendDiscardInfoToDriver (
2347 IN FORM_BROWSER_FORMSET
*FormSet
,
2348 IN FORM_BROWSER_FORM
*Form
2352 FORM_BROWSER_STATEMENT
*Question
;
2353 EFI_IFR_TYPE_VALUE
*TypeValue
;
2354 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2356 if (FormSet
->ConfigAccess
== NULL
) {
2360 Link
= GetFirstNode (&Form
->StatementListHead
);
2361 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2362 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2363 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2365 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2369 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2373 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2377 if (!Question
->ValueChanged
) {
2382 // Restore the question value before call the CHANGED callback type.
2384 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2386 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2387 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2389 TypeValue
= &Question
->HiiValue
.Value
;
2392 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2393 FormSet
->ConfigAccess
->Callback (
2394 FormSet
->ConfigAccess
,
2395 EFI_BROWSER_ACTION_CHANGED
,
2396 Question
->QuestionId
,
2397 Question
->HiiValue
.Type
,
2405 Validate the HiiHandle.
2407 @param HiiHandle The input HiiHandle which need to validate.
2409 @retval TRUE The handle is validate.
2410 @retval FALSE The handle is invalidate.
2415 EFI_HII_HANDLE HiiHandle
2418 EFI_HII_HANDLE
*HiiHandles
;
2422 if (HiiHandle
== NULL
) {
2428 HiiHandles
= HiiGetHiiHandles (NULL
);
2429 ASSERT (HiiHandles
!= NULL
);
2431 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2432 if (HiiHandles
[Index
] == HiiHandle
) {
2438 FreePool (HiiHandles
);
2444 Validate the FormSet. If the formset is not validate, remove it from the list.
2446 @param FormSet The input FormSet which need to validate.
2448 @retval TRUE The handle is validate.
2449 @retval FALSE The handle is invalidate.
2454 FORM_BROWSER_FORMSET
*FormSet
2459 ASSERT (FormSet
!= NULL
);
2461 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2463 // Should not remove the formset which is being used.
2465 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2466 CleanBrowserStorage(FormSet
);
2467 RemoveEntryList (&FormSet
->Link
);
2468 DestroyFormSet (FormSet
);
2474 Check whether need to enable the reset flag in form level.
2475 Also clean all ValueChanged flag in question.
2477 @param SetFlag Whether need to set the Reset Flag.
2478 @param FormSet FormSet data structure.
2479 @param Form Form data structure.
2485 IN FORM_BROWSER_FORMSET
*FormSet
,
2486 IN FORM_BROWSER_FORM
*Form
2490 FORM_BROWSER_STATEMENT
*Question
;
2493 Link
= GetFirstNode (&Form
->StatementListHead
);
2494 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2495 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2496 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2498 if (!Question
->ValueChanged
) {
2502 OldValue
= Question
->ValueChanged
;
2505 // Compare the buffer and editbuffer data to see whether the data has been saved.
2507 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2510 // Only the changed data has been saved, then need to set the reset flag.
2512 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2513 gResetRequired
= TRUE
;
2519 Check whether need to enable the reset flag.
2520 Also clean ValueChanged flag for all statements.
2522 Form level or formset level, only one.
2524 @param SetFlag Whether need to set the Reset Flag.
2525 @param FormSet FormSet data structure.
2526 @param Form Form data structure.
2530 ValueChangeResetFlagUpdate (
2532 IN FORM_BROWSER_FORMSET
*FormSet
,
2533 IN FORM_BROWSER_FORM
*Form
2536 FORM_BROWSER_FORM
*CurrentForm
;
2540 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2544 Link
= GetFirstNode (&FormSet
->FormListHead
);
2545 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2546 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2547 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2549 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2554 Base on the return Progress string to find the form.
2556 Base on the first return Offset/Width (Name) string to find the form
2557 which keep this string.
2559 @param FormSet FormSet data structure.
2560 @param Storage Storage which has this Progress string.
2561 @param Progress The Progress string which has the first fail string.
2562 @param RetForm The return form for this progress string.
2563 @param RetQuestion The return question for the error progress string.
2565 @retval TRUE Find the error form and statement for this error progress string.
2566 @retval FALSE Not find the error form.
2570 FindQuestionFromProgress (
2571 IN FORM_BROWSER_FORMSET
*FormSet
,
2572 IN BROWSER_STORAGE
*Storage
,
2573 IN EFI_STRING Progress
,
2574 OUT FORM_BROWSER_FORM
**RetForm
,
2575 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2579 LIST_ENTRY
*LinkStorage
;
2580 LIST_ENTRY
*LinkStatement
;
2581 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2582 FORM_BROWSER_FORM
*Form
;
2584 FORM_BROWSER_STATEMENT
*Statement
;
2586 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2590 *RetQuestion
= NULL
;
2593 // Skip the first "&" or the ConfigHdr part.
2595 if (*Progress
== '&') {
2599 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2601 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2603 // For Name/Value type, Skip the ConfigHdr part.
2605 EndStr
= StrStr (Progress
, L
"PATH=");
2606 ASSERT (EndStr
!= NULL
);
2607 while (*EndStr
!= '&') {
2614 // For Buffer type, Skip the ConfigHdr part.
2616 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2617 ASSERT (EndStr
!= NULL
);
2621 Progress
= EndStr
+ 1;
2625 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2627 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2629 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2630 // here, just keep the "Fred" string.
2632 EndStr
= StrStr (Progress
, L
"=");
2633 ASSERT (EndStr
!= NULL
);
2637 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2638 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2640 EndStr
= StrStr (Progress
, L
"&VALUE=");
2641 ASSERT (EndStr
!= NULL
);
2646 // Search in the form list.
2648 Link
= GetFirstNode (&FormSet
->FormListHead
);
2649 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2650 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2651 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2654 // Search in the ConfigReqeust list in this form.
2656 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2657 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2658 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2659 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2661 if (Storage
!= ConfigInfo
->Storage
) {
2665 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2667 // Find the OffsetWidth string in this form.
2674 if (*RetForm
!= NULL
) {
2675 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2676 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2677 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2678 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2680 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2681 *RetQuestion
= Statement
;
2687 if (*RetForm
!= NULL
) {
2693 // restore the OffsetWidth string to the original format.
2695 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2701 return (BOOLEAN
) (*RetForm
!= NULL
);
2705 Popup an save error info and get user input.
2707 @param TitleId The form title id.
2708 @param HiiHandle The hii handle for this package.
2710 @retval UINT32 The user select option for the save fail.
2711 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2715 IN EFI_STRING_ID TitleId
,
2716 IN EFI_HII_HANDLE HiiHandle
2720 CHAR16
*StringBuffer
;
2723 FormTitle
= GetToken (TitleId
, HiiHandle
);
2725 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2726 ASSERT (StringBuffer
!= NULL
);
2730 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2731 L
"Submit Fail For Form: %s.",
2735 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2737 FreePool (StringBuffer
);
2738 FreePool (FormTitle
);
2744 Popup an NO_SUBMIT_IF error info and get user input.
2746 @param TitleId The form title id.
2747 @param HiiHandle The hii handle for this package.
2749 @retval UINT32 The user select option for the save fail.
2750 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2753 ConfirmNoSubmitFail (
2754 IN EFI_STRING_ID TitleId
,
2755 IN EFI_HII_HANDLE HiiHandle
2759 CHAR16
*StringBuffer
;
2762 FormTitle
= GetToken (TitleId
, HiiHandle
);
2764 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2765 ASSERT (StringBuffer
!= NULL
);
2769 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2770 L
"NO_SUBMIT_IF error For Form: %s.",
2774 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2776 FreePool (StringBuffer
);
2777 FreePool (FormTitle
);
2783 Discard data based on the input setting scope (Form, FormSet or System).
2785 @param FormSet FormSet data structure.
2786 @param Form Form data structure.
2787 @param SettingScope Setting Scope for Discard action.
2789 @retval EFI_SUCCESS The function completed successfully.
2790 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2795 IN FORM_BROWSER_FORMSET
*FormSet
,
2796 IN FORM_BROWSER_FORM
*Form
,
2797 IN BROWSER_SETTING_SCOPE SettingScope
2801 FORMSET_STORAGE
*Storage
;
2802 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2803 FORM_BROWSER_FORMSET
*LocalFormSet
;
2804 FORM_BROWSER_FORMSET
*OldFormSet
;
2807 // Check the supported setting level.
2809 if (SettingScope
>= MaxLevel
) {
2810 return EFI_UNSUPPORTED
;
2813 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2815 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2816 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2817 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2818 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2820 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2825 // Skip if there is no RequestElement
2827 if (ConfigInfo
->ElementCount
== 0) {
2832 // Prepare <ConfigResp>
2834 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2837 // Call callback with Changed type to inform the driver.
2839 SendDiscardInfoToDriver (FormSet
, Form
);
2842 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2843 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2846 // Discard Buffer storage or Name/Value storage
2848 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2849 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2850 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2851 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2853 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2858 // Skip if there is no RequestElement
2860 if (Storage
->ElementCount
== 0) {
2864 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2867 Link
= GetFirstNode (&FormSet
->FormListHead
);
2868 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2869 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2870 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2873 // Call callback with Changed type to inform the driver.
2875 SendDiscardInfoToDriver (FormSet
, Form
);
2878 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2879 } else if (SettingScope
== SystemLevel
) {
2881 // System Level Discard.
2883 OldFormSet
= mSystemLevelFormSet
;
2886 // Discard changed value for each FormSet in the maintain list.
2888 Link
= GetFirstNode (&gBrowserFormSetList
);
2889 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2890 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2891 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2892 if (!ValidateFormSet(LocalFormSet
)) {
2896 mSystemLevelFormSet
= LocalFormSet
;
2898 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2899 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2901 // Remove maintain backup list after discard except for the current using FormSet.
2903 CleanBrowserStorage(LocalFormSet
);
2904 RemoveEntryList (&LocalFormSet
->Link
);
2905 DestroyFormSet (LocalFormSet
);
2909 mSystemLevelFormSet
= OldFormSet
;
2916 Submit data for a form.
2918 @param FormSet FormSet data structure.
2919 @param Form Form data structure.
2921 @retval EFI_SUCCESS The function completed successfully.
2922 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2927 IN FORM_BROWSER_FORMSET
*FormSet
,
2928 IN FORM_BROWSER_FORM
*Form
2933 EFI_STRING ConfigResp
;
2934 EFI_STRING Progress
;
2935 BROWSER_STORAGE
*Storage
;
2936 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2938 if (!IsNvUpdateRequiredForForm (Form
)) {
2942 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2943 if (EFI_ERROR (Status
)) {
2947 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2948 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2949 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2950 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2952 Storage
= ConfigInfo
->Storage
;
2953 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2958 // Skip if there is no RequestElement
2960 if (ConfigInfo
->ElementCount
== 0) {
2965 // 1. Prepare <ConfigResp>
2967 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2968 if (EFI_ERROR (Status
)) {
2973 // 2. Set value to hii config routine protocol.
2975 Status
= mHiiConfigRouting
->RouteConfig (
2980 FreePool (ConfigResp
);
2982 if (EFI_ERROR (Status
)) {
2983 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2988 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2990 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2994 // 4. Process the save failed storage.
2996 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2997 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
2998 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2999 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3000 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3001 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3003 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3005 Status
= EFI_SUCCESS
;
3008 Status
= EFI_UNSUPPORTED
;
3012 // Free Form save fail list.
3014 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3015 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3016 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3017 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3022 // 5. Update the NV flag.
3024 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3030 Submit data for a formset.
3032 @param FormSet FormSet data structure.
3033 @param SkipProcessFail Whether skip to process the save failed storage.
3034 If submit formset is called when do system level save,
3035 set this value to true and process the failed formset
3037 if submit formset is called when do formset level save,
3038 set the value to false and process the failed storage
3039 right after process all storages for this formset.
3041 @retval EFI_SUCCESS The function completed successfully.
3042 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3047 IN FORM_BROWSER_FORMSET
*FormSet
,
3048 IN BOOLEAN SkipProcessFail
3053 EFI_STRING ConfigResp
;
3054 EFI_STRING Progress
;
3055 BROWSER_STORAGE
*Storage
;
3056 FORMSET_STORAGE
*FormSetStorage
;
3057 FORM_BROWSER_FORM
*Form
;
3058 BOOLEAN HasInserted
;
3059 FORM_BROWSER_STATEMENT
*Question
;
3061 HasInserted
= FALSE
;
3063 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3068 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3069 if (EFI_ERROR (Status
)) {
3070 if (SkipProcessFail
) {
3072 // Process NO_SUBMIT check first, so insert it at head.
3074 FormSet
->SaveFailForm
= Form
;
3075 FormSet
->SaveFailStatement
= Question
;
3076 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3085 // Submit Buffer storage or Name/Value storage
3087 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3088 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3089 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3090 Storage
= FormSetStorage
->BrowserStorage
;
3091 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3093 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3098 // Skip if there is no RequestElement
3100 if (FormSetStorage
->ElementCount
== 0) {
3105 // 1. Prepare <ConfigResp>
3107 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3108 if (EFI_ERROR (Status
)) {
3113 // 2. Send <ConfigResp> to Routine config Protocol.
3115 Status
= mHiiConfigRouting
->RouteConfig (
3120 if (EFI_ERROR (Status
)) {
3121 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3124 // Call submit formset for system level, save the formset info
3125 // and process later.
3127 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3128 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3129 FormSet
->SaveFailForm
= Form
;
3130 FormSet
->SaveFailStatement
= Question
;
3131 if (SkipProcessFail
) {
3132 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3137 FreePool (ConfigResp
);
3141 FreePool (ConfigResp
);
3143 // 3. Config success, update storage shadow Buffer
3145 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3149 // 4. Has save fail storage need to handle.
3152 if (!SkipProcessFail
) {
3154 // If not in system level, just handl the save failed storage here.
3156 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3157 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3158 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3159 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3160 Storage
= FormSetStorage
->BrowserStorage
;
3161 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3163 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3165 Status
= EFI_SUCCESS
;
3168 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3170 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3171 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3172 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3173 gCurrentSelection
->FormId
= Form
->FormId
;
3174 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3176 Status
= EFI_UNSUPPORTED
;
3180 // Free FormSet save fail list.
3182 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3183 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3184 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3185 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3189 // If in system level, just return error and handle the failed formset later.
3191 Status
= EFI_UNSUPPORTED
;
3196 // 5. Update the NV flag.
3198 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3204 Submit data for all formsets.
3206 @retval EFI_SUCCESS The function completed successfully.
3207 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3217 LIST_ENTRY
*StorageLink
;
3218 FORMSET_STORAGE
*FormSetStorage
;
3219 FORM_BROWSER_FORM
*Form
;
3220 FORM_BROWSER_FORMSET
*LocalFormSet
;
3221 UINT32 UserSelection
;
3222 FORM_BROWSER_STATEMENT
*Question
;
3224 mSystemSubmit
= TRUE
;
3225 Link
= GetFirstNode (&gBrowserFormSetList
);
3226 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3227 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3228 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3229 if (!ValidateFormSet(LocalFormSet
)) {
3233 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3234 if (EFI_ERROR (Status
)) {
3239 // Remove maintain backup list after save except for the current using FormSet.
3241 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3242 CleanBrowserStorage(LocalFormSet
);
3243 RemoveEntryList (&LocalFormSet
->Link
);
3244 DestroyFormSet (LocalFormSet
);
3247 mSystemSubmit
= FALSE
;
3249 Status
= EFI_SUCCESS
;
3252 // Process the save failed formsets.
3254 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3255 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3256 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3257 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3259 if (!ValidateFormSet(LocalFormSet
)) {
3263 Form
= LocalFormSet
->SaveFailForm
;
3264 Question
= LocalFormSet
->SaveFailStatement
;
3267 // Confirm with user, get user input.
3269 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3271 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3273 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3275 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3278 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3279 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3280 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3281 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3282 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3283 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3285 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3288 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3289 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3290 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3291 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3293 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3297 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3298 CleanBrowserStorage(LocalFormSet
);
3299 RemoveEntryList (&LocalFormSet
->Link
);
3300 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3301 DestroyFormSet (LocalFormSet
);
3303 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3306 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3307 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3310 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3312 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3313 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3314 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3315 gCurrentSelection
->FormId
= Form
->FormId
;
3316 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3318 Status
= EFI_UNSUPPORTED
;
3324 // Clean the list which will not process.
3326 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3327 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3328 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3329 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3331 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3332 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3333 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3334 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3342 Submit data based on the input Setting level (Form, FormSet or System).
3344 @param FormSet FormSet data structure.
3345 @param Form Form data structure.
3346 @param SettingScope Setting Scope for Submit action.
3348 @retval EFI_SUCCESS The function completed successfully.
3349 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3354 IN FORM_BROWSER_FORMSET
*FormSet
,
3355 IN FORM_BROWSER_FORM
*Form
,
3356 IN BROWSER_SETTING_SCOPE SettingScope
3361 switch (SettingScope
) {
3363 Status
= SubmitForForm(FormSet
, Form
);
3367 Status
= SubmitForFormSet (FormSet
, FALSE
);
3371 Status
= SubmitForSystem ();
3375 Status
= EFI_UNSUPPORTED
;
3383 Converts the unicode character of the string from uppercase to lowercase.
3384 This is a internal function.
3386 @param ConfigString String to be converted
3392 IN EFI_STRING ConfigString
3398 ASSERT (ConfigString
!= NULL
);
3401 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3403 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3404 if (*String
== L
'=') {
3406 } else if (*String
== L
'&') {
3408 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3409 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3415 Find the point in the ConfigResp string for this question.
3417 @param Question The question.
3418 @param ConfigResp Get ConfigResp string.
3420 @retval point to the offset where is for this question.
3424 GetOffsetFromConfigResp (
3425 IN FORM_BROWSER_STATEMENT
*Question
,
3426 IN CHAR16
*ConfigResp
3429 CHAR16
*RequestElement
;
3433 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3435 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3436 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3437 if (RequestElement
!= NULL
) {
3439 // Skip the "VariableName=" field.
3441 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3444 return RequestElement
;
3448 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3452 // 1. Directly use Question->BlockName to find.
3454 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3455 if (RequestElement
!= NULL
) {
3457 // Skip the "Question->BlockName&VALUE=" field.
3459 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3460 return RequestElement
;
3464 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3466 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3467 ASSERT (BlockData
!= NULL
);
3468 HiiToLower (BlockData
);
3469 RequestElement
= StrStr (ConfigResp
, BlockData
);
3470 FreePool (BlockData
);
3472 if (RequestElement
!= NULL
) {
3474 // Skip the "Question->BlockName&VALUE=" field.
3476 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3479 return RequestElement
;
3483 Get Question default value from AltCfg string.
3485 @param FormSet The form set.
3486 @param Form The form
3487 @param Question The question.
3489 @retval EFI_SUCCESS Question is reset to default value.
3493 GetDefaultValueFromAltCfg (
3494 IN FORM_BROWSER_FORMSET
*FormSet
,
3495 IN FORM_BROWSER_FORM
*Form
,
3496 IN OUT FORM_BROWSER_STATEMENT
*Question
3499 BROWSER_STORAGE
*Storage
;
3500 FORMSET_STORAGE
*FormSetStorage
;
3504 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3506 Storage
= Question
->Storage
;
3507 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3508 return EFI_NOT_FOUND
;
3512 // Try to get AltCfg string from form. If not found it, then
3513 // try to get it from formset.
3516 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3517 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3518 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3519 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3521 if (Storage
== ConfigInfo
->Storage
) {
3522 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3527 if (ConfigResp
== NULL
) {
3528 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3529 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3530 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3531 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3533 if (Storage
== FormSetStorage
->BrowserStorage
) {
3534 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3540 if (ConfigResp
== NULL
) {
3541 return EFI_NOT_FOUND
;
3544 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3545 if (Value
== NULL
) {
3546 return EFI_NOT_FOUND
;
3549 return BufferToValue (Question
, Value
);
3553 Get default Id value used for browser.
3555 @param DefaultId The default id value used by hii.
3557 @retval Browser used default value.
3561 GetDefaultIdForCallBack (
3565 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3566 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3567 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3568 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3569 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3570 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3571 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3572 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3573 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3574 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3575 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3576 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3585 Return data element in an Array by its Index.
3587 @param Array The data array.
3588 @param Type Type of the data in this array.
3589 @param Index Zero based index for data in this array.
3591 @retval Value The data to be returned
3603 ASSERT (Array
!= NULL
);
3607 case EFI_IFR_TYPE_NUM_SIZE_8
:
3608 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3611 case EFI_IFR_TYPE_NUM_SIZE_16
:
3612 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3615 case EFI_IFR_TYPE_NUM_SIZE_32
:
3616 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3619 case EFI_IFR_TYPE_NUM_SIZE_64
:
3620 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3632 Set value of a data element in an Array by its Index.
3634 @param Array The data array.
3635 @param Type Type of the data in this array.
3636 @param Index Zero based index for data in this array.
3637 @param Value The value to be set.
3649 ASSERT (Array
!= NULL
);
3652 case EFI_IFR_TYPE_NUM_SIZE_8
:
3653 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3656 case EFI_IFR_TYPE_NUM_SIZE_16
:
3657 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3660 case EFI_IFR_TYPE_NUM_SIZE_32
:
3661 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3664 case EFI_IFR_TYPE_NUM_SIZE_64
:
3665 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3674 Search an Option of a Question by its value.
3676 @param Question The Question
3677 @param OptionValue Value for Option to be searched.
3679 @retval Pointer Pointer to the found Option.
3680 @retval NULL Option not found.
3685 IN FORM_BROWSER_STATEMENT
*Question
,
3686 IN EFI_HII_VALUE
*OptionValue
3690 QUESTION_OPTION
*Option
;
3693 Link
= GetFirstNode (&Question
->OptionListHead
);
3694 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3695 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3697 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3699 // Check the suppressif condition, only a valid option can be return.
3701 if ((Option
->SuppressExpression
== NULL
) ||
3702 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3707 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3715 Reset Question to its default value.
3717 @param FormSet The form set.
3718 @param Form The form.
3719 @param Question The question.
3720 @param DefaultId The Class of the default.
3722 @retval EFI_SUCCESS Question is reset to default value.
3726 GetQuestionDefault (
3727 IN FORM_BROWSER_FORMSET
*FormSet
,
3728 IN FORM_BROWSER_FORM
*Form
,
3729 IN FORM_BROWSER_STATEMENT
*Question
,
3735 QUESTION_DEFAULT
*Default
;
3736 QUESTION_OPTION
*Option
;
3737 EFI_HII_VALUE
*HiiValue
;
3739 EFI_STRING StrValue
;
3740 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3741 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3745 Status
= EFI_NOT_FOUND
;
3749 // Statement don't have storage, skip them
3751 if (Question
->QuestionId
== 0) {
3756 // There are Five ways to specify default value for a Question:
3757 // 1, use call back function (highest priority)
3758 // 2, use ExtractConfig function
3759 // 3, use nested EFI_IFR_DEFAULT
3760 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3761 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3763 HiiValue
= &Question
->HiiValue
;
3766 // Get Question defaut value from call back function.
3768 ConfigAccess
= FormSet
->ConfigAccess
;
3769 Action
= GetDefaultIdForCallBack (DefaultId
);
3770 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3771 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3772 Status
= ConfigAccess
->Callback (
3775 Question
->QuestionId
,
3780 if (!EFI_ERROR (Status
)) {
3781 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3782 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3783 ASSERT (NewString
!= NULL
);
3785 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3786 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3787 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3789 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3792 FreePool (NewString
);
3799 // Get default value from altcfg string.
3801 if (ConfigAccess
!= NULL
) {
3802 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
3803 if (!EFI_ERROR (Status
)) {
3809 // EFI_IFR_DEFAULT has highest priority
3811 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3812 Link
= GetFirstNode (&Question
->DefaultListHead
);
3813 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3814 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3816 if (Default
->DefaultId
== DefaultId
) {
3817 if (Default
->ValueExpression
!= NULL
) {
3819 // Default is provided by an Expression, evaluate it
3821 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3822 if (EFI_ERROR (Status
)) {
3826 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3827 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3828 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3829 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3830 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3832 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3833 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3835 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3837 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3838 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3841 // Default value is embedded in EFI_IFR_DEFAULT
3843 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3846 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3847 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3848 if (StrValue
== NULL
) {
3849 return EFI_NOT_FOUND
;
3851 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3852 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3854 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3861 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3866 // EFI_ONE_OF_OPTION
3868 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3869 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3871 // OneOfOption could only provide Standard and Manufacturing default
3873 Link
= GetFirstNode (&Question
->OptionListHead
);
3874 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3875 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3876 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3878 if ((Option
->SuppressExpression
!= NULL
) &&
3879 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3883 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3884 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3886 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3895 // EFI_IFR_CHECKBOX - lowest priority
3897 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3898 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3900 // Checkbox could only provide Standard and Manufacturing default
3902 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3903 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3905 HiiValue
->Value
.b
= TRUE
;
3907 HiiValue
->Value
.b
= FALSE
;
3915 // For Questions without default
3917 Status
= EFI_NOT_FOUND
;
3918 switch (Question
->Operand
) {
3919 case EFI_IFR_NUMERIC_OP
:
3921 // Take minimum value as numeric default value
3923 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3924 HiiValue
->Value
.u64
= Question
->Minimum
;
3925 Status
= EFI_SUCCESS
;
3929 case EFI_IFR_ONE_OF_OP
:
3931 // Take first oneof option as oneof's default value
3933 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3934 Link
= GetFirstNode (&Question
->OptionListHead
);
3935 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3936 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3937 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3939 if ((Option
->SuppressExpression
!= NULL
) &&
3940 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3944 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3945 Status
= EFI_SUCCESS
;
3951 case EFI_IFR_ORDERED_LIST_OP
:
3953 // Take option sequence in IFR as ordered list's default value
3956 Link
= GetFirstNode (&Question
->OptionListHead
);
3957 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3958 Status
= EFI_SUCCESS
;
3959 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3960 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3962 if ((Option
->SuppressExpression
!= NULL
) &&
3963 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3967 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3970 if (Index
>= Question
->MaxContainers
) {
3984 Get AltCfg string for current form.
3986 @param FormSet Form data structure.
3987 @param Form Form data structure.
3988 @param DefaultId The Class of the default.
3989 @param BrowserStorage The input request storage for the questions.
3993 ExtractAltCfgForForm (
3994 IN FORM_BROWSER_FORMSET
*FormSet
,
3995 IN FORM_BROWSER_FORM
*Form
,
3996 IN UINT16 DefaultId
,
3997 IN BROWSER_STORAGE
*BrowserStorage
4005 BROWSER_STORAGE
*Storage
;
4006 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4007 FORMSET_STORAGE
*FormSetStorage
;
4010 // Check whether has get AltCfg string for this formset.
4011 // If yes, no need to get AltCfg for form.
4013 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4014 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4015 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4016 Storage
= FormSetStorage
->BrowserStorage
;
4017 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4018 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4022 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4023 FormSetStorage
->ElementCount
!= 0 &&
4024 FormSetStorage
->HasCallAltCfg
) {
4030 // Get AltCfg string for each form.
4032 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4033 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4034 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4035 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4037 Storage
= ConfigInfo
->Storage
;
4038 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4042 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4047 // 1. Skip if there is no RequestElement
4049 if (ConfigInfo
->ElementCount
== 0) {
4054 // 2. Get value through hii config routine protocol.
4056 Status
= mHiiConfigRouting
->ExtractConfig (
4058 ConfigInfo
->ConfigRequest
,
4062 if (EFI_ERROR (Status
)) {
4067 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4068 // Get the default configuration string according to the default ID.
4070 Status
= mHiiConfigRouting
->GetAltConfig (
4076 &DefaultId
, // it can be NULL to get the current setting.
4080 if (EFI_ERROR (Status
)) {
4084 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4089 Clean AltCfg string for current form.
4091 @param Form Form data structure.
4095 CleanAltCfgForForm (
4096 IN FORM_BROWSER_FORM
*Form
4100 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4102 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4103 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4104 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4105 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4107 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4108 FreePool (ConfigInfo
->ConfigAltResp
);
4109 ConfigInfo
->ConfigAltResp
= NULL
;
4115 Get AltCfg string for current formset.
4117 @param FormSet Form data structure.
4118 @param DefaultId The Class of the default.
4119 @param BrowserStorage The input request storage for the questions.
4123 ExtractAltCfgForFormSet (
4124 IN FORM_BROWSER_FORMSET
*FormSet
,
4125 IN UINT16 DefaultId
,
4126 IN BROWSER_STORAGE
*BrowserStorage
4134 BROWSER_STORAGE
*Storage
;
4135 FORMSET_STORAGE
*FormSetStorage
;
4137 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4138 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4139 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4140 Storage
= FormSetStorage
->BrowserStorage
;
4141 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4143 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4147 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4152 // 1. Skip if there is no RequestElement
4154 if (FormSetStorage
->ElementCount
== 0) {
4158 FormSetStorage
->HasCallAltCfg
= TRUE
;
4161 // 2. Get value through hii config routine protocol.
4163 Status
= mHiiConfigRouting
->ExtractConfig (
4165 FormSetStorage
->ConfigRequest
,
4169 if (EFI_ERROR (Status
)) {
4174 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4175 // Get the default configuration string according to the default ID.
4177 Status
= mHiiConfigRouting
->GetAltConfig (
4183 &DefaultId
, // it can be NULL to get the current setting.
4188 if (EFI_ERROR (Status
)) {
4192 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4198 Clean AltCfg string for current formset.
4200 @param FormSet Form data structure.
4204 CleanAltCfgForFormSet (
4205 IN FORM_BROWSER_FORMSET
*FormSet
4209 FORMSET_STORAGE
*FormSetStorage
;
4211 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4212 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4213 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4214 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4216 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4217 FreePool (FormSetStorage
->ConfigAltResp
);
4218 FormSetStorage
->ConfigAltResp
= NULL
;
4221 FormSetStorage
->HasCallAltCfg
= FALSE
;
4226 Reset Questions to their initial value or default value in a Form, Formset or System.
4228 GetDefaultValueScope parameter decides which questions will reset
4229 to its default value.
4231 @param FormSet FormSet data structure.
4232 @param Form Form data structure.
4233 @param DefaultId The Class of the default.
4234 @param SettingScope Setting Scope for Default action.
4235 @param GetDefaultValueScope Get default value scope.
4236 @param Storage Get default value only for this storage.
4237 @param RetrieveValueFirst Whether call the retrieve call back to
4238 get the initial value before get default
4240 @param SkipGetAltCfg Whether skip the get altcfg string process.
4242 @retval EFI_SUCCESS The function completed successfully.
4243 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4248 IN FORM_BROWSER_FORMSET
*FormSet
,
4249 IN FORM_BROWSER_FORM
*Form
,
4250 IN UINT16 DefaultId
,
4251 IN BROWSER_SETTING_SCOPE SettingScope
,
4252 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4253 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4254 IN BOOLEAN RetrieveValueFirst
,
4255 IN BOOLEAN SkipGetAltCfg
4259 LIST_ENTRY
*FormLink
;
4261 FORM_BROWSER_STATEMENT
*Question
;
4262 FORM_BROWSER_FORMSET
*LocalFormSet
;
4263 FORM_BROWSER_FORMSET
*OldFormSet
;
4265 Status
= EFI_SUCCESS
;
4268 // Check the supported setting level.
4270 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4271 return EFI_UNSUPPORTED
;
4274 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4275 return EFI_UNSUPPORTED
;
4278 if (SettingScope
== FormLevel
) {
4280 // Prepare the AltCfg String for form.
4282 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4283 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4287 // Extract Form default
4289 Link
= GetFirstNode (&Form
->StatementListHead
);
4290 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4291 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4292 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4295 // If get default value only for this storage, check the storage first.
4297 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4302 // If get default value only for no storage question, just skip the question which has storage.
4304 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4309 // If Question is disabled, don't reset it to default
4311 if (Question
->Expression
!= NULL
) {
4312 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4317 if (RetrieveValueFirst
) {
4319 // Call the Retrieve call back to get the initial question value.
4321 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4325 // If not request to get the initial value or get initial value fail, then get default value.
4327 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4328 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4329 if (EFI_ERROR (Status
)) {
4335 // Synchronize Buffer storage's Edit buffer
4337 if ((Question
->Storage
!= NULL
) &&
4338 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4339 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4344 // Clean the AltCfg String.
4346 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4347 CleanAltCfgForForm(Form
);
4349 } else if (SettingScope
== FormSetLevel
) {
4351 // Prepare the AltCfg String for formset.
4353 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4354 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4357 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4358 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4359 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4360 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4361 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4365 // Clean the AltCfg String.
4367 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4368 CleanAltCfgForFormSet (FormSet
);
4370 } else if (SettingScope
== SystemLevel
) {
4372 // Preload all Hii formset.
4374 LoadAllHiiFormset();
4376 OldFormSet
= mSystemLevelFormSet
;
4379 // Set Default Value for each FormSet in the maintain list.
4381 Link
= GetFirstNode (&gBrowserFormSetList
);
4382 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4383 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4384 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4385 if (!ValidateFormSet(LocalFormSet
)) {
4389 mSystemLevelFormSet
= LocalFormSet
;
4391 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4394 mSystemLevelFormSet
= OldFormSet
;
4402 Validate whether this question's value has changed.
4404 @param FormSet FormSet data structure.
4405 @param Form Form data structure.
4406 @param Question Question to be initialized.
4407 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4409 @retval TRUE Question's value has changed.
4410 @retval FALSE Question's value has not changed
4414 IsQuestionValueChanged (
4415 IN FORM_BROWSER_FORMSET
*FormSet
,
4416 IN FORM_BROWSER_FORM
*Form
,
4417 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4418 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4421 EFI_HII_VALUE BackUpValue
;
4422 CHAR8
*BackUpBuffer
;
4423 EFI_HII_VALUE BackUpValue2
;
4424 CHAR8
*BackUpBuffer2
;
4426 BOOLEAN ValueChanged
;
4430 // For quetion without storage, always mark it as data not changed.
4432 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4436 BackUpBuffer
= NULL
;
4437 BackUpBuffer2
= NULL
;
4438 ValueChanged
= FALSE
;
4440 switch (Question
->Operand
) {
4441 case EFI_IFR_ORDERED_LIST_OP
:
4442 BufferWidth
= Question
->StorageWidth
;
4443 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4444 ASSERT (BackUpBuffer
!= NULL
);
4447 case EFI_IFR_STRING_OP
:
4448 case EFI_IFR_PASSWORD_OP
:
4449 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4450 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4451 ASSERT (BackUpBuffer
!= NULL
);
4458 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4460 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4461 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4462 ASSERT_EFI_ERROR(Status
);
4464 switch (Question
->Operand
) {
4465 case EFI_IFR_ORDERED_LIST_OP
:
4466 BufferWidth
= Question
->StorageWidth
;
4467 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4468 ASSERT (BackUpBuffer2
!= NULL
);
4471 case EFI_IFR_STRING_OP
:
4472 case EFI_IFR_PASSWORD_OP
:
4473 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4474 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4475 ASSERT (BackUpBuffer2
!= NULL
);
4482 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4484 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4485 ASSERT_EFI_ERROR(Status
);
4487 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4488 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4489 ValueChanged
= TRUE
;
4492 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4493 ASSERT_EFI_ERROR(Status
);
4495 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4496 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4497 ValueChanged
= TRUE
;
4501 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4502 if (BackUpBuffer
!= NULL
) {
4503 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4504 FreePool (BackUpBuffer
);
4507 if (BackUpBuffer2
!= NULL
) {
4508 FreePool (BackUpBuffer2
);
4511 Question
->ValueChanged
= ValueChanged
;
4513 return ValueChanged
;
4517 Initialize Question's Edit copy from Storage.
4519 @param Selection Selection contains the information about
4520 the Selection, form and formset to be displayed.
4521 Selection action may be updated in retrieve callback.
4522 If Selection is NULL, only initialize Question value.
4523 @param FormSet FormSet data structure.
4524 @param Form Form data structure.
4526 @retval EFI_SUCCESS The function completed successfully.
4531 IN OUT UI_MENU_SELECTION
*Selection
,
4532 IN FORM_BROWSER_FORMSET
*FormSet
,
4533 IN FORM_BROWSER_FORM
*Form
4538 FORM_BROWSER_STATEMENT
*Question
;
4540 Link
= GetFirstNode (&Form
->StatementListHead
);
4541 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4542 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4545 // Initialize local copy of Value for each Question
4547 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4548 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4550 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4552 if (EFI_ERROR (Status
)) {
4556 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4557 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4560 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4567 Initialize Question's Edit copy from Storage for the whole Formset.
4569 @param Selection Selection contains the information about
4570 the Selection, form and formset to be displayed.
4571 Selection action may be updated in retrieve callback.
4572 If Selection is NULL, only initialize Question value.
4573 @param FormSet FormSet data structure.
4575 @retval EFI_SUCCESS The function completed successfully.
4580 IN OUT UI_MENU_SELECTION
*Selection
,
4581 IN FORM_BROWSER_FORMSET
*FormSet
4586 FORM_BROWSER_FORM
*Form
;
4588 Link
= GetFirstNode (&FormSet
->FormListHead
);
4589 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4590 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4593 // Initialize local copy of Value for each Form
4595 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4596 if (EFI_ERROR (Status
)) {
4600 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4604 // Finished question initialization.
4606 FormSet
->QuestionInited
= TRUE
;
4612 Remove the Request element from the Config Request.
4614 @param Storage Pointer to the browser storage.
4615 @param RequestElement The pointer to the Request element.
4620 IN OUT BROWSER_STORAGE
*Storage
,
4621 IN CHAR16
*RequestElement
4627 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4629 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4631 if (NewStr
== NULL
) {
4636 // Remove this element from this ConfigRequest.
4639 NewStr
+= StrLen (RequestElement
);
4640 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4642 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4646 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4648 @param Storage Pointer to the browser storage.
4649 @param ConfigRequest The pointer to the Request element.
4653 RemoveConfigRequest (
4654 BROWSER_STORAGE
*Storage
,
4655 CHAR16
*ConfigRequest
4658 CHAR16
*RequestElement
;
4659 CHAR16
*NextRequestElement
;
4663 // No request element in it, just return.
4665 if (ConfigRequest
== NULL
) {
4669 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4671 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4676 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4678 SearchKey
= L
"&OFFSET";
4682 // Find SearchKey storage
4684 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4685 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4686 ASSERT (RequestElement
!= NULL
);
4687 RequestElement
= StrStr (RequestElement
, SearchKey
);
4689 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4692 while (RequestElement
!= NULL
) {
4694 // +1 to avoid find header itself.
4696 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4699 // The last Request element in configRequest string.
4701 if (NextRequestElement
!= NULL
) {
4703 // Replace "&" with '\0'.
4705 *NextRequestElement
= L
'\0';
4708 RemoveElement (Storage
, RequestElement
);
4710 if (NextRequestElement
!= NULL
) {
4712 // Restore '&' with '\0' for later used.
4714 *NextRequestElement
= L
'&';
4717 RequestElement
= NextRequestElement
;
4721 // If no request element remain, just remove the ConfigRequest string.
4723 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4724 FreePool (Storage
->ConfigRequest
);
4725 Storage
->ConfigRequest
= NULL
;
4726 Storage
->SpareStrLen
= 0;
4731 Base on the current formset info, clean the ConfigRequest string in browser storage.
4733 @param FormSet Pointer of the FormSet
4737 CleanBrowserStorage (
4738 IN OUT FORM_BROWSER_FORMSET
*FormSet
4742 FORMSET_STORAGE
*Storage
;
4744 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4745 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4746 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4747 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4749 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4750 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4754 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4755 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4756 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4757 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4758 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4759 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4761 Storage
->BrowserStorage
->Initialized
= FALSE
;
4767 Check whether current element in the ConfigReqeust string.
4769 @param BrowserStorage Storage which includes ConfigReqeust.
4770 @param RequestElement New element need to check.
4772 @retval TRUE The Element is in the ConfigReqeust string.
4773 @retval FALSE The Element not in the configReqeust String.
4778 BROWSER_STORAGE
*BrowserStorage
,
4779 CHAR16
*RequestElement
4782 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4786 Append the Request element to the Config Request.
4788 @param ConfigRequest Current ConfigRequest info.
4789 @param SpareStrLen Current remain free buffer for config reqeust.
4790 @param RequestElement New Request element.
4794 AppendConfigRequest (
4795 IN OUT CHAR16
**ConfigRequest
,
4796 IN OUT UINTN
*SpareStrLen
,
4797 IN CHAR16
*RequestElement
4804 StrLength
= StrLen (RequestElement
);
4807 // Append <RequestElement> to <ConfigRequest>
4809 if (StrLength
> *SpareStrLen
) {
4811 // Old String buffer is not sufficient for RequestElement, allocate a new one
4813 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4814 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4815 ASSERT (NewStr
!= NULL
);
4817 if (*ConfigRequest
!= NULL
) {
4818 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4819 FreePool (*ConfigRequest
);
4821 *ConfigRequest
= NewStr
;
4822 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4825 StrCat (*ConfigRequest
, RequestElement
);
4826 *SpareStrLen
-= StrLength
;
4830 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4832 @param Storage Form set Storage.
4833 @param Request The input request string.
4834 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4836 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4837 @retval FALSE All elements covered by current used elements.
4841 ConfigRequestAdjust (
4842 IN BROWSER_STORAGE
*Storage
,
4844 IN BOOLEAN RespString
4847 CHAR16
*RequestElement
;
4848 CHAR16
*NextRequestElement
;
4849 CHAR16
*NextElementBakup
;
4853 CHAR16
*ConfigRequest
;
4856 NextElementBakup
= NULL
;
4859 if (Request
!= NULL
) {
4860 ConfigRequest
= Request
;
4862 ConfigRequest
= Storage
->ConfigRequest
;
4865 if (Storage
->ConfigRequest
== NULL
) {
4866 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4870 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4872 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4877 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4879 SearchKey
= L
"&OFFSET";
4880 ValueKey
= L
"&VALUE";
4884 // Find SearchKey storage
4886 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4887 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4888 ASSERT (RequestElement
!= NULL
);
4889 RequestElement
= StrStr (RequestElement
, SearchKey
);
4891 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4894 while (RequestElement
!= NULL
) {
4897 // +1 to avoid find header itself.
4899 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4902 // The last Request element in configRequest string.
4904 if (NextRequestElement
!= NULL
) {
4905 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4906 NextElementBakup
= NextRequestElement
;
4907 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4908 ASSERT (NextRequestElement
!= NULL
);
4911 // Replace "&" with '\0'.
4913 *NextRequestElement
= L
'\0';
4915 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4916 NextElementBakup
= NextRequestElement
;
4917 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4918 ASSERT (NextRequestElement
!= NULL
);
4920 // Replace "&" with '\0'.
4922 *NextRequestElement
= L
'\0';
4926 if (!ElementValidation (Storage
, RequestElement
)) {
4928 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4930 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4934 if (NextRequestElement
!= NULL
) {
4936 // Restore '&' with '\0' for later used.
4938 *NextRequestElement
= L
'&';
4941 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4942 RequestElement
= NextElementBakup
;
4944 RequestElement
= NextRequestElement
;
4952 Fill storage's edit copy with settings requested from Configuration Driver.
4954 @param FormSet FormSet data structure.
4955 @param Storage Buffer Storage.
4960 IN FORM_BROWSER_FORMSET
*FormSet
,
4961 IN FORMSET_STORAGE
*Storage
4965 EFI_STRING Progress
;
4968 EFI_STRING ConfigRequest
;
4971 ConfigRequest
= NULL
;
4973 switch (Storage
->BrowserStorage
->Type
) {
4974 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4977 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4978 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4979 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4984 case EFI_HII_VARSTORE_BUFFER
:
4985 case EFI_HII_VARSTORE_NAME_VALUE
:
4987 // Skip if there is no RequestElement.
4989 if (Storage
->ElementCount
== 0) {
4994 // Just update the ConfigRequest, if storage already initialized.
4996 if (Storage
->BrowserStorage
->Initialized
) {
4997 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5001 Storage
->BrowserStorage
->Initialized
= TRUE
;
5008 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5010 // Create the config request string to get all fields for this storage.
5011 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5012 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5014 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5015 ConfigRequest
= AllocateZeroPool (StrLen
);
5016 ASSERT (ConfigRequest
!= NULL
);
5020 L
"%s&OFFSET=0&WIDTH=%04x",
5021 Storage
->BrowserStorage
->ConfigHdr
,
5022 Storage
->BrowserStorage
->Size
);
5024 ConfigRequest
= Storage
->ConfigRequest
;
5028 // Request current settings from Configuration Driver
5030 Status
= mHiiConfigRouting
->ExtractConfig (
5038 // If get value fail, extract default from IFR binary
5040 if (EFI_ERROR (Status
)) {
5041 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5044 // Convert Result from <ConfigAltResp> to <ConfigResp>
5046 StrPtr
= StrStr (Result
, L
"&GUID=");
5047 if (StrPtr
!= NULL
) {
5051 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5055 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5058 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5060 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5062 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5063 if (ConfigRequest
!= NULL
) {
5064 FreePool (ConfigRequest
);
5070 Get Value changed status from old question.
5072 @param NewFormSet FormSet data structure.
5073 @param OldQuestion Old question which has value changed.
5077 SyncStatusForQuestion (
5078 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5079 IN FORM_BROWSER_STATEMENT
*OldQuestion
5083 LIST_ENTRY
*QuestionLink
;
5084 FORM_BROWSER_FORM
*Form
;
5085 FORM_BROWSER_STATEMENT
*Question
;
5088 // For each form in one formset.
5090 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5091 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5092 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5093 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5096 // for each question in one form.
5098 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5099 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5100 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5101 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5103 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5104 Question
->ValueChanged
= TRUE
;
5112 Get Value changed status from old formset.
5114 @param NewFormSet FormSet data structure.
5115 @param OldFormSet FormSet data structure.
5119 SyncStatusForFormSet (
5120 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5121 IN FORM_BROWSER_FORMSET
*OldFormSet
5125 LIST_ENTRY
*QuestionLink
;
5126 FORM_BROWSER_FORM
*Form
;
5127 FORM_BROWSER_STATEMENT
*Question
;
5130 // For each form in one formset.
5132 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5133 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5134 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5135 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5138 // for each question in one form.
5140 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5141 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5142 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5143 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5145 if (!Question
->ValueChanged
) {
5150 // Find the same question in new formset and update the value changed flag.
5152 SyncStatusForQuestion (NewFormSet
, Question
);
5158 Get current setting of Questions.
5160 @param FormSet FormSet data structure.
5164 InitializeCurrentSetting (
5165 IN OUT FORM_BROWSER_FORMSET
*FormSet
5169 FORMSET_STORAGE
*Storage
;
5170 FORM_BROWSER_FORMSET
*OldFormSet
;
5173 // Try to find pre FormSet in the maintain backup list.
5174 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5176 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5177 if (OldFormSet
!= NULL
) {
5178 SyncStatusForFormSet (FormSet
, OldFormSet
);
5179 RemoveEntryList (&OldFormSet
->Link
);
5180 DestroyFormSet (OldFormSet
);
5182 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5185 // Extract default from IFR binary for no storage questions.
5187 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5190 // Request current settings from Configuration Driver
5192 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5193 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5194 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5196 LoadStorage (FormSet
, Storage
);
5198 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5204 Fetch the Ifr binary data of a FormSet.
5206 @param Handle PackageList Handle
5207 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5208 specified (NULL or zero GUID), take the first
5209 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5210 found in package list.
5211 On output, GUID of the formset found(if not NULL).
5212 @param BinaryLength The length of the FormSet IFR binary.
5213 @param BinaryData The buffer designed to receive the FormSet.
5215 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5216 BufferLength was updated.
5217 @retval EFI_INVALID_PARAMETER The handle is unknown.
5218 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5219 be found with the requested FormId.
5224 IN EFI_HII_HANDLE Handle
,
5225 IN OUT EFI_GUID
*FormSetGuid
,
5226 OUT UINTN
*BinaryLength
,
5227 OUT UINT8
**BinaryData
5231 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5237 UINT32 PackageListLength
;
5238 EFI_HII_PACKAGE_HEADER PackageHeader
;
5240 UINT8 NumberOfClassGuid
;
5241 BOOLEAN ClassGuidMatch
;
5242 EFI_GUID
*ClassGuid
;
5243 EFI_GUID
*ComparingGuid
;
5247 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5250 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5252 if (FormSetGuid
== NULL
) {
5253 ComparingGuid
= &gZeroGuid
;
5255 ComparingGuid
= FormSetGuid
;
5259 // Get HII PackageList
5262 HiiPackageList
= NULL
;
5263 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5264 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5265 HiiPackageList
= AllocatePool (BufferSize
);
5266 ASSERT (HiiPackageList
!= NULL
);
5268 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5270 if (EFI_ERROR (Status
)) {
5273 ASSERT (HiiPackageList
!= NULL
);
5276 // Get Form package from this HII package List
5278 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5280 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5282 ClassGuidMatch
= FALSE
;
5283 while (Offset
< PackageListLength
) {
5284 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5285 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5287 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5289 // Search FormSet in this Form Package
5291 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5292 while (Offset2
< PackageHeader
.Length
) {
5293 OpCodeData
= Package
+ Offset2
;
5295 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5297 // Try to compare against formset GUID
5299 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5300 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5304 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5306 // Try to compare against formset class GUID
5308 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5309 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5310 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5311 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5312 ClassGuidMatch
= TRUE
;
5316 if (ClassGuidMatch
) {
5319 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5320 ClassGuidMatch
= TRUE
;
5325 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5328 if (Offset2
< PackageHeader
.Length
) {
5330 // Target formset found
5336 Offset
+= PackageHeader
.Length
;
5339 if (Offset
>= PackageListLength
) {
5341 // Form package not found in this Package List
5343 FreePool (HiiPackageList
);
5344 return EFI_NOT_FOUND
;
5347 if (FormSetGuid
!= NULL
) {
5349 // Return the FormSet GUID
5351 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5355 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5356 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5357 // of the Form Package.
5359 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5360 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5362 FreePool (HiiPackageList
);
5364 if (*BinaryData
== NULL
) {
5365 return EFI_OUT_OF_RESOURCES
;
5373 Initialize the internal data structure of a FormSet.
5375 @param Handle PackageList Handle
5376 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5377 specified (NULL or zero GUID), take the first
5378 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5379 found in package list.
5380 On output, GUID of the formset found(if not NULL).
5381 @param FormSet FormSet data structure.
5383 @retval EFI_SUCCESS The function completed successfully.
5384 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5389 IN EFI_HII_HANDLE Handle
,
5390 IN OUT EFI_GUID
*FormSetGuid
,
5391 OUT FORM_BROWSER_FORMSET
*FormSet
5395 EFI_HANDLE DriverHandle
;
5397 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5398 if (EFI_ERROR (Status
)) {
5402 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5403 FormSet
->HiiHandle
= Handle
;
5404 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5405 FormSet
->QuestionInited
= FALSE
;
5408 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5410 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5411 if (EFI_ERROR (Status
)) {
5414 FormSet
->DriverHandle
= DriverHandle
;
5415 Status
= gBS
->HandleProtocol (
5417 &gEfiHiiConfigAccessProtocolGuid
,
5418 (VOID
**) &FormSet
->ConfigAccess
5420 if (EFI_ERROR (Status
)) {
5422 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5423 // list, then there will be no configuration action required
5425 FormSet
->ConfigAccess
= NULL
;
5429 // Parse the IFR binary OpCodes
5431 Status
= ParseOpCodes (FormSet
);
5438 Save globals used by previous call to SendForm(). SendForm() may be called from
5439 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5440 So, save globals of previous call to SendForm() and restore them upon exit.
5444 SaveBrowserContext (
5448 BROWSER_CONTEXT
*Context
;
5449 FORM_ENTRY_INFO
*MenuList
;
5451 gBrowserContextCount
++;
5452 if (gBrowserContextCount
== 1) {
5454 // This is not reentry of SendForm(), no context to save
5459 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5460 ASSERT (Context
!= NULL
);
5462 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5465 // Save FormBrowser context
5467 Context
->Selection
= gCurrentSelection
;
5468 Context
->ResetRequired
= gResetRequired
;
5469 Context
->ExitRequired
= gExitRequired
;
5470 Context
->HiiHandle
= mCurrentHiiHandle
;
5471 Context
->FormId
= mCurrentFormId
;
5472 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5475 // Save the menu history data.
5477 InitializeListHead(&Context
->FormHistoryList
);
5478 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5479 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5480 RemoveEntryList (&MenuList
->Link
);
5482 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5486 // Insert to FormBrowser context list
5488 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5493 Restore globals used by previous call to SendForm().
5497 RestoreBrowserContext (
5502 BROWSER_CONTEXT
*Context
;
5503 FORM_ENTRY_INFO
*MenuList
;
5505 ASSERT (gBrowserContextCount
!= 0);
5506 gBrowserContextCount
--;
5507 if (gBrowserContextCount
== 0) {
5509 // This is not reentry of SendForm(), no context to restore
5514 ASSERT (!IsListEmpty (&gBrowserContextList
));
5516 Link
= GetFirstNode (&gBrowserContextList
);
5517 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5520 // Restore FormBrowser context
5522 gCurrentSelection
= Context
->Selection
;
5523 gResetRequired
= Context
->ResetRequired
;
5524 gExitRequired
= Context
->ExitRequired
;
5525 mCurrentHiiHandle
= Context
->HiiHandle
;
5526 mCurrentFormId
= Context
->FormId
;
5527 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5530 // Restore the menu history data.
5532 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5533 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5534 RemoveEntryList (&MenuList
->Link
);
5536 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5540 // Remove from FormBrowser context list
5542 RemoveEntryList (&Context
->Link
);
5543 gBS
->FreePool (Context
);
5547 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5549 @param Handle The Hii Handle.
5551 @return the found FormSet context. If no found, NULL will return.
5554 FORM_BROWSER_FORMSET
*
5555 GetFormSetFromHiiHandle (
5556 EFI_HII_HANDLE Handle
5560 FORM_BROWSER_FORMSET
*FormSet
;
5562 Link
= GetFirstNode (&gBrowserFormSetList
);
5563 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5564 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5565 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5566 if (!ValidateFormSet(FormSet
)) {
5569 if (FormSet
->HiiHandle
== Handle
) {
5578 Check whether the input HII handle is the FormSet that is being used.
5580 @param Handle The Hii Handle.
5582 @retval TRUE HII handle is being used.
5583 @retval FALSE HII handle is not being used.
5587 IsHiiHandleInBrowserContext (
5588 EFI_HII_HANDLE Handle
5592 BROWSER_CONTEXT
*Context
;
5595 // HiiHandle is Current FormSet.
5597 if (mCurrentHiiHandle
== Handle
) {
5602 // Check whether HiiHandle is in BrowserContext.
5604 Link
= GetFirstNode (&gBrowserContextList
);
5605 while (!IsNull (&gBrowserContextList
, Link
)) {
5606 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5607 if (Context
->HiiHandle
== Handle
) {
5609 // HiiHandle is in BrowserContext
5613 Link
= GetNextNode (&gBrowserContextList
, Link
);
5620 Perform Password check.
5621 Passwork may be encrypted by driver that requires the specific check.
5623 @param Form Form where Password Statement is in.
5624 @param Statement Password statement
5625 @param PasswordString Password string to be checked. It may be NULL.
5626 NULL means to restore password.
5627 "" string can be used to checked whether old password does exist.
5629 @return Status Status of Password check.
5634 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5635 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5636 IN EFI_STRING PasswordString OPTIONAL
5640 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5641 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5642 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5643 FORM_BROWSER_STATEMENT
*Question
;
5645 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5646 Question
= GetBrowserStatement(Statement
);
5647 ASSERT (Question
!= NULL
);
5649 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5650 if (ConfigAccess
== NULL
) {
5651 return EFI_UNSUPPORTED
;
5654 if (PasswordString
== NULL
) {
5659 // Check whether has preexisted password.
5661 if (PasswordString
[0] == 0) {
5662 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5665 return EFI_NOT_READY
;
5670 // Check whether the input password is same as preexisted password.
5672 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5675 return EFI_NOT_READY
;
5680 // Prepare password string in HII database
5682 if (PasswordString
!= NULL
) {
5683 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5685 IfrTypeValue
.string
= 0;
5689 // Send password to Configuration Driver for validation
5691 Status
= ConfigAccess
->Callback (
5693 EFI_BROWSER_ACTION_CHANGING
,
5694 Question
->QuestionId
,
5695 Question
->HiiValue
.Type
,
5701 // Remove password string from HII database
5703 if (PasswordString
!= NULL
) {
5704 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5711 Find the registered HotKey based on KeyData.
5713 @param[in] KeyData A pointer to a buffer that describes the keystroke
5714 information for the hot key.
5716 @return The registered HotKey context. If no found, NULL will return.
5719 GetHotKeyFromRegisterList (
5720 IN EFI_INPUT_KEY
*KeyData
5724 BROWSER_HOT_KEY
*HotKey
;
5726 Link
= GetFirstNode (&gBrowserHotKeyList
);
5727 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5728 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5729 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5732 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5739 Configure what scope the hot key will impact.
5740 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5741 If no scope is set, the default scope will be FormSet level.
5742 After all registered hot keys are removed, previous Scope can reset to another level.
5744 @param[in] Scope Scope level to be set.
5746 @retval EFI_SUCCESS Scope is set correctly.
5747 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5748 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5754 IN BROWSER_SETTING_SCOPE Scope
5757 if (Scope
>= MaxLevel
) {
5758 return EFI_INVALID_PARAMETER
;
5762 // When no hot key registered in system or on the first setting,
5763 // Scope can be set.
5765 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5766 gBrowserSettingScope
= Scope
;
5767 mBrowserScopeFirstSet
= FALSE
;
5768 } else if (Scope
!= gBrowserSettingScope
) {
5769 return EFI_UNSUPPORTED
;
5776 Register the hot key with its browser action, or unregistered the hot key.
5777 Only support hot key that is not printable character (control key, function key, etc.).
5778 If the action value is zero, the hot key will be unregistered if it has been registered.
5779 If the same hot key has been registered, the new action and help string will override the previous ones.
5781 @param[in] KeyData A pointer to a buffer that describes the keystroke
5782 information for the hot key. Its type is EFI_INPUT_KEY to
5783 be supported by all ConsoleIn devices.
5784 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5785 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5786 @param[in] HelpString Help string that describes the hot key information.
5787 Its value may be NULL for the unregistered hot key.
5789 @retval EFI_SUCCESS Hot key is registered or unregistered.
5790 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5791 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5792 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5797 IN EFI_INPUT_KEY
*KeyData
,
5799 IN UINT16 DefaultId
,
5800 IN EFI_STRING HelpString OPTIONAL
5803 BROWSER_HOT_KEY
*HotKey
;
5806 // Check input parameters.
5808 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5809 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5810 return EFI_INVALID_PARAMETER
;
5814 // Check whether the input KeyData is in BrowserHotKeyList.
5816 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5819 // Unregister HotKey
5821 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5822 if (HotKey
!= NULL
) {
5824 // The registered HotKey is found.
5825 // Remove it from List, and free its resource.
5827 RemoveEntryList (&HotKey
->Link
);
5828 FreePool (HotKey
->KeyData
);
5829 FreePool (HotKey
->HelpString
);
5833 // The registered HotKey is not found.
5835 return EFI_NOT_FOUND
;
5840 // Register HotKey into List.
5842 if (HotKey
== NULL
) {
5844 // Create new Key, and add it into List.
5846 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5847 ASSERT (HotKey
!= NULL
);
5848 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5849 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5850 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5854 // Fill HotKey information.
5856 HotKey
->Action
= Action
;
5857 HotKey
->DefaultId
= DefaultId
;
5858 if (HotKey
->HelpString
!= NULL
) {
5859 FreePool (HotKey
->HelpString
);
5861 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5867 Register Exit handler function.
5868 When more than one handler function is registered, the latter one will override the previous one.
5869 When NULL handler is specified, the previous Exit handler will be unregistered.
5871 @param[in] Handler Pointer to handler function.
5876 RegiserExitHandler (
5877 IN EXIT_HANDLER Handler
5880 ExitHandlerFunction
= Handler
;
5885 Check whether the browser data has been modified.
5887 @retval TRUE Browser data is modified.
5888 @retval FALSE No browser data is modified.
5893 IsBrowserDataModified (
5898 FORM_BROWSER_FORMSET
*FormSet
;
5900 switch (gBrowserSettingScope
) {
5902 if (gCurrentSelection
== NULL
) {
5905 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5908 if (gCurrentSelection
== NULL
) {
5911 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5914 Link
= GetFirstNode (&gBrowserFormSetList
);
5915 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5916 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5917 if (!ValidateFormSet(FormSet
)) {
5921 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5924 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5934 Execute the action requested by the Action parameter.
5936 @param[in] Action Execute the request action.
5937 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5939 @retval EFI_SUCCESS Execute the request action succss.
5940 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5951 FORM_BROWSER_FORMSET
*FormSet
;
5952 FORM_BROWSER_FORM
*Form
;
5954 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5955 return EFI_NOT_READY
;
5958 Status
= EFI_SUCCESS
;
5961 if (gBrowserSettingScope
< SystemLevel
) {
5962 FormSet
= gCurrentSelection
->FormSet
;
5963 Form
= gCurrentSelection
->Form
;
5967 // Executet the discard action.
5969 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5970 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5971 if (EFI_ERROR (Status
)) {
5977 // Executet the difault action.
5979 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5980 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
5981 if (EFI_ERROR (Status
)) {
5984 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5988 // Executet the submit action.
5990 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5991 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5992 if (EFI_ERROR (Status
)) {
5998 // Executet the reset action.
6000 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6001 gResetRequired
= TRUE
;
6005 // Executet the exit action.
6007 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6008 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6009 if (gBrowserSettingScope
== SystemLevel
) {
6010 if (ExitHandlerFunction
!= NULL
) {
6011 ExitHandlerFunction ();
6015 gExitRequired
= TRUE
;
6022 Create reminder to let user to choose save or discard the changed browser data.
6023 Caller can use it to actively check the changed browser data.
6025 @retval BROWSER_NO_CHANGES No browser data is changed.
6026 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6027 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6028 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6038 FORM_BROWSER_FORMSET
*FormSet
;
6039 BOOLEAN IsDataChanged
;
6040 UINT32 DataSavedAction
;
6043 DataSavedAction
= BROWSER_NO_CHANGES
;
6044 IsDataChanged
= FALSE
;
6045 Link
= GetFirstNode (&gBrowserFormSetList
);
6046 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6047 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6048 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6049 if (!ValidateFormSet(FormSet
)) {
6052 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6053 IsDataChanged
= TRUE
;
6059 // No data is changed. No save is required.
6061 if (!IsDataChanged
) {
6062 return DataSavedAction
;
6066 // If data is changed, prompt user to save or discard it.
6069 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6071 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6072 SubmitForm (NULL
, NULL
, SystemLevel
);
6073 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6075 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6076 DiscardForm (NULL
, NULL
, SystemLevel
);
6077 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6079 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6080 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6085 return DataSavedAction
;
6089 Check whether the Reset Required for the browser
6091 @retval TRUE Browser required to reset after exit.
6092 @retval FALSE Browser not need to reset after exit.
6101 return gResetRequired
;