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
210 @retval The parent menu for current menu.
214 IN FORM_ENTRY_INFO
*CurrentMenu
217 FORM_ENTRY_INFO
*ParentMenu
;
220 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
221 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
228 Free Menu list linked list.
230 @param MenuListHead One Menu list point in the menu list.
235 LIST_ENTRY
*MenuListHead
238 FORM_ENTRY_INFO
*MenuList
;
240 while (!IsListEmpty (MenuListHead
)) {
241 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
242 RemoveEntryList (&MenuList
->Link
);
249 Copy current Menu list to the new menu list.
251 @param NewMenuListHead New create Menu list.
252 @param CurrentMenuListHead Current Menu list.
257 OUT LIST_ENTRY
*NewMenuListHead
,
258 IN LIST_ENTRY
*CurrentMenuListHead
262 FORM_ENTRY_INFO
*MenuList
;
263 FORM_ENTRY_INFO
*NewMenuEntry
;
266 // If new menu list not empty, free it first.
268 UiFreeMenuList (NewMenuListHead
);
270 Link
= GetFirstNode (CurrentMenuListHead
);
271 while (!IsNull (CurrentMenuListHead
, Link
)) {
272 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
273 Link
= GetNextNode (CurrentMenuListHead
, Link
);
275 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
276 ASSERT (NewMenuEntry
!= NULL
);
277 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
278 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
279 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
280 NewMenuEntry
->FormId
= MenuList
->FormId
;
281 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
283 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
288 Load all hii formset to the browser.
296 FORM_BROWSER_FORMSET
*LocalFormSet
;
297 EFI_HII_HANDLE
*HiiHandles
;
301 FORM_BROWSER_FORMSET
*OldFormset
;
303 OldFormset
= mSystemLevelFormSet
;
306 // Get all the Hii handles
308 HiiHandles
= HiiGetHiiHandles (NULL
);
309 ASSERT (HiiHandles
!= NULL
);
312 // Search for formset of each class type
314 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
316 // Check HiiHandles[Index] does exist in global maintain list.
318 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
323 // Initilize FormSet Setting
325 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
326 ASSERT (LocalFormSet
!= NULL
);
327 mSystemLevelFormSet
= LocalFormSet
;
329 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
330 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
331 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
332 DestroyFormSet (LocalFormSet
);
335 InitializeCurrentSetting (LocalFormSet
);
338 // Initilize Questions' Value
340 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
341 if (EFI_ERROR (Status
)) {
342 DestroyFormSet (LocalFormSet
);
348 // Free resources, and restore gOldFormSet and gClassOfVfr
350 FreePool (HiiHandles
);
352 mSystemLevelFormSet
= OldFormset
;
356 Pop up the error info.
358 @param BrowserStatus The input browser status.
359 @param HiiHandle The Hiihandle for this opcode.
360 @param OpCode The opcode use to get the erro info and timeout value.
361 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
366 IN UINT32 BrowserStatus
,
367 IN EFI_HII_HANDLE HiiHandle
,
368 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
369 IN CHAR16
*ErrorString
372 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
373 USER_INPUT UserInputData
;
377 if (OpCode
!= NULL
) {
378 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
379 ASSERT (Statement
!= NULL
);
380 Statement
->OpCode
= OpCode
;
381 gDisplayFormData
.HighLightedStatement
= Statement
;
385 // Used to compatible with old display engine.
386 // New display engine not use this field.
388 gDisplayFormData
.ErrorString
= ErrorString
;
389 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
391 if (HiiHandle
!= NULL
) {
392 gDisplayFormData
.HiiHandle
= HiiHandle
;
395 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
397 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
398 gDisplayFormData
.ErrorString
= NULL
;
400 if (OpCode
!= NULL
) {
401 FreePool (Statement
);
404 return UserInputData
.Action
;
408 This is the routine which an external caller uses to direct the browser
409 where to obtain it's information.
412 @param This The Form Browser protocol instanse.
413 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
414 display a list of the formsets for the handles specified.
415 @param HandleCount The number of Handles specified in Handle.
416 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
417 field in the EFI_IFR_FORM_SET op-code for the specified
418 forms-based package. If FormSetGuid is NULL, then this
419 function will display the first found forms package.
420 @param FormId This field specifies which EFI_IFR_FORM to render as the first
421 displayable page. If this field has a value of 0x0000, then
422 the forms browser will render the specified forms in their encoded order.
423 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
425 @param ActionRequest Points to the action recommended by the form.
427 @retval EFI_SUCCESS The function completed successfully.
428 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
429 @retval EFI_NOT_FOUND No valid forms could be found to display.
435 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
436 IN EFI_HII_HANDLE
*Handles
,
437 IN UINTN HandleCount
,
438 IN EFI_GUID
*FormSetGuid
, OPTIONAL
439 IN UINT16 FormId
, OPTIONAL
440 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
441 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
445 UI_MENU_SELECTION
*Selection
;
447 FORM_BROWSER_FORMSET
*FormSet
;
448 FORM_ENTRY_INFO
*MenuList
;
451 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
453 if (mFormDisplay
== NULL
) {
454 return EFI_UNSUPPORTED
;
458 // Save globals used by SendForm()
460 SaveBrowserContext ();
462 gResetRequired
= FALSE
;
463 gExitRequired
= FALSE
;
464 Status
= EFI_SUCCESS
;
466 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
468 for (Index
= 0; Index
< HandleCount
; Index
++) {
469 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
470 ASSERT (Selection
!= NULL
);
472 Selection
->Handle
= Handles
[Index
];
473 if (FormSetGuid
!= NULL
) {
474 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
475 Selection
->FormId
= FormId
;
477 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
481 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
482 ASSERT (FormSet
!= NULL
);
485 // Initialize internal data structures of FormSet
487 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
488 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
489 DestroyFormSet (FormSet
);
492 Selection
->FormSet
= FormSet
;
493 mSystemLevelFormSet
= FormSet
;
496 // Display this formset
498 gCurrentSelection
= Selection
;
500 Status
= SetupBrowser (Selection
);
502 gCurrentSelection
= NULL
;
503 mSystemLevelFormSet
= NULL
;
506 // If no data is changed, don't need to save current FormSet into the maintain list.
508 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
509 CleanBrowserStorage(FormSet
);
510 RemoveEntryList (&FormSet
->Link
);
511 DestroyFormSet (FormSet
);
514 if (EFI_ERROR (Status
)) {
517 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
519 FreePool (Selection
);
522 if (ActionRequest
!= NULL
) {
523 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
524 if (gResetRequired
) {
525 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
529 mFormDisplay
->ExitDisplay();
532 // Clear the menu history data.
534 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
535 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
536 RemoveEntryList (&MenuList
->Link
);
541 // Restore globals used by SendForm()
543 RestoreBrowserContext ();
549 Get or set data to the storage.
551 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
552 @param ResultsData A string returned from an IFR browser or
553 equivalent. The results string will have no
554 routing information in them.
555 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
556 (if RetrieveData = TRUE) data from the uncommitted
557 browser state information or set (if RetrieveData
558 = FALSE) data in the uncommitted browser state
560 @param Storage The pointer to the storage.
562 @retval EFI_SUCCESS The results have been distributed or are awaiting
568 IN OUT UINTN
*ResultsDataSize
,
569 IN OUT EFI_STRING
*ResultsData
,
570 IN BOOLEAN RetrieveData
,
571 IN BROWSER_STORAGE
*Storage
582 // Generate <ConfigResp>
584 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
585 if (EFI_ERROR (Status
)) {
590 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
591 // Also need to consider add "\0" at first time.
593 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
594 BufferSize
= StrSize (StrPtr
);
598 // Copy the data if the input buffer is bigger enough.
600 if (*ResultsDataSize
>= BufferSize
) {
601 StrCpy (*ResultsData
, StrPtr
);
604 *ResultsDataSize
= BufferSize
;
605 FreePool (ConfigResp
);
608 // Prepare <ConfigResp>
610 TmpSize
= StrLen (*ResultsData
);
611 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
612 ConfigResp
= AllocateZeroPool (BufferSize
);
613 ASSERT (ConfigResp
!= NULL
);
615 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
616 StrCat (ConfigResp
, L
"&");
617 StrCat (ConfigResp
, *ResultsData
);
620 // Update Browser uncommited data
622 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
623 FreePool (ConfigResp
);
624 if (EFI_ERROR (Status
)) {
633 This routine called this service in the browser to retrieve or set certain uncommitted
634 state information that resides in the open formsets.
636 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
638 @param ResultsDataSize A pointer to the size of the buffer associated
640 @param ResultsData A string returned from an IFR browser or
641 equivalent. The results string will have no
642 routing information in them.
643 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
644 (if RetrieveData = TRUE) data from the uncommitted
645 browser state information or set (if RetrieveData
646 = FALSE) data in the uncommitted browser state
648 @param VariableGuid An optional field to indicate the target variable
650 @param VariableName An optional field to indicate the target
651 human-readable variable name.
653 @retval EFI_SUCCESS The results have been distributed or are awaiting
655 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
656 contain the results data.
662 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
663 IN OUT UINTN
*ResultsDataSize
,
664 IN OUT EFI_STRING ResultsData
,
665 IN BOOLEAN RetrieveData
,
666 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
667 IN CONST CHAR16
*VariableName OPTIONAL
672 BROWSER_STORAGE
*Storage
;
673 FORMSET_STORAGE
*FormsetStorage
;
677 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
678 return EFI_INVALID_PARAMETER
;
681 TotalSize
= *ResultsDataSize
;
684 Status
= EFI_SUCCESS
;
686 if (VariableGuid
!= NULL
) {
688 // Try to find target storage in the current formset.
690 Link
= GetFirstNode (&gBrowserStorageList
);
691 while (!IsNull (&gBrowserStorageList
, Link
)) {
692 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
693 Link
= GetNextNode (&gBrowserStorageList
, Link
);
695 // Check the current storage.
697 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
701 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
702 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
704 // Buffer storage require both GUID and Name
706 if (VariableName
== NULL
) {
707 return EFI_NOT_FOUND
;
710 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
715 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
716 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
717 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
718 return EFI_NOT_FOUND
;
721 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
726 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
727 if (EFI_ERROR (Status
)) {
731 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
732 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
736 // Different formsets may have same varstore, so here just set the flag
737 // not exit the circle.
744 return EFI_NOT_FOUND
;
748 // GUID/Name is not specified, take the first storage in FormSet
750 if (mSystemLevelFormSet
== NULL
) {
751 return EFI_NOT_READY
;
755 // Generate <ConfigResp>
757 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
758 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
759 return EFI_UNSUPPORTED
;
762 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
764 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
765 if (EFI_ERROR (Status
)) {
771 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
772 *ResultsDataSize
= TotalSize
;
781 Callback function for SimpleTextInEx protocol install events
783 @param Event the event that is signaled.
784 @param Context not used here.
789 FormDisplayCallback (
796 if (mFormDisplay
!= NULL
) {
800 Status
= gBS
->LocateProtocol (
801 &gEdkiiFormDisplayEngineProtocolGuid
,
803 (VOID
**) &mFormDisplay
808 Initialize Setup Browser driver.
810 @param ImageHandle The image handle.
811 @param SystemTable The system table.
813 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
814 @return Other value if failed to initialize the Setup Browser module.
820 IN EFI_HANDLE ImageHandle
,
821 IN EFI_SYSTEM_TABLE
*SystemTable
828 // Locate required Hii relative protocols
830 Status
= gBS
->LocateProtocol (
831 &gEfiHiiDatabaseProtocolGuid
,
833 (VOID
**) &mHiiDatabase
835 ASSERT_EFI_ERROR (Status
);
837 Status
= gBS
->LocateProtocol (
838 &gEfiHiiConfigRoutingProtocolGuid
,
840 (VOID
**) &mHiiConfigRouting
842 ASSERT_EFI_ERROR (Status
);
844 Status
= gBS
->LocateProtocol (
845 &gEfiDevicePathFromTextProtocolGuid
,
847 (VOID
**) &mPathFromText
851 // Install FormBrowser2 protocol
853 mPrivateData
.Handle
= NULL
;
854 Status
= gBS
->InstallProtocolInterface (
855 &mPrivateData
.Handle
,
856 &gEfiFormBrowser2ProtocolGuid
,
857 EFI_NATIVE_INTERFACE
,
858 &mPrivateData
.FormBrowser2
860 ASSERT_EFI_ERROR (Status
);
863 // Install FormBrowserEx2 protocol
865 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
866 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
867 mPrivateData
.Handle
= NULL
;
868 Status
= gBS
->InstallProtocolInterface (
869 &mPrivateData
.Handle
,
870 &gEdkiiFormBrowserEx2ProtocolGuid
,
871 EFI_NATIVE_INTERFACE
,
872 &mPrivateData
.FormBrowserEx2
874 ASSERT_EFI_ERROR (Status
);
876 Status
= gBS
->InstallProtocolInterface (
877 &mPrivateData
.Handle
,
878 &gEfiFormBrowserExProtocolGuid
,
879 EFI_NATIVE_INTERFACE
,
880 &mPrivateData
.FormBrowserEx
882 ASSERT_EFI_ERROR (Status
);
884 InitializeDisplayFormData ();
886 Status
= gBS
->LocateProtocol (
887 &gEdkiiFormDisplayEngineProtocolGuid
,
889 (VOID
**) &mFormDisplay
892 if (EFI_ERROR (Status
)) {
893 EfiCreateProtocolNotifyEvent (
894 &gEdkiiFormDisplayEngineProtocolGuid
,
907 Create a new string in HII Package List.
909 @param String The String to be added
910 @param HiiHandle The package list in the HII database to insert the
913 @return The output string.
919 IN EFI_HII_HANDLE HiiHandle
922 EFI_STRING_ID StringId
;
924 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
925 ASSERT (StringId
!= 0);
932 Delete a string from HII Package List.
934 @param StringId Id of the string in HII database.
935 @param HiiHandle The HII package list handle.
937 @retval EFI_SUCCESS The string was deleted successfully.
942 IN EFI_STRING_ID StringId
,
943 IN EFI_HII_HANDLE HiiHandle
948 NullChar
= CHAR_NULL
;
949 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
955 Get the string based on the StringId and HII Package List Handle.
957 @param Token The String's ID.
958 @param HiiHandle The package list in the HII database to search for
959 the specified string.
961 @return The output string.
966 IN EFI_STRING_ID Token
,
967 IN EFI_HII_HANDLE HiiHandle
972 if (HiiHandle
== NULL
) {
976 String
= HiiGetString (HiiHandle
, Token
, NULL
);
977 if (String
== NULL
) {
978 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
979 ASSERT (String
!= NULL
);
981 return (CHAR16
*) String
;
986 Allocate new memory and then copy the Unicode string Source to Destination.
988 @param Dest Location to copy string
989 @param Src String to copy
994 IN OUT CHAR16
**Dest
,
1001 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1002 ASSERT (*Dest
!= NULL
);
1007 Allocate new memory and concatinate Source on the end of Destination.
1009 @param Dest String to added to the end of.
1010 @param Src String to concatinate.
1015 IN OUT CHAR16
**Dest
,
1022 if (*Dest
== NULL
) {
1023 NewStringCpy (Dest
, Src
);
1027 TmpSize
= StrSize (*Dest
);
1028 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1029 ASSERT (NewString
!= NULL
);
1031 StrCpy (NewString
, *Dest
);
1032 StrCat (NewString
, Src
);
1039 Get Value for given Name from a NameValue Storage.
1041 @param Storage The NameValue Storage.
1042 @param Name The Name.
1043 @param Value The retured Value.
1044 @param GetValueFrom Where to get source value, from EditValue or Value.
1046 @retval EFI_SUCCESS Value found for given Name.
1047 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1052 IN BROWSER_STORAGE
*Storage
,
1054 IN OUT CHAR16
**Value
,
1055 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1059 NAME_VALUE_NODE
*Node
;
1061 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1062 return EFI_INVALID_PARAMETER
;
1067 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1068 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1069 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1071 if (StrCmp (Name
, Node
->Name
) == 0) {
1072 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1073 NewStringCpy (Value
, Node
->EditValue
);
1075 NewStringCpy (Value
, Node
->Value
);
1080 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1083 return EFI_NOT_FOUND
;
1088 Set Value of given Name in a NameValue Storage.
1090 @param Storage The NameValue Storage.
1091 @param Name The Name.
1092 @param Value The Value to set.
1093 @param SetValueTo Whether update editValue or Value.
1094 @param ReturnNode The node use the input name.
1096 @retval EFI_SUCCESS Value found for given Name.
1097 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1102 IN BROWSER_STORAGE
*Storage
,
1105 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1106 OUT NAME_VALUE_NODE
**ReturnNode
1110 NAME_VALUE_NODE
*Node
;
1113 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1114 return EFI_INVALID_PARAMETER
;
1117 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1118 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1119 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1121 if (StrCmp (Name
, Node
->Name
) == 0) {
1122 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1123 Buffer
= Node
->EditValue
;
1125 Buffer
= Node
->Value
;
1127 if (Buffer
!= NULL
) {
1130 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1131 ASSERT (Buffer
!= NULL
);
1132 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1133 Node
->EditValue
= Buffer
;
1135 Node
->Value
= Buffer
;
1138 if (ReturnNode
!= NULL
) {
1145 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1148 return EFI_NOT_FOUND
;
1153 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1155 @param Storage The Storage to be conveted.
1156 @param ConfigResp The returned <ConfigResp>.
1157 @param ConfigRequest The ConfigRequest string.
1158 @param GetEditBuf Get the data from editbuffer or buffer.
1160 @retval EFI_SUCCESS Convert success.
1161 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1165 StorageToConfigResp (
1166 IN BROWSER_STORAGE
*Storage
,
1167 IN CHAR16
**ConfigResp
,
1168 IN CHAR16
*ConfigRequest
,
1169 IN BOOLEAN GetEditBuf
1173 EFI_STRING Progress
;
1175 NAME_VALUE_NODE
*Node
;
1178 Status
= EFI_SUCCESS
;
1180 switch (Storage
->Type
) {
1181 case EFI_HII_VARSTORE_BUFFER
:
1182 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1183 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1184 Status
= mHiiConfigRouting
->BlockToConfig (
1194 case EFI_HII_VARSTORE_NAME_VALUE
:
1196 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1198 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1199 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1200 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1202 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1203 NewStringCat (ConfigResp
, L
"&");
1204 NewStringCat (ConfigResp
, Node
->Name
);
1205 NewStringCat (ConfigResp
, L
"=");
1207 NewStringCat (ConfigResp
, Node
->EditValue
);
1209 NewStringCat (ConfigResp
, Node
->Value
);
1212 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1216 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1218 Status
= EFI_INVALID_PARAMETER
;
1227 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1229 @param Storage The Storage to receive the settings.
1230 @param ConfigResp The <ConfigResp> to be converted.
1232 @retval EFI_SUCCESS Convert success.
1233 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1237 ConfigRespToStorage (
1238 IN BROWSER_STORAGE
*Storage
,
1239 IN CHAR16
*ConfigResp
1243 EFI_STRING Progress
;
1249 Status
= EFI_SUCCESS
;
1251 switch (Storage
->Type
) {
1252 case EFI_HII_VARSTORE_BUFFER
:
1253 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1254 BufferSize
= Storage
->Size
;
1255 Status
= mHiiConfigRouting
->ConfigToBlock (
1258 Storage
->EditBuffer
,
1264 case EFI_HII_VARSTORE_NAME_VALUE
:
1265 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1266 if (StrPtr
== NULL
) {
1269 StrPtr
= StrStr (ConfigResp
, L
"&");
1270 while (StrPtr
!= NULL
) {
1274 StrPtr
= StrPtr
+ 1;
1276 StrPtr
= StrStr (StrPtr
, L
"=");
1277 if (StrPtr
== NULL
) {
1285 StrPtr
= StrPtr
+ 1;
1287 StrPtr
= StrStr (StrPtr
, L
"&");
1288 if (StrPtr
!= NULL
) {
1291 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1295 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1297 Status
= EFI_INVALID_PARAMETER
;
1306 Get Question's current Value.
1308 @param FormSet FormSet data structure.
1309 @param Form Form data structure.
1310 @param Question Question to be initialized.
1311 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1313 @retval EFI_SUCCESS The function completed successfully.
1318 IN FORM_BROWSER_FORMSET
*FormSet
,
1319 IN FORM_BROWSER_FORM
*Form
,
1320 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1321 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1330 BROWSER_STORAGE
*Storage
;
1331 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1332 CHAR16
*ConfigRequest
;
1340 BOOLEAN IsBufferStorage
;
1345 Status
= EFI_SUCCESS
;
1349 if (GetValueFrom
>= GetSetValueWithMax
) {
1350 return EFI_INVALID_PARAMETER
;
1354 // Question value is provided by an Expression, evaluate it
1356 if (Question
->ValueExpression
!= NULL
) {
1357 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1358 if (!EFI_ERROR (Status
)) {
1359 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1360 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1361 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1362 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1363 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1365 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1366 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1368 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1370 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1371 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1377 // Get question value by read expression.
1379 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1380 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1381 if (!EFI_ERROR (Status
) &&
1382 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1384 // Only update question value to the valid result.
1386 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1387 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1388 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1389 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1390 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1392 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1393 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1395 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1397 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1398 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1404 // Question value is provided by RTC
1406 Storage
= Question
->Storage
;
1407 QuestionValue
= &Question
->HiiValue
.Value
;
1408 if (Storage
== NULL
) {
1410 // It's a Question without storage, or RTC date/time
1412 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1414 // Date and time define the same Flags bit
1416 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1417 case QF_DATE_STORAGE_TIME
:
1418 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1421 case QF_DATE_STORAGE_WAKEUP
:
1422 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1425 case QF_DATE_STORAGE_NORMAL
:
1428 // For date/time without storage
1433 if (EFI_ERROR (Status
)) {
1437 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1438 QuestionValue
->date
.Year
= EfiTime
.Year
;
1439 QuestionValue
->date
.Month
= EfiTime
.Month
;
1440 QuestionValue
->date
.Day
= EfiTime
.Day
;
1442 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1443 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1444 QuestionValue
->time
.Second
= EfiTime
.Second
;
1452 // Question value is provided by EFI variable
1454 StorageWidth
= Question
->StorageWidth
;
1455 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1456 if (Question
->BufferValue
!= NULL
) {
1457 Dst
= Question
->BufferValue
;
1459 Dst
= (UINT8
*) QuestionValue
;
1462 Status
= gRT
->GetVariable (
1463 Question
->VariableName
,
1470 // Always return success, even this EFI variable doesn't exist
1476 // Question Value is provided by Buffer Storage or NameValue Storage
1478 if (Question
->BufferValue
!= NULL
) {
1480 // This Question is password or orderedlist
1482 Dst
= Question
->BufferValue
;
1485 // Other type of Questions
1487 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1490 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1491 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1492 IsBufferStorage
= TRUE
;
1494 IsBufferStorage
= FALSE
;
1496 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1497 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1498 if (IsBufferStorage
) {
1499 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1501 // Copy from storage Edit buffer
1503 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1506 // Copy from storage Edit buffer
1508 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1512 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1513 if (EFI_ERROR (Status
)) {
1517 ASSERT (Value
!= NULL
);
1518 LengthStr
= StrLen (Value
);
1519 Status
= EFI_SUCCESS
;
1522 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1523 // Add string tail char L'\0' into Length
1525 Length
= StorageWidth
+ sizeof (CHAR16
);
1526 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1527 Status
= EFI_BUFFER_TOO_SMALL
;
1529 StringPtr
= (CHAR16
*) Dst
;
1530 ZeroMem (TemStr
, sizeof (TemStr
));
1531 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1532 StrnCpy (TemStr
, Value
+ Index
, 4);
1533 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1536 // Add tailing L'\0' character
1538 StringPtr
[Index
/4] = L
'\0';
1541 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1542 Status
= EFI_BUFFER_TOO_SMALL
;
1544 ZeroMem (TemStr
, sizeof (TemStr
));
1545 for (Index
= 0; Index
< LengthStr
; Index
++) {
1546 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1547 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1548 if ((Index
& 1) == 0) {
1549 Dst
[Index
/2] = DigitUint8
;
1551 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1561 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1562 // <ConfigHdr> + "&" + <VariableName>
1564 if (IsBufferStorage
) {
1565 Length
= StrLen (Storage
->ConfigHdr
);
1566 Length
+= StrLen (Question
->BlockName
);
1568 Length
= StrLen (Storage
->ConfigHdr
);
1569 Length
+= StrLen (Question
->VariableName
) + 1;
1571 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1572 ASSERT (ConfigRequest
!= NULL
);
1574 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1575 if (IsBufferStorage
) {
1576 StrCat (ConfigRequest
, Question
->BlockName
);
1578 StrCat (ConfigRequest
, L
"&");
1579 StrCat (ConfigRequest
, Question
->VariableName
);
1583 // Request current settings from Configuration Driver
1585 Status
= mHiiConfigRouting
->ExtractConfig (
1591 FreePool (ConfigRequest
);
1592 if (EFI_ERROR (Status
)) {
1597 // Skip <ConfigRequest>
1599 if (IsBufferStorage
) {
1600 Value
= StrStr (Result
, L
"&VALUE");
1601 if (Value
== NULL
) {
1603 return EFI_NOT_FOUND
;
1610 Value
= Result
+ Length
;
1612 if (*Value
!= '=') {
1614 return EFI_NOT_FOUND
;
1617 // Skip '=', point to value
1622 // Suppress <AltResp> if any
1625 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1630 LengthStr
= StrLen (Value
);
1631 Status
= EFI_SUCCESS
;
1632 if (!IsBufferStorage
&& IsString
) {
1634 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1635 // Add string tail char L'\0' into Length
1637 Length
= StorageWidth
+ sizeof (CHAR16
);
1638 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1639 Status
= EFI_BUFFER_TOO_SMALL
;
1641 StringPtr
= (CHAR16
*) Dst
;
1642 ZeroMem (TemStr
, sizeof (TemStr
));
1643 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1644 StrnCpy (TemStr
, Value
+ Index
, 4);
1645 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1648 // Add tailing L'\0' character
1650 StringPtr
[Index
/4] = L
'\0';
1653 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1654 Status
= EFI_BUFFER_TOO_SMALL
;
1656 ZeroMem (TemStr
, sizeof (TemStr
));
1657 for (Index
= 0; Index
< LengthStr
; Index
++) {
1658 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1659 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1660 if ((Index
& 1) == 0) {
1661 Dst
[Index
/2] = DigitUint8
;
1663 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1669 if (EFI_ERROR (Status
)) {
1675 // Synchronize Edit Buffer
1677 if (IsBufferStorage
) {
1678 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1680 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1683 if (Result
!= NULL
) {
1693 Save Question Value to edit copy(cached) or Storage(uncached).
1695 @param FormSet FormSet data structure.
1696 @param Form Form data structure.
1697 @param Question Pointer to the Question.
1698 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1700 @retval EFI_SUCCESS The function completed successfully.
1705 IN FORM_BROWSER_FORMSET
*FormSet
,
1706 IN FORM_BROWSER_FORM
*Form
,
1707 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1708 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1718 BROWSER_STORAGE
*Storage
;
1719 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1724 BOOLEAN IsBufferStorage
;
1730 NAME_VALUE_NODE
*Node
;
1732 Status
= EFI_SUCCESS
;
1735 if (SetValueTo
>= GetSetValueWithMax
) {
1736 return EFI_INVALID_PARAMETER
;
1740 // If Question value is provided by an Expression, then it is read only
1742 if (Question
->ValueExpression
!= NULL
) {
1747 // Before set question value, evaluate its write expression.
1749 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1750 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1751 if (EFI_ERROR (Status
)) {
1757 // Question value is provided by RTC
1759 Storage
= Question
->Storage
;
1760 QuestionValue
= &Question
->HiiValue
.Value
;
1761 if (Storage
== NULL
) {
1763 // It's a Question without storage, or RTC date/time
1765 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1767 // Date and time define the same Flags bit
1769 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1770 case QF_DATE_STORAGE_TIME
:
1771 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1774 case QF_DATE_STORAGE_WAKEUP
:
1775 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1778 case QF_DATE_STORAGE_NORMAL
:
1781 // For date/time without storage
1786 if (EFI_ERROR (Status
)) {
1790 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1791 EfiTime
.Year
= QuestionValue
->date
.Year
;
1792 EfiTime
.Month
= QuestionValue
->date
.Month
;
1793 EfiTime
.Day
= QuestionValue
->date
.Day
;
1795 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1796 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1797 EfiTime
.Second
= QuestionValue
->time
.Second
;
1800 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1801 Status
= gRT
->SetTime (&EfiTime
);
1803 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1811 // Question value is provided by EFI variable
1813 StorageWidth
= Question
->StorageWidth
;
1814 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1815 if (Question
->BufferValue
!= NULL
) {
1816 Src
= Question
->BufferValue
;
1818 Src
= (UINT8
*) QuestionValue
;
1821 Status
= gRT
->SetVariable (
1822 Question
->VariableName
,
1824 Storage
->Attributes
,
1832 // Question Value is provided by Buffer Storage or NameValue Storage
1834 if (Question
->BufferValue
!= NULL
) {
1835 Src
= Question
->BufferValue
;
1837 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1840 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1841 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1842 IsBufferStorage
= TRUE
;
1844 IsBufferStorage
= FALSE
;
1846 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1848 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1849 if (IsBufferStorage
) {
1850 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1852 // Copy to storage edit buffer
1854 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1855 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1857 // Copy to storage edit buffer
1859 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1864 // Allocate enough string buffer.
1867 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1868 Value
= AllocateZeroPool (BufferLen
);
1869 ASSERT (Value
!= NULL
);
1871 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1873 TemName
= (CHAR16
*) Src
;
1875 for (; *TemName
!= L
'\0'; TemName
++) {
1876 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1879 BufferLen
= StorageWidth
* 2 + 1;
1880 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1881 ASSERT (Value
!= NULL
);
1883 // Convert Buffer to Hex String
1885 TemBuffer
= Src
+ StorageWidth
- 1;
1887 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1888 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1892 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1894 if (EFI_ERROR (Status
)) {
1898 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1900 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1901 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1903 if (IsBufferStorage
) {
1904 Length
= StrLen (Question
->BlockName
) + 7;
1906 Length
= StrLen (Question
->VariableName
) + 2;
1908 if (!IsBufferStorage
&& IsString
) {
1909 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1911 Length
+= (StorageWidth
* 2);
1913 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1914 ASSERT (ConfigResp
!= NULL
);
1916 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1917 if (IsBufferStorage
) {
1918 StrCat (ConfigResp
, Question
->BlockName
);
1919 StrCat (ConfigResp
, L
"&VALUE=");
1921 StrCat (ConfigResp
, L
"&");
1922 StrCat (ConfigResp
, Question
->VariableName
);
1923 StrCat (ConfigResp
, L
"=");
1926 Value
= ConfigResp
+ StrLen (ConfigResp
);
1928 if (!IsBufferStorage
&& IsString
) {
1930 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1932 TemName
= (CHAR16
*) Src
;
1934 for (; *TemName
!= L
'\0'; TemName
++) {
1935 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1939 // Convert Buffer to Hex String
1941 TemBuffer
= Src
+ StorageWidth
- 1;
1943 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1944 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1949 // Convert to lower char.
1951 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1952 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1953 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1958 // Submit Question Value to Configuration Driver
1960 Status
= mHiiConfigRouting
->RouteConfig (
1965 if (EFI_ERROR (Status
)) {
1966 FreePool (ConfigResp
);
1969 FreePool (ConfigResp
);
1972 // Sync storage, from editbuffer to buffer.
1974 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1982 Perform nosubmitif check for a Form.
1984 @param FormSet FormSet data structure.
1985 @param Form Form data structure.
1986 @param Question The Question to be validated.
1987 @param Type Validation type: NoSubmit
1989 @retval EFI_SUCCESS Form validation pass.
1990 @retval other Form validation failed.
1995 IN FORM_BROWSER_FORMSET
*FormSet
,
1996 IN FORM_BROWSER_FORM
*Form
,
1997 IN FORM_BROWSER_STATEMENT
*Question
,
2003 LIST_ENTRY
*ListHead
;
2004 FORM_EXPRESSION
*Expression
;
2005 UINT32 BrowserStatus
;
2008 BrowserStatus
= BROWSER_SUCCESS
;
2012 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2013 ListHead
= &Question
->InconsistentListHead
;
2016 case EFI_HII_EXPRESSION_WARNING_IF
:
2017 ListHead
= &Question
->WarningListHead
;
2020 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2021 ListHead
= &Question
->NoSubmitListHead
;
2026 return EFI_UNSUPPORTED
;
2029 Link
= GetFirstNode (ListHead
);
2030 while (!IsNull (ListHead
, Link
)) {
2031 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2034 // Evaluate the expression
2036 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2037 if (EFI_ERROR (Status
)) {
2041 if (IsTrue (&Expression
->Result
)) {
2043 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2044 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2047 case EFI_HII_EXPRESSION_WARNING_IF
:
2048 BrowserStatus
= BROWSER_WARNING_IF
;
2051 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2052 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2054 // This code only used to compatible with old display engine,
2055 // New display engine will not use this field.
2057 if (Expression
->Error
!= 0) {
2058 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2067 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2069 // If in system submit process and for no_submit_if check, not popup this error message.
2070 // Will process this fail again later in not system submit process.
2072 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2075 if (ErrorStr
!= NULL
) {
2076 FreePool (ErrorStr
);
2079 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2082 return EFI_NOT_READY
;
2086 Link
= GetNextNode (ListHead
, Link
);
2093 Perform question check.
2095 If one question has more than one check, process form high priority to low.
2096 Only one error info will be popup.
2098 @param FormSet FormSet data structure.
2099 @param Form Form data structure.
2100 @param Question The Question to be validated.
2102 @retval EFI_SUCCESS Form validation pass.
2103 @retval other Form validation failed.
2107 ValueChangedValidation (
2108 IN FORM_BROWSER_FORMSET
*FormSet
,
2109 IN FORM_BROWSER_FORM
*Form
,
2110 IN FORM_BROWSER_STATEMENT
*Question
2115 Status
= EFI_SUCCESS
;
2118 // Do the inconsistentif check.
2120 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2121 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2122 if (EFI_ERROR (Status
)) {
2128 // Do the warningif check.
2130 if (!IsListEmpty (&Question
->WarningListHead
)) {
2131 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2138 Perform NoSubmit check for each Form in FormSet.
2140 @param FormSet FormSet data structure.
2141 @param CurrentForm Current input form data structure.
2142 @param Statement The statement for this check.
2144 @retval EFI_SUCCESS Form validation pass.
2145 @retval other Form validation failed.
2150 IN FORM_BROWSER_FORMSET
*FormSet
,
2151 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2152 OUT FORM_BROWSER_STATEMENT
**Statement
2157 FORM_BROWSER_STATEMENT
*Question
;
2158 FORM_BROWSER_FORM
*Form
;
2159 LIST_ENTRY
*LinkForm
;
2161 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2162 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2163 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2164 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2166 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2170 Link
= GetFirstNode (&Form
->StatementListHead
);
2171 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2172 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2173 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2174 if (EFI_ERROR (Status
)) {
2175 if (*CurrentForm
== NULL
) {
2176 *CurrentForm
= Form
;
2178 if (Statement
!= NULL
) {
2179 *Statement
= Question
;
2184 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2192 Fill storage's edit copy with settings requested from Configuration Driver.
2194 @param Storage The storage which need to sync.
2195 @param ConfigRequest The config request string which used to sync storage.
2196 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2197 editbuffer to buffer
2198 if TRUE, copy the editbuffer to the buffer.
2199 if FALSE, copy the buffer to the editbuffer.
2201 @retval EFI_SUCCESS The function completed successfully.
2205 SynchronizeStorage (
2206 OUT BROWSER_STORAGE
*Storage
,
2207 IN CHAR16
*ConfigRequest
,
2208 IN BOOLEAN SyncOrRestore
2212 EFI_STRING Progress
;
2216 NAME_VALUE_NODE
*Node
;
2220 Status
= EFI_SUCCESS
;
2223 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2224 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2225 BufferSize
= Storage
->Size
;
2227 if (SyncOrRestore
) {
2228 Src
= Storage
->EditBuffer
;
2229 Dst
= Storage
->Buffer
;
2231 Src
= Storage
->Buffer
;
2232 Dst
= Storage
->EditBuffer
;
2235 if (ConfigRequest
!= NULL
) {
2236 Status
= mHiiConfigRouting
->BlockToConfig(
2244 if (EFI_ERROR (Status
)) {
2248 Status
= mHiiConfigRouting
->ConfigToBlock (
2255 if (Result
!= NULL
) {
2259 CopyMem (Dst
, Src
, BufferSize
);
2261 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2262 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2263 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2264 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2266 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2267 (ConfigRequest
== NULL
)) {
2268 if (SyncOrRestore
) {
2269 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2271 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2275 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2283 When discard the question value, call the callback function with Changed type
2284 to inform the hii driver.
2286 @param FormSet FormSet data structure.
2287 @param Form Form data structure.
2291 SendDiscardInfoToDriver (
2292 IN FORM_BROWSER_FORMSET
*FormSet
,
2293 IN FORM_BROWSER_FORM
*Form
2297 FORM_BROWSER_STATEMENT
*Question
;
2298 EFI_IFR_TYPE_VALUE
*TypeValue
;
2299 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2301 if (FormSet
->ConfigAccess
== NULL
) {
2305 Link
= GetFirstNode (&Form
->StatementListHead
);
2306 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2307 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2308 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2310 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2314 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2318 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2322 if (!Question
->ValueChanged
) {
2327 // Restore the question value before call the CHANGED callback type.
2329 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2331 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2332 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2334 TypeValue
= &Question
->HiiValue
.Value
;
2337 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2338 FormSet
->ConfigAccess
->Callback (
2339 FormSet
->ConfigAccess
,
2340 EFI_BROWSER_ACTION_CHANGED
,
2341 Question
->QuestionId
,
2342 Question
->HiiValue
.Type
,
2350 Validate the FormSet. If the formset is not validate, remove it from the list.
2352 @param FormSet The input FormSet which need to validate.
2354 @retval TRUE The handle is validate.
2355 @retval FALSE The handle is invalidate.
2360 FORM_BROWSER_FORMSET
*FormSet
2363 EFI_HII_HANDLE
*HiiHandles
;
2367 ASSERT (FormSet
!= NULL
);
2370 // Get all the Hii handles
2372 HiiHandles
= HiiGetHiiHandles (NULL
);
2373 ASSERT (HiiHandles
!= NULL
);
2376 // Search for formset of each class type
2378 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2379 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2386 CleanBrowserStorage(FormSet
);
2387 RemoveEntryList (&FormSet
->Link
);
2388 DestroyFormSet (FormSet
);
2391 FreePool (HiiHandles
);
2396 Check whether need to enable the reset flag in form level.
2397 Also clean all ValueChanged flag in question.
2399 @param SetFlag Whether need to set the Reset Flag.
2400 @param FormSet FormSet data structure.
2401 @param Form Form data structure.
2407 IN FORM_BROWSER_FORMSET
*FormSet
,
2408 IN FORM_BROWSER_FORM
*Form
2412 FORM_BROWSER_STATEMENT
*Question
;
2415 Link
= GetFirstNode (&Form
->StatementListHead
);
2416 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2417 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2418 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2420 if (!Question
->ValueChanged
) {
2424 OldValue
= Question
->ValueChanged
;
2427 // Compare the buffer and editbuffer data to see whether the data has been saved.
2429 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2432 // Only the changed data has been saved, then need to set the reset flag.
2434 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2435 gResetRequired
= TRUE
;
2441 Check whether need to enable the reset flag.
2442 Also clean ValueChanged flag for all statements.
2444 Form level or formset level, only one.
2446 @param SetFlag Whether need to set the Reset Flag.
2447 @param FormSet FormSet data structure.
2448 @param Form Form data structure.
2452 ValueChangeResetFlagUpdate (
2454 IN FORM_BROWSER_FORMSET
*FormSet
,
2455 IN FORM_BROWSER_FORM
*Form
2458 FORM_BROWSER_FORM
*CurrentForm
;
2462 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2466 Link
= GetFirstNode (&FormSet
->FormListHead
);
2467 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2468 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2469 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2471 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2476 Base on the return Progress string to find the form.
2478 Base on the first return Offset/Width (Name) string to find the form
2479 which keep this string.
2481 @param FormSet FormSet data structure.
2482 @param Storage Storage which has this Progress string.
2483 @param Progress The Progress string which has the first fail string.
2484 @param RetForm The return form for this progress string.
2485 @param RetQuestion The return question for the error progress string.
2487 @retval TRUE Find the error form and statement for this error progress string.
2488 @retval FALSE Not find the error form.
2492 FindQuestionFromProgress (
2493 IN FORM_BROWSER_FORMSET
*FormSet
,
2494 IN BROWSER_STORAGE
*Storage
,
2495 IN EFI_STRING Progress
,
2496 OUT FORM_BROWSER_FORM
**RetForm
,
2497 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2501 LIST_ENTRY
*LinkStorage
;
2502 LIST_ENTRY
*LinkStatement
;
2503 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2504 FORM_BROWSER_FORM
*Form
;
2506 FORM_BROWSER_STATEMENT
*Statement
;
2508 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2512 *RetQuestion
= NULL
;
2515 // Skip the first "&" or the ConfigHdr part.
2517 if (*Progress
== '&') {
2521 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2523 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2525 // For Name/Value type, Skip the ConfigHdr part.
2527 EndStr
= StrStr (Progress
, L
"PATH=");
2528 while (*EndStr
!= '&') {
2535 // For Buffer type, Skip the ConfigHdr part.
2537 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2541 Progress
= EndStr
+ 1;
2545 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2547 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2549 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2550 // here, just keep the "Fred" string.
2552 EndStr
= StrStr (Progress
, L
"=");
2556 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2557 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2559 EndStr
= StrStr (Progress
, L
"&VALUE=");
2564 // Search in the form list.
2566 Link
= GetFirstNode (&FormSet
->FormListHead
);
2567 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2568 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2569 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2572 // Search in the ConfigReqeust list in this form.
2574 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2575 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2576 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2577 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2579 if (Storage
!= ConfigInfo
->Storage
) {
2583 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2585 // Find the OffsetWidth string in this form.
2592 if (*RetForm
!= NULL
) {
2593 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2594 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2595 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2596 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2598 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2599 *RetQuestion
= Statement
;
2605 if (*RetForm
!= NULL
) {
2611 // restore the OffsetWidth string to the original format.
2613 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2619 return (BOOLEAN
) (*RetForm
!= NULL
);
2623 Popup an save error info and get user input.
2625 @param TitleId The form title id.
2626 @param HiiHandle The hii handle for this package.
2628 @retval UINT32 The user select option for the save fail.
2629 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2633 IN EFI_STRING_ID TitleId
,
2634 IN EFI_HII_HANDLE HiiHandle
2638 CHAR16
*StringBuffer
;
2641 FormTitle
= GetToken (TitleId
, HiiHandle
);
2643 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2644 ASSERT (StringBuffer
!= NULL
);
2648 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2649 L
"Submit Fail For Form: %s.",
2653 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2655 FreePool (StringBuffer
);
2656 FreePool (FormTitle
);
2662 Popup an NO_SUBMIT_IF error info and get user input.
2664 @param TitleId The form title id.
2665 @param HiiHandle The hii handle for this package.
2667 @retval UINT32 The user select option for the save fail.
2668 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2671 ConfirmNoSubmitFail (
2672 IN EFI_STRING_ID TitleId
,
2673 IN EFI_HII_HANDLE HiiHandle
2677 CHAR16
*StringBuffer
;
2680 FormTitle
= GetToken (TitleId
, HiiHandle
);
2682 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2683 ASSERT (StringBuffer
!= NULL
);
2687 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2688 L
"NO_SUBMIT_IF error For Form: %s.",
2692 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2694 FreePool (StringBuffer
);
2695 FreePool (FormTitle
);
2701 Discard data based on the input setting scope (Form, FormSet or System).
2703 @param FormSet FormSet data structure.
2704 @param Form Form data structure.
2705 @param SettingScope Setting Scope for Discard action.
2707 @retval EFI_SUCCESS The function completed successfully.
2708 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2713 IN FORM_BROWSER_FORMSET
*FormSet
,
2714 IN FORM_BROWSER_FORM
*Form
,
2715 IN BROWSER_SETTING_SCOPE SettingScope
2719 FORMSET_STORAGE
*Storage
;
2720 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2721 FORM_BROWSER_FORMSET
*LocalFormSet
;
2722 FORM_BROWSER_FORMSET
*OldFormSet
;
2725 // Check the supported setting level.
2727 if (SettingScope
>= MaxLevel
) {
2728 return EFI_UNSUPPORTED
;
2731 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2733 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2734 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2735 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2736 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2738 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2743 // Skip if there is no RequestElement
2745 if (ConfigInfo
->ElementCount
== 0) {
2750 // Prepare <ConfigResp>
2752 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2755 // Call callback with Changed type to inform the driver.
2757 SendDiscardInfoToDriver (FormSet
, Form
);
2760 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2761 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2764 // Discard Buffer storage or Name/Value storage
2766 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2767 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2768 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2769 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2771 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2776 // Skip if there is no RequestElement
2778 if (Storage
->ElementCount
== 0) {
2782 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2785 Link
= GetFirstNode (&FormSet
->FormListHead
);
2786 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2787 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2788 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2791 // Call callback with Changed type to inform the driver.
2793 SendDiscardInfoToDriver (FormSet
, Form
);
2796 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2797 } else if (SettingScope
== SystemLevel
) {
2799 // System Level Discard.
2801 OldFormSet
= mSystemLevelFormSet
;
2804 // Discard changed value for each FormSet in the maintain list.
2806 Link
= GetFirstNode (&gBrowserFormSetList
);
2807 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2808 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2809 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2810 if (!ValidateFormSet(LocalFormSet
)) {
2814 mSystemLevelFormSet
= LocalFormSet
;
2816 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2817 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2819 // Remove maintain backup list after discard except for the current using FormSet.
2821 CleanBrowserStorage(LocalFormSet
);
2822 RemoveEntryList (&LocalFormSet
->Link
);
2823 DestroyFormSet (LocalFormSet
);
2827 mSystemLevelFormSet
= OldFormSet
;
2834 Submit data for a form.
2836 @param FormSet FormSet data structure.
2837 @param Form Form data structure.
2839 @retval EFI_SUCCESS The function completed successfully.
2840 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2845 IN FORM_BROWSER_FORMSET
*FormSet
,
2846 IN FORM_BROWSER_FORM
*Form
2851 EFI_STRING ConfigResp
;
2852 EFI_STRING Progress
;
2853 BROWSER_STORAGE
*Storage
;
2854 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2856 if (!IsNvUpdateRequiredForForm (Form
)) {
2860 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2861 if (EFI_ERROR (Status
)) {
2865 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2866 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2867 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2868 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2870 Storage
= ConfigInfo
->Storage
;
2871 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2876 // Skip if there is no RequestElement
2878 if (ConfigInfo
->ElementCount
== 0) {
2883 // 1. Prepare <ConfigResp>
2885 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2886 if (EFI_ERROR (Status
)) {
2891 // 2. Set value to hii config routine protocol.
2893 Status
= mHiiConfigRouting
->RouteConfig (
2898 FreePool (ConfigResp
);
2900 if (EFI_ERROR (Status
)) {
2901 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2906 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2908 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2912 // 4. Process the save failed storage.
2914 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2915 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
2916 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2917 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
2918 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
2919 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
2921 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2923 Status
= EFI_SUCCESS
;
2926 Status
= EFI_UNSUPPORTED
;
2930 // Free Form save fail list.
2932 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2933 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2934 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
2935 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
2940 // 5. Update the NV flag.
2942 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
2948 Submit data for a formset.
2950 @param FormSet FormSet data structure.
2951 @param SkipProcessFail Whether skip to process the save failed storage.
2952 If submit formset is called when do system level save,
2953 set this value to true and process the failed formset
2955 if submit formset is called when do formset level save,
2956 set the value to false and process the failed storage
2957 right after process all storages for this formset.
2959 @retval EFI_SUCCESS The function completed successfully.
2960 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2965 IN FORM_BROWSER_FORMSET
*FormSet
,
2966 IN BOOLEAN SkipProcessFail
2971 EFI_STRING ConfigResp
;
2972 EFI_STRING Progress
;
2973 BROWSER_STORAGE
*Storage
;
2974 FORMSET_STORAGE
*FormSetStorage
;
2975 FORM_BROWSER_FORM
*Form
;
2976 BOOLEAN HasInserted
;
2977 FORM_BROWSER_STATEMENT
*Question
;
2979 HasInserted
= FALSE
;
2981 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
2986 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
2987 if (EFI_ERROR (Status
)) {
2988 if (SkipProcessFail
) {
2990 // Process NO_SUBMIT check first, so insert it at head.
2992 FormSet
->SaveFailForm
= Form
;
2993 FormSet
->SaveFailStatement
= Question
;
2994 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3003 // Submit Buffer storage or Name/Value storage
3005 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3006 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3007 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3008 Storage
= FormSetStorage
->BrowserStorage
;
3009 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3011 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3016 // Skip if there is no RequestElement
3018 if (FormSetStorage
->ElementCount
== 0) {
3023 // 1. Prepare <ConfigResp>
3025 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3026 if (EFI_ERROR (Status
)) {
3031 // 2. Send <ConfigResp> to Routine config Protocol.
3033 Status
= mHiiConfigRouting
->RouteConfig (
3038 if (EFI_ERROR (Status
)) {
3039 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3042 // Call submit formset for system level, save the formset info
3043 // and process later.
3045 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3046 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3047 FormSet
->SaveFailForm
= Form
;
3048 FormSet
->SaveFailStatement
= Question
;
3049 if (SkipProcessFail
) {
3050 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3055 FreePool (ConfigResp
);
3059 FreePool (ConfigResp
);
3061 // 3. Config success, update storage shadow Buffer
3063 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3067 // 4. Has save fail storage need to handle.
3070 if (!SkipProcessFail
) {
3072 // If not in system level, just handl the save failed storage here.
3074 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3075 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3076 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3077 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3078 Storage
= FormSetStorage
->BrowserStorage
;
3079 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3081 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3083 Status
= EFI_SUCCESS
;
3086 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3088 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3089 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3090 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3091 gCurrentSelection
->FormId
= Form
->FormId
;
3092 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3094 Status
= EFI_UNSUPPORTED
;
3098 // Free FormSet save fail list.
3100 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3101 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3102 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3103 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3107 // If in system level, just return error and handle the failed formset later.
3109 Status
= EFI_UNSUPPORTED
;
3114 // 5. Update the NV flag.
3116 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3122 Submit data for all formsets.
3124 @retval EFI_SUCCESS The function completed successfully.
3125 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3135 LIST_ENTRY
*StorageLink
;
3136 BROWSER_STORAGE
*Storage
;
3137 FORMSET_STORAGE
*FormSetStorage
;
3138 FORM_BROWSER_FORM
*Form
;
3139 FORM_BROWSER_FORMSET
*LocalFormSet
;
3140 UINT32 UserSelection
;
3141 FORM_BROWSER_STATEMENT
*Question
;
3143 mSystemSubmit
= TRUE
;
3144 Link
= GetFirstNode (&gBrowserFormSetList
);
3145 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3146 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3147 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3148 if (!ValidateFormSet(LocalFormSet
)) {
3152 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3153 if (EFI_ERROR (Status
)) {
3158 // Remove maintain backup list after save except for the current using FormSet.
3160 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3161 CleanBrowserStorage(LocalFormSet
);
3162 RemoveEntryList (&LocalFormSet
->Link
);
3163 DestroyFormSet (LocalFormSet
);
3166 mSystemSubmit
= FALSE
;
3168 Status
= EFI_SUCCESS
;
3171 // Process the save failed formsets.
3173 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3174 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3175 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3176 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3178 if (!ValidateFormSet(LocalFormSet
)) {
3182 Form
= LocalFormSet
->SaveFailForm
;
3183 Question
= LocalFormSet
->SaveFailStatement
;
3186 // Confirm with user, get user input.
3188 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3190 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3192 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3194 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3197 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3198 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3199 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3200 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3201 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3202 Storage
= FormSetStorage
->BrowserStorage
;
3203 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3205 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3208 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3209 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3210 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3211 Storage
= FormSetStorage
->BrowserStorage
;
3212 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3214 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3218 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3219 CleanBrowserStorage(LocalFormSet
);
3220 RemoveEntryList (&LocalFormSet
->Link
);
3221 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3222 DestroyFormSet (LocalFormSet
);
3224 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3227 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3228 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3231 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3233 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3234 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3235 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3236 gCurrentSelection
->FormId
= Form
->FormId
;
3237 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3239 Status
= EFI_UNSUPPORTED
;
3245 // Clean the list which will not process.
3247 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3248 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3249 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3250 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3252 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3253 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3254 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3255 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3263 Submit data based on the input Setting level (Form, FormSet or System).
3265 @param FormSet FormSet data structure.
3266 @param Form Form data structure.
3267 @param SettingScope Setting Scope for Submit action.
3269 @retval EFI_SUCCESS The function completed successfully.
3270 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3275 IN FORM_BROWSER_FORMSET
*FormSet
,
3276 IN FORM_BROWSER_FORM
*Form
,
3277 IN BROWSER_SETTING_SCOPE SettingScope
3282 switch (SettingScope
) {
3284 Status
= SubmitForForm(FormSet
, Form
);
3288 Status
= SubmitForFormSet (FormSet
, FALSE
);
3292 Status
= SubmitForSystem ();
3296 Status
= EFI_UNSUPPORTED
;
3304 Get Question default value from AltCfg string.
3306 @param FormSet The form set.
3307 @param Question The question.
3308 @param DefaultId The default Id.
3310 @retval EFI_SUCCESS Question is reset to default value.
3314 GetDefaultValueFromAltCfg (
3315 IN FORM_BROWSER_FORMSET
*FormSet
,
3316 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3320 BOOLEAN IsBufferStorage
;
3323 BROWSER_STORAGE
*Storage
;
3324 CHAR16
*ConfigRequest
;
3337 Status
= EFI_NOT_FOUND
;
3340 ConfigRequest
= NULL
;
3344 Storage
= Question
->Storage
;
3346 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3351 // Question Value is provided by Buffer Storage or NameValue Storage
3353 if (Question
->BufferValue
!= NULL
) {
3355 // This Question is password or orderedlist
3357 Dst
= Question
->BufferValue
;
3360 // Other type of Questions
3362 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
3365 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3366 IsBufferStorage
= TRUE
;
3368 IsBufferStorage
= FALSE
;
3370 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
3373 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
3374 // <ConfigHdr> + "&" + <VariableName>
3376 if (IsBufferStorage
) {
3377 Length
= StrLen (Storage
->ConfigHdr
);
3378 Length
+= StrLen (Question
->BlockName
);
3380 Length
= StrLen (Storage
->ConfigHdr
);
3381 Length
+= StrLen (Question
->VariableName
) + 1;
3383 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
3384 ASSERT (ConfigRequest
!= NULL
);
3386 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
3387 if (IsBufferStorage
) {
3388 StrCat (ConfigRequest
, Question
->BlockName
);
3390 StrCat (ConfigRequest
, L
"&");
3391 StrCat (ConfigRequest
, Question
->VariableName
);
3394 Status
= mHiiConfigRouting
->ExtractConfig (
3400 if (EFI_ERROR (Status
)) {
3405 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
3406 // Get the default configuration string according to the default ID.
3408 Status
= mHiiConfigRouting
->GetAltConfig (
3414 &DefaultId
, // it can be NULL to get the current setting.
3419 // The required setting can't be found. So, it is not required to be validated and set.
3421 if (EFI_ERROR (Status
)) {
3425 if (ConfigResp
== NULL
) {
3426 Status
= EFI_NOT_FOUND
;
3431 // Skip <ConfigRequest>
3433 if (IsBufferStorage
) {
3434 Value
= StrStr (ConfigResp
, L
"&VALUE");
3435 ASSERT (Value
!= NULL
);
3441 Value
= StrStr (ConfigResp
, Question
->VariableName
);
3442 ASSERT (Value
!= NULL
);
3444 Value
= Value
+ StrLen (Question
->VariableName
);
3446 if (*Value
!= '=') {
3447 Status
= EFI_NOT_FOUND
;
3451 // Skip '=', point to value
3456 // Suppress <AltResp> if any
3459 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3464 LengthStr
= StrLen (Value
);
3465 if (!IsBufferStorage
&& IsString
) {
3466 StringPtr
= (CHAR16
*) Dst
;
3467 ZeroMem (TemStr
, sizeof (TemStr
));
3468 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
3469 StrnCpy (TemStr
, Value
+ Index
, 4);
3470 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
3473 // Add tailing L'\0' character
3475 StringPtr
[Index
/4] = L
'\0';
3477 ZeroMem (TemStr
, sizeof (TemStr
));
3478 for (Index
= 0; Index
< LengthStr
; Index
++) {
3479 TemStr
[0] = Value
[LengthStr
- Index
- 1];
3480 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
3481 if ((Index
& 1) == 0) {
3482 Dst
[Index
/2] = DigitUint8
;
3484 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
3490 if (ConfigRequest
!= NULL
){
3491 FreePool (ConfigRequest
);
3494 if (ConfigResp
!= NULL
) {
3495 FreePool (ConfigResp
);
3498 if (Result
!= NULL
) {
3506 Get default Id value used for browser.
3508 @param DefaultId The default id value used by hii.
3510 @retval Browser used default value.
3514 GetDefaultIdForCallBack (
3518 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3519 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3520 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3521 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3522 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3523 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3524 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3525 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3526 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3527 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3528 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3529 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3538 Return data element in an Array by its Index.
3540 @param Array The data array.
3541 @param Type Type of the data in this array.
3542 @param Index Zero based index for data in this array.
3544 @retval Value The data to be returned
3556 ASSERT (Array
!= NULL
);
3560 case EFI_IFR_TYPE_NUM_SIZE_8
:
3561 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3564 case EFI_IFR_TYPE_NUM_SIZE_16
:
3565 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3568 case EFI_IFR_TYPE_NUM_SIZE_32
:
3569 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3572 case EFI_IFR_TYPE_NUM_SIZE_64
:
3573 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3585 Set value of a 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.
3590 @param Value The value to be set.
3602 ASSERT (Array
!= NULL
);
3605 case EFI_IFR_TYPE_NUM_SIZE_8
:
3606 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3609 case EFI_IFR_TYPE_NUM_SIZE_16
:
3610 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3613 case EFI_IFR_TYPE_NUM_SIZE_32
:
3614 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3617 case EFI_IFR_TYPE_NUM_SIZE_64
:
3618 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3627 Search an Option of a Question by its value.
3629 @param Question The Question
3630 @param OptionValue Value for Option to be searched.
3632 @retval Pointer Pointer to the found Option.
3633 @retval NULL Option not found.
3638 IN FORM_BROWSER_STATEMENT
*Question
,
3639 IN EFI_HII_VALUE
*OptionValue
3643 QUESTION_OPTION
*Option
;
3646 Link
= GetFirstNode (&Question
->OptionListHead
);
3647 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3648 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3650 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3652 // Check the suppressif condition, only a valid option can be return.
3654 if ((Option
->SuppressExpression
== NULL
) ||
3655 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3660 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3668 Reset Question to its default value.
3670 @param FormSet The form set.
3671 @param Form The form.
3672 @param Question The question.
3673 @param DefaultId The Class of the default.
3675 @retval EFI_SUCCESS Question is reset to default value.
3679 GetQuestionDefault (
3680 IN FORM_BROWSER_FORMSET
*FormSet
,
3681 IN FORM_BROWSER_FORM
*Form
,
3682 IN FORM_BROWSER_STATEMENT
*Question
,
3688 QUESTION_DEFAULT
*Default
;
3689 QUESTION_OPTION
*Option
;
3690 EFI_HII_VALUE
*HiiValue
;
3692 EFI_STRING StrValue
;
3693 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3694 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3698 Status
= EFI_NOT_FOUND
;
3702 // Statement don't have storage, skip them
3704 if (Question
->QuestionId
== 0) {
3709 // There are Five ways to specify default value for a Question:
3710 // 1, use call back function (highest priority)
3711 // 2, use ExtractConfig function
3712 // 3, use nested EFI_IFR_DEFAULT
3713 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3714 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3716 HiiValue
= &Question
->HiiValue
;
3719 // Get Question defaut value from call back function.
3721 ConfigAccess
= FormSet
->ConfigAccess
;
3722 Action
= GetDefaultIdForCallBack (DefaultId
);
3723 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3724 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3725 Status
= ConfigAccess
->Callback (
3728 Question
->QuestionId
,
3733 if (!EFI_ERROR (Status
)) {
3734 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3735 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3736 ASSERT (NewString
!= NULL
);
3738 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3739 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3740 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3742 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3745 FreePool (NewString
);
3752 // Get default value from altcfg string.
3754 if (ConfigAccess
!= NULL
) {
3755 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3756 if (!EFI_ERROR (Status
)) {
3762 // EFI_IFR_DEFAULT has highest priority
3764 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3765 Link
= GetFirstNode (&Question
->DefaultListHead
);
3766 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3767 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3769 if (Default
->DefaultId
== DefaultId
) {
3770 if (Default
->ValueExpression
!= NULL
) {
3772 // Default is provided by an Expression, evaluate it
3774 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3775 if (EFI_ERROR (Status
)) {
3779 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3780 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3781 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3782 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3783 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3785 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3786 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3788 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3790 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3791 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3794 // Default value is embedded in EFI_IFR_DEFAULT
3796 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3799 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3800 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3801 if (StrValue
== NULL
) {
3802 return EFI_NOT_FOUND
;
3804 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3805 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3807 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3814 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3819 // EFI_ONE_OF_OPTION
3821 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3822 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3824 // OneOfOption could only provide Standard and Manufacturing default
3826 Link
= GetFirstNode (&Question
->OptionListHead
);
3827 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3828 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3829 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3831 if ((Option
->SuppressExpression
!= NULL
) &&
3832 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3836 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3837 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3839 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3848 // EFI_IFR_CHECKBOX - lowest priority
3850 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3851 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3853 // Checkbox could only provide Standard and Manufacturing default
3855 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3856 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3858 HiiValue
->Value
.b
= TRUE
;
3860 HiiValue
->Value
.b
= FALSE
;
3868 // For Questions without default
3870 Status
= EFI_NOT_FOUND
;
3871 switch (Question
->Operand
) {
3872 case EFI_IFR_NUMERIC_OP
:
3874 // Take minimum value as numeric default value
3876 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3877 HiiValue
->Value
.u64
= Question
->Minimum
;
3878 Status
= EFI_SUCCESS
;
3882 case EFI_IFR_ONE_OF_OP
:
3884 // Take first oneof option as oneof's default value
3886 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3887 Link
= GetFirstNode (&Question
->OptionListHead
);
3888 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3889 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3890 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3892 if ((Option
->SuppressExpression
!= NULL
) &&
3893 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3897 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3898 Status
= EFI_SUCCESS
;
3904 case EFI_IFR_ORDERED_LIST_OP
:
3906 // Take option sequence in IFR as ordered list's default value
3909 Link
= GetFirstNode (&Question
->OptionListHead
);
3910 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3911 Status
= EFI_SUCCESS
;
3912 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3913 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3915 if ((Option
->SuppressExpression
!= NULL
) &&
3916 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3920 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3923 if (Index
>= Question
->MaxContainers
) {
3938 Reset Questions to their initial value or default value in a Form, Formset or System.
3940 GetDefaultValueScope parameter decides which questions will reset
3941 to its default value.
3943 @param FormSet FormSet data structure.
3944 @param Form Form data structure.
3945 @param DefaultId The Class of the default.
3946 @param SettingScope Setting Scope for Default action.
3947 @param GetDefaultValueScope Get default value scope.
3948 @param Storage Get default value only for this storage.
3949 @param RetrieveValueFirst Whether call the retrieve call back to
3950 get the initial value before get default
3953 @retval EFI_SUCCESS The function completed successfully.
3954 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3959 IN FORM_BROWSER_FORMSET
*FormSet
,
3960 IN FORM_BROWSER_FORM
*Form
,
3961 IN UINT16 DefaultId
,
3962 IN BROWSER_SETTING_SCOPE SettingScope
,
3963 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3964 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3965 IN BOOLEAN RetrieveValueFirst
3969 LIST_ENTRY
*FormLink
;
3971 FORM_BROWSER_STATEMENT
*Question
;
3972 FORM_BROWSER_FORMSET
*LocalFormSet
;
3973 FORM_BROWSER_FORMSET
*OldFormSet
;
3975 Status
= EFI_SUCCESS
;
3978 // Check the supported setting level.
3980 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3981 return EFI_UNSUPPORTED
;
3984 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3985 return EFI_UNSUPPORTED
;
3988 if (SettingScope
== FormLevel
) {
3990 // Extract Form default
3992 Link
= GetFirstNode (&Form
->StatementListHead
);
3993 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3994 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3995 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3998 // If get default value only for this storage, check the storage first.
4000 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4005 // If get default value only for no storage question, just skip the question which has storage.
4007 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4012 // If Question is disabled, don't reset it to default
4014 if (Question
->Expression
!= NULL
) {
4015 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4020 if (RetrieveValueFirst
) {
4022 // Call the Retrieve call back to get the initial question value.
4024 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4028 // If not request to get the initial value or get initial value fail, then get default value.
4030 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4031 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4032 if (EFI_ERROR (Status
)) {
4038 // Synchronize Buffer storage's Edit buffer
4040 if ((Question
->Storage
!= NULL
) &&
4041 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4042 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4045 } else if (SettingScope
== FormSetLevel
) {
4046 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4047 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4048 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4049 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4050 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4052 } else if (SettingScope
== SystemLevel
) {
4054 // Preload all Hii formset.
4056 LoadAllHiiFormset();
4058 OldFormSet
= mSystemLevelFormSet
;
4061 // Set Default Value for each FormSet in the maintain list.
4063 Link
= GetFirstNode (&gBrowserFormSetList
);
4064 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4065 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4066 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4067 if (!ValidateFormSet(LocalFormSet
)) {
4071 mSystemLevelFormSet
= LocalFormSet
;
4073 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4076 mSystemLevelFormSet
= OldFormSet
;
4084 Validate whether this question's value has changed.
4086 @param FormSet FormSet data structure.
4087 @param Form Form data structure.
4088 @param Question Question to be initialized.
4089 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4091 @retval TRUE Question's value has changed.
4092 @retval FALSE Question's value has not changed
4096 IsQuestionValueChanged (
4097 IN FORM_BROWSER_FORMSET
*FormSet
,
4098 IN FORM_BROWSER_FORM
*Form
,
4099 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4100 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4103 EFI_HII_VALUE BackUpValue
;
4104 CHAR8
*BackUpBuffer
;
4105 EFI_HII_VALUE BackUpValue2
;
4106 CHAR8
*BackUpBuffer2
;
4108 BOOLEAN ValueChanged
;
4112 // For quetion without storage, always mark it as data not changed.
4114 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4118 BackUpBuffer
= NULL
;
4119 BackUpBuffer2
= NULL
;
4120 ValueChanged
= FALSE
;
4122 switch (Question
->Operand
) {
4123 case EFI_IFR_ORDERED_LIST_OP
:
4124 BufferWidth
= Question
->StorageWidth
;
4125 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4126 ASSERT (BackUpBuffer
!= NULL
);
4129 case EFI_IFR_STRING_OP
:
4130 case EFI_IFR_PASSWORD_OP
:
4131 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4132 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4133 ASSERT (BackUpBuffer
!= NULL
);
4140 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4142 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4143 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4144 ASSERT_EFI_ERROR(Status
);
4146 switch (Question
->Operand
) {
4147 case EFI_IFR_ORDERED_LIST_OP
:
4148 BufferWidth
= Question
->StorageWidth
;
4149 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4150 ASSERT (BackUpBuffer2
!= NULL
);
4153 case EFI_IFR_STRING_OP
:
4154 case EFI_IFR_PASSWORD_OP
:
4155 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4156 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4157 ASSERT (BackUpBuffer2
!= NULL
);
4164 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4166 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4167 ASSERT_EFI_ERROR(Status
);
4169 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4170 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4171 ValueChanged
= TRUE
;
4174 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4175 ASSERT_EFI_ERROR(Status
);
4177 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4178 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4179 ValueChanged
= TRUE
;
4183 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4184 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4186 if (BackUpBuffer
!= NULL
) {
4187 FreePool (BackUpBuffer
);
4190 if (BackUpBuffer2
!= NULL
) {
4191 FreePool (BackUpBuffer2
);
4194 Question
->ValueChanged
= ValueChanged
;
4196 return ValueChanged
;
4200 Initialize Question's Edit copy from Storage.
4202 @param Selection Selection contains the information about
4203 the Selection, form and formset to be displayed.
4204 Selection action may be updated in retrieve callback.
4205 If Selection is NULL, only initialize Question value.
4206 @param FormSet FormSet data structure.
4207 @param Form Form data structure.
4209 @retval EFI_SUCCESS The function completed successfully.
4214 IN OUT UI_MENU_SELECTION
*Selection
,
4215 IN FORM_BROWSER_FORMSET
*FormSet
,
4216 IN FORM_BROWSER_FORM
*Form
4221 FORM_BROWSER_STATEMENT
*Question
;
4223 Link
= GetFirstNode (&Form
->StatementListHead
);
4224 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4225 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4228 // Initialize local copy of Value for each Question
4230 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4231 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4233 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4235 if (EFI_ERROR (Status
)) {
4239 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4240 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4243 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4250 Initialize Question's Edit copy from Storage for the whole Formset.
4252 @param Selection Selection contains the information about
4253 the Selection, form and formset to be displayed.
4254 Selection action may be updated in retrieve callback.
4255 If Selection is NULL, only initialize Question value.
4256 @param FormSet FormSet data structure.
4258 @retval EFI_SUCCESS The function completed successfully.
4263 IN OUT UI_MENU_SELECTION
*Selection
,
4264 IN FORM_BROWSER_FORMSET
*FormSet
4269 FORM_BROWSER_FORM
*Form
;
4271 Link
= GetFirstNode (&FormSet
->FormListHead
);
4272 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4273 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4276 // Initialize local copy of Value for each Form
4278 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4279 if (EFI_ERROR (Status
)) {
4283 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4287 // Finished question initialization.
4289 FormSet
->QuestionInited
= TRUE
;
4295 Remove the Request element from the Config Request.
4297 @param Storage Pointer to the browser storage.
4298 @param RequestElement The pointer to the Request element.
4303 IN OUT BROWSER_STORAGE
*Storage
,
4304 IN CHAR16
*RequestElement
4310 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4312 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4314 if (NewStr
== NULL
) {
4319 // Remove this element from this ConfigRequest.
4322 NewStr
+= StrLen (RequestElement
);
4323 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4325 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4329 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4331 @param Storage Pointer to the browser storage.
4332 @param ConfigRequest The pointer to the Request element.
4336 RemoveConfigRequest (
4337 BROWSER_STORAGE
*Storage
,
4338 CHAR16
*ConfigRequest
4341 CHAR16
*RequestElement
;
4342 CHAR16
*NextRequestElement
;
4346 // No request element in it, just return.
4348 if (ConfigRequest
== NULL
) {
4352 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4354 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4359 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4361 SearchKey
= L
"&OFFSET";
4365 // Find SearchKey storage
4367 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4368 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4369 ASSERT (RequestElement
!= NULL
);
4370 RequestElement
= StrStr (RequestElement
, SearchKey
);
4372 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4375 while (RequestElement
!= NULL
) {
4377 // +1 to avoid find header itself.
4379 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4382 // The last Request element in configRequest string.
4384 if (NextRequestElement
!= NULL
) {
4386 // Replace "&" with '\0'.
4388 *NextRequestElement
= L
'\0';
4391 RemoveElement (Storage
, RequestElement
);
4393 if (NextRequestElement
!= NULL
) {
4395 // Restore '&' with '\0' for later used.
4397 *NextRequestElement
= L
'&';
4400 RequestElement
= NextRequestElement
;
4404 // If no request element remain, just remove the ConfigRequest string.
4406 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4407 FreePool (Storage
->ConfigRequest
);
4408 Storage
->ConfigRequest
= NULL
;
4409 Storage
->SpareStrLen
= 0;
4414 Base on the current formset info, clean the ConfigRequest string in browser storage.
4416 @param FormSet Pointer of the FormSet
4420 CleanBrowserStorage (
4421 IN OUT FORM_BROWSER_FORMSET
*FormSet
4425 FORMSET_STORAGE
*Storage
;
4427 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4428 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4429 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4430 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4432 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4433 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4437 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4438 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4439 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4440 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4441 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4442 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4444 Storage
->BrowserStorage
->Initialized
= FALSE
;
4450 Check whether current element in the ConfigReqeust string.
4452 @param BrowserStorage Storage which includes ConfigReqeust.
4453 @param RequestElement New element need to check.
4455 @retval TRUE The Element is in the ConfigReqeust string.
4456 @retval FALSE The Element not in the configReqeust String.
4461 BROWSER_STORAGE
*BrowserStorage
,
4462 CHAR16
*RequestElement
4465 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4469 Append the Request element to the Config Request.
4471 @param ConfigRequest Current ConfigRequest info.
4472 @param SpareStrLen Current remain free buffer for config reqeust.
4473 @param RequestElement New Request element.
4477 AppendConfigRequest (
4478 IN OUT CHAR16
**ConfigRequest
,
4479 IN OUT UINTN
*SpareStrLen
,
4480 IN CHAR16
*RequestElement
4487 StrLength
= StrLen (RequestElement
);
4490 // Append <RequestElement> to <ConfigRequest>
4492 if (StrLength
> *SpareStrLen
) {
4494 // Old String buffer is not sufficient for RequestElement, allocate a new one
4496 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4497 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4498 ASSERT (NewStr
!= NULL
);
4500 if (*ConfigRequest
!= NULL
) {
4501 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4502 FreePool (*ConfigRequest
);
4504 *ConfigRequest
= NewStr
;
4505 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4508 StrCat (*ConfigRequest
, RequestElement
);
4509 *SpareStrLen
-= StrLength
;
4513 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4515 @param Storage Form set Storage.
4516 @param Request The input request string.
4517 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4519 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4520 @retval FALSE All elements covered by current used elements.
4524 ConfigRequestAdjust (
4525 IN BROWSER_STORAGE
*Storage
,
4527 IN BOOLEAN RespString
4530 CHAR16
*RequestElement
;
4531 CHAR16
*NextRequestElement
;
4532 CHAR16
*NextElementBakup
;
4537 CHAR16
*ConfigRequest
;
4541 NextElementBakup
= NULL
;
4544 if (Request
!= NULL
) {
4545 ConfigRequest
= Request
;
4547 ConfigRequest
= Storage
->ConfigRequest
;
4550 if (Storage
->ConfigRequest
== NULL
) {
4551 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4555 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4557 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4562 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4564 SearchKey
= L
"&OFFSET";
4565 ValueKey
= L
"&VALUE";
4569 // Find SearchKey storage
4571 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4572 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4573 ASSERT (RequestElement
!= NULL
);
4574 RequestElement
= StrStr (RequestElement
, SearchKey
);
4576 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4579 while (RequestElement
!= NULL
) {
4582 // +1 to avoid find header itself.
4584 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4587 // The last Request element in configRequest string.
4589 if (NextRequestElement
!= NULL
) {
4590 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4591 NextElementBakup
= NextRequestElement
;
4592 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4593 ASSERT (NextRequestElement
!= NULL
);
4596 // Replace "&" with '\0'.
4598 *NextRequestElement
= L
'\0';
4600 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4601 NextElementBakup
= NextRequestElement
;
4602 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4603 ASSERT (NextRequestElement
!= NULL
);
4605 // Replace "&" with '\0'.
4607 *NextRequestElement
= L
'\0';
4611 if (!ElementValidation (Storage
, RequestElement
)) {
4613 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4615 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4619 if (NextRequestElement
!= NULL
) {
4621 // Restore '&' with '\0' for later used.
4623 *NextRequestElement
= L
'&';
4626 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4627 RequestElement
= NextElementBakup
;
4629 RequestElement
= NextRequestElement
;
4638 Base on ConfigRequest info to get default value for current formset.
4640 ConfigRequest info include the info about which questions in current formset need to
4641 get default value. This function only get these questions default value.
4643 @param FormSet FormSet data structure.
4644 @param Storage Storage need to update value.
4645 @param ConfigRequest The config request string.
4649 GetDefaultForFormset (
4650 IN FORM_BROWSER_FORMSET
*FormSet
,
4651 IN BROWSER_STORAGE
*Storage
,
4652 IN CHAR16
*ConfigRequest
4657 LIST_ENTRY BackUpList
;
4658 NAME_VALUE_NODE
*Node
;
4660 LIST_ENTRY
*NodeLink
;
4661 NAME_VALUE_NODE
*TmpNode
;
4663 EFI_STRING Progress
;
4667 InitializeListHead(&BackUpList
);
4670 // Back update the edit buffer.
4672 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4673 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4674 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4675 ASSERT (BackUpBuf
!= NULL
);
4676 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4677 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4678 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4679 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4680 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4683 // Only back Node belong to this formset.
4685 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4689 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4690 ASSERT (TmpNode
!= NULL
);
4691 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4692 ASSERT (TmpNode
->Name
!= NULL
);
4693 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4694 ASSERT (TmpNode
->EditValue
!= NULL
);
4696 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4701 // Get default value.
4703 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4706 // Update the question value based on the input ConfigRequest.
4708 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4709 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4710 ASSERT (BackUpBuf
!= NULL
);
4711 BufferSize
= Storage
->Size
;
4712 Status
= mHiiConfigRouting
->BlockToConfig(
4715 Storage
->EditBuffer
,
4720 ASSERT_EFI_ERROR (Status
);
4722 Status
= mHiiConfigRouting
->ConfigToBlock (
4729 ASSERT_EFI_ERROR (Status
);
4731 if (Result
!= NULL
) {
4735 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4736 FreePool (BackUpBuf
);
4737 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4739 // Update question value, only element in ConfigReqeust will be update.
4741 Link
= GetFirstNode (&BackUpList
);
4742 while (!IsNull (&BackUpList
, Link
)) {
4743 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4744 Link
= GetNextNode (&BackUpList
, Link
);
4746 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4750 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4751 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4752 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4753 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4755 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4759 FreePool (TmpNode
->EditValue
);
4760 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4762 RemoveEntryList (&Node
->Link
);
4763 FreePool (Node
->EditValue
);
4764 FreePool (Node
->Name
);
4770 // Restore the Name/Value node.
4772 Link
= GetFirstNode (&BackUpList
);
4773 while (!IsNull (&BackUpList
, Link
)) {
4774 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4775 Link
= GetNextNode (&BackUpList
, Link
);
4780 RemoveEntryList (&Node
->Link
);
4781 FreePool (Node
->EditValue
);
4782 FreePool (Node
->Name
);
4789 Fill storage's edit copy with settings requested from Configuration Driver.
4791 @param FormSet FormSet data structure.
4792 @param Storage Buffer Storage.
4797 IN FORM_BROWSER_FORMSET
*FormSet
,
4798 IN FORMSET_STORAGE
*Storage
4802 EFI_STRING Progress
;
4805 EFI_STRING ConfigRequest
;
4808 ConfigRequest
= NULL
;
4810 switch (Storage
->BrowserStorage
->Type
) {
4811 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4814 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4815 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4816 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4821 case EFI_HII_VARSTORE_BUFFER
:
4822 case EFI_HII_VARSTORE_NAME_VALUE
:
4824 // Skip if there is no RequestElement.
4826 if (Storage
->ElementCount
== 0) {
4831 // Just update the ConfigRequest, if storage already initialized.
4833 if (Storage
->BrowserStorage
->Initialized
) {
4834 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4838 Storage
->BrowserStorage
->Initialized
= TRUE
;
4845 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4847 // Create the config request string to get all fields for this storage.
4848 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4849 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4851 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4852 ConfigRequest
= AllocateZeroPool (StrLen
);
4853 ASSERT (ConfigRequest
!= NULL
);
4857 L
"%s&OFFSET=0&WIDTH=%04x",
4858 Storage
->BrowserStorage
->ConfigHdr
,
4859 Storage
->BrowserStorage
->Size
);
4861 ConfigRequest
= Storage
->ConfigRequest
;
4865 // Request current settings from Configuration Driver
4867 Status
= mHiiConfigRouting
->ExtractConfig (
4875 // If get value fail, extract default from IFR binary
4877 if (EFI_ERROR (Status
)) {
4878 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4881 // Convert Result from <ConfigAltResp> to <ConfigResp>
4883 StrPtr
= StrStr (Result
, L
"&GUID=");
4884 if (StrPtr
!= NULL
) {
4888 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4892 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4895 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4897 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
4899 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4900 if (ConfigRequest
!= NULL
) {
4901 FreePool (ConfigRequest
);
4907 Get Value changed status from old question.
4909 @param NewFormSet FormSet data structure.
4910 @param OldQuestion Old question which has value changed.
4914 SyncStatusForQuestion (
4915 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4916 IN FORM_BROWSER_STATEMENT
*OldQuestion
4920 LIST_ENTRY
*QuestionLink
;
4921 FORM_BROWSER_FORM
*Form
;
4922 FORM_BROWSER_STATEMENT
*Question
;
4925 // For each form in one formset.
4927 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4928 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4929 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4930 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4933 // for each question in one form.
4935 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4936 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4937 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4938 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4940 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4941 Question
->ValueChanged
= TRUE
;
4949 Get Value changed status from old formset.
4951 @param NewFormSet FormSet data structure.
4952 @param OldFormSet FormSet data structure.
4956 SyncStatusForFormSet (
4957 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4958 IN FORM_BROWSER_FORMSET
*OldFormSet
4962 LIST_ENTRY
*QuestionLink
;
4963 FORM_BROWSER_FORM
*Form
;
4964 FORM_BROWSER_STATEMENT
*Question
;
4967 // For each form in one formset.
4969 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4970 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4971 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4972 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4975 // for each question in one form.
4977 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4978 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4979 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4980 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4982 if (!Question
->ValueChanged
) {
4987 // Find the same question in new formset and update the value changed flag.
4989 SyncStatusForQuestion (NewFormSet
, Question
);
4995 Get current setting of Questions.
4997 @param FormSet FormSet data structure.
5001 InitializeCurrentSetting (
5002 IN OUT FORM_BROWSER_FORMSET
*FormSet
5006 FORMSET_STORAGE
*Storage
;
5007 FORM_BROWSER_FORMSET
*OldFormSet
;
5010 // Try to find pre FormSet in the maintain backup list.
5011 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5013 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5014 if (OldFormSet
!= NULL
) {
5015 SyncStatusForFormSet (FormSet
, OldFormSet
);
5016 RemoveEntryList (&OldFormSet
->Link
);
5017 DestroyFormSet (OldFormSet
);
5019 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5022 // Extract default from IFR binary for no storage questions.
5024 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
5027 // Request current settings from Configuration Driver
5029 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5030 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5031 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5033 LoadStorage (FormSet
, Storage
);
5035 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5041 Fetch the Ifr binary data of a FormSet.
5043 @param Handle PackageList Handle
5044 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5045 specified (NULL or zero GUID), take the first
5046 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5047 found in package list.
5048 On output, GUID of the formset found(if not NULL).
5049 @param BinaryLength The length of the FormSet IFR binary.
5050 @param BinaryData The buffer designed to receive the FormSet.
5052 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5053 BufferLength was updated.
5054 @retval EFI_INVALID_PARAMETER The handle is unknown.
5055 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5056 be found with the requested FormId.
5061 IN EFI_HII_HANDLE Handle
,
5062 IN OUT EFI_GUID
*FormSetGuid
,
5063 OUT UINTN
*BinaryLength
,
5064 OUT UINT8
**BinaryData
5068 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5074 UINT32 PackageListLength
;
5075 EFI_HII_PACKAGE_HEADER PackageHeader
;
5077 UINT8 NumberOfClassGuid
;
5078 BOOLEAN ClassGuidMatch
;
5079 EFI_GUID
*ClassGuid
;
5080 EFI_GUID
*ComparingGuid
;
5084 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5087 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5089 if (FormSetGuid
== NULL
) {
5090 ComparingGuid
= &gZeroGuid
;
5092 ComparingGuid
= FormSetGuid
;
5096 // Get HII PackageList
5099 HiiPackageList
= NULL
;
5100 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5101 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5102 HiiPackageList
= AllocatePool (BufferSize
);
5103 ASSERT (HiiPackageList
!= NULL
);
5105 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5107 if (EFI_ERROR (Status
)) {
5110 ASSERT (HiiPackageList
!= NULL
);
5113 // Get Form package from this HII package List
5115 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5117 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5119 ClassGuidMatch
= FALSE
;
5120 while (Offset
< PackageListLength
) {
5121 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5122 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5124 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5126 // Search FormSet in this Form Package
5128 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5129 while (Offset2
< PackageHeader
.Length
) {
5130 OpCodeData
= Package
+ Offset2
;
5132 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5134 // Try to compare against formset GUID
5136 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5137 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5141 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5143 // Try to compare against formset class GUID
5145 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5146 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5147 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5148 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5149 ClassGuidMatch
= TRUE
;
5153 if (ClassGuidMatch
) {
5156 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5157 ClassGuidMatch
= TRUE
;
5162 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5165 if (Offset2
< PackageHeader
.Length
) {
5167 // Target formset found
5173 Offset
+= PackageHeader
.Length
;
5176 if (Offset
>= PackageListLength
) {
5178 // Form package not found in this Package List
5180 FreePool (HiiPackageList
);
5181 return EFI_NOT_FOUND
;
5184 if (FormSetGuid
!= NULL
) {
5186 // Return the FormSet GUID
5188 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5192 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5193 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5194 // of the Form Package.
5196 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5197 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5199 FreePool (HiiPackageList
);
5201 if (*BinaryData
== NULL
) {
5202 return EFI_OUT_OF_RESOURCES
;
5210 Initialize the internal data structure of a FormSet.
5212 @param Handle PackageList Handle
5213 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5214 specified (NULL or zero GUID), take the first
5215 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5216 found in package list.
5217 On output, GUID of the formset found(if not NULL).
5218 @param FormSet FormSet data structure.
5220 @retval EFI_SUCCESS The function completed successfully.
5221 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5226 IN EFI_HII_HANDLE Handle
,
5227 IN OUT EFI_GUID
*FormSetGuid
,
5228 OUT FORM_BROWSER_FORMSET
*FormSet
5232 EFI_HANDLE DriverHandle
;
5234 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5235 if (EFI_ERROR (Status
)) {
5239 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5240 FormSet
->HiiHandle
= Handle
;
5241 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5242 FormSet
->QuestionInited
= FALSE
;
5245 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5247 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5248 if (EFI_ERROR (Status
)) {
5251 FormSet
->DriverHandle
= DriverHandle
;
5252 Status
= gBS
->HandleProtocol (
5254 &gEfiHiiConfigAccessProtocolGuid
,
5255 (VOID
**) &FormSet
->ConfigAccess
5257 if (EFI_ERROR (Status
)) {
5259 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5260 // list, then there will be no configuration action required
5262 FormSet
->ConfigAccess
= NULL
;
5266 // Parse the IFR binary OpCodes
5268 Status
= ParseOpCodes (FormSet
);
5275 Save globals used by previous call to SendForm(). SendForm() may be called from
5276 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5277 So, save globals of previous call to SendForm() and restore them upon exit.
5281 SaveBrowserContext (
5285 BROWSER_CONTEXT
*Context
;
5286 FORM_ENTRY_INFO
*MenuList
;
5288 gBrowserContextCount
++;
5289 if (gBrowserContextCount
== 1) {
5291 // This is not reentry of SendForm(), no context to save
5296 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5297 ASSERT (Context
!= NULL
);
5299 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5302 // Save FormBrowser context
5304 Context
->Selection
= gCurrentSelection
;
5305 Context
->ResetRequired
= gResetRequired
;
5306 Context
->ExitRequired
= gExitRequired
;
5307 Context
->HiiHandle
= mCurrentHiiHandle
;
5308 Context
->FormId
= mCurrentFormId
;
5309 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5312 // Save the menu history data.
5314 InitializeListHead(&Context
->FormHistoryList
);
5315 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5316 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5317 RemoveEntryList (&MenuList
->Link
);
5319 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5323 // Insert to FormBrowser context list
5325 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5330 Restore globals used by previous call to SendForm().
5334 RestoreBrowserContext (
5339 BROWSER_CONTEXT
*Context
;
5340 FORM_ENTRY_INFO
*MenuList
;
5342 ASSERT (gBrowserContextCount
!= 0);
5343 gBrowserContextCount
--;
5344 if (gBrowserContextCount
== 0) {
5346 // This is not reentry of SendForm(), no context to restore
5351 ASSERT (!IsListEmpty (&gBrowserContextList
));
5353 Link
= GetFirstNode (&gBrowserContextList
);
5354 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5357 // Restore FormBrowser context
5359 gCurrentSelection
= Context
->Selection
;
5360 gResetRequired
= Context
->ResetRequired
;
5361 gExitRequired
= Context
->ExitRequired
;
5362 mCurrentHiiHandle
= Context
->HiiHandle
;
5363 mCurrentFormId
= Context
->FormId
;
5364 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5367 // Restore the menu history data.
5369 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5370 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5371 RemoveEntryList (&MenuList
->Link
);
5373 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5377 // Remove from FormBrowser context list
5379 RemoveEntryList (&Context
->Link
);
5380 gBS
->FreePool (Context
);
5384 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5386 @param Handle The Hii Handle.
5388 @return the found FormSet context. If no found, NULL will return.
5391 FORM_BROWSER_FORMSET
*
5392 GetFormSetFromHiiHandle (
5393 EFI_HII_HANDLE Handle
5397 FORM_BROWSER_FORMSET
*FormSet
;
5399 Link
= GetFirstNode (&gBrowserFormSetList
);
5400 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5401 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5402 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5403 if (!ValidateFormSet(FormSet
)) {
5406 if (FormSet
->HiiHandle
== Handle
) {
5415 Check whether the input HII handle is the FormSet that is being used.
5417 @param Handle The Hii Handle.
5419 @retval TRUE HII handle is being used.
5420 @retval FALSE HII handle is not being used.
5424 IsHiiHandleInBrowserContext (
5425 EFI_HII_HANDLE Handle
5429 BROWSER_CONTEXT
*Context
;
5432 // HiiHandle is Current FormSet.
5434 if (mCurrentHiiHandle
== Handle
) {
5439 // Check whether HiiHandle is in BrowserContext.
5441 Link
= GetFirstNode (&gBrowserContextList
);
5442 while (!IsNull (&gBrowserContextList
, Link
)) {
5443 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5444 if (Context
->HiiHandle
== Handle
) {
5446 // HiiHandle is in BrowserContext
5450 Link
= GetNextNode (&gBrowserContextList
, Link
);
5457 Perform Password check.
5458 Passwork may be encrypted by driver that requires the specific check.
5460 @param Form Form where Password Statement is in.
5461 @param Statement Password statement
5462 @param PasswordString Password string to be checked. It may be NULL.
5463 NULL means to restore password.
5464 "" string can be used to checked whether old password does exist.
5466 @return Status Status of Password check.
5471 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5472 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5473 IN EFI_STRING PasswordString OPTIONAL
5477 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5478 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5479 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5480 FORM_BROWSER_STATEMENT
*Question
;
5482 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5483 Question
= GetBrowserStatement(Statement
);
5484 ASSERT (Question
!= NULL
);
5486 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5487 if (ConfigAccess
== NULL
) {
5488 return EFI_UNSUPPORTED
;
5491 if (PasswordString
== NULL
) {
5496 // Check whether has preexisted password.
5498 if (PasswordString
[0] == 0) {
5499 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5502 return EFI_NOT_READY
;
5507 // Check whether the input password is same as preexisted password.
5509 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5512 return EFI_NOT_READY
;
5517 // Prepare password string in HII database
5519 if (PasswordString
!= NULL
) {
5520 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5522 IfrTypeValue
.string
= 0;
5526 // Send password to Configuration Driver for validation
5528 Status
= ConfigAccess
->Callback (
5530 EFI_BROWSER_ACTION_CHANGING
,
5531 Question
->QuestionId
,
5532 Question
->HiiValue
.Type
,
5538 // Remove password string from HII database
5540 if (PasswordString
!= NULL
) {
5541 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5548 Find the registered HotKey based on KeyData.
5550 @param[in] KeyData A pointer to a buffer that describes the keystroke
5551 information for the hot key.
5553 @return The registered HotKey context. If no found, NULL will return.
5556 GetHotKeyFromRegisterList (
5557 IN EFI_INPUT_KEY
*KeyData
5561 BROWSER_HOT_KEY
*HotKey
;
5563 Link
= GetFirstNode (&gBrowserHotKeyList
);
5564 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5565 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5566 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5569 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5576 Configure what scope the hot key will impact.
5577 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5578 If no scope is set, the default scope will be FormSet level.
5579 After all registered hot keys are removed, previous Scope can reset to another level.
5581 @param[in] Scope Scope level to be set.
5583 @retval EFI_SUCCESS Scope is set correctly.
5584 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5585 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5591 IN BROWSER_SETTING_SCOPE Scope
5594 if (Scope
>= MaxLevel
) {
5595 return EFI_INVALID_PARAMETER
;
5599 // When no hot key registered in system or on the first setting,
5600 // Scope can be set.
5602 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5603 gBrowserSettingScope
= Scope
;
5604 mBrowserScopeFirstSet
= FALSE
;
5605 } else if (Scope
!= gBrowserSettingScope
) {
5606 return EFI_UNSUPPORTED
;
5613 Register the hot key with its browser action, or unregistered the hot key.
5614 Only support hot key that is not printable character (control key, function key, etc.).
5615 If the action value is zero, the hot key will be unregistered if it has been registered.
5616 If the same hot key has been registered, the new action and help string will override the previous ones.
5618 @param[in] KeyData A pointer to a buffer that describes the keystroke
5619 information for the hot key. Its type is EFI_INPUT_KEY to
5620 be supported by all ConsoleIn devices.
5621 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5622 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5623 @param[in] HelpString Help string that describes the hot key information.
5624 Its value may be NULL for the unregistered hot key.
5626 @retval EFI_SUCCESS Hot key is registered or unregistered.
5627 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5628 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5629 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5634 IN EFI_INPUT_KEY
*KeyData
,
5636 IN UINT16 DefaultId
,
5637 IN EFI_STRING HelpString OPTIONAL
5640 BROWSER_HOT_KEY
*HotKey
;
5643 // Check input parameters.
5645 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5646 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5647 return EFI_INVALID_PARAMETER
;
5651 // Check whether the input KeyData is in BrowserHotKeyList.
5653 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5656 // Unregister HotKey
5658 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5659 if (HotKey
!= NULL
) {
5661 // The registered HotKey is found.
5662 // Remove it from List, and free its resource.
5664 RemoveEntryList (&HotKey
->Link
);
5665 FreePool (HotKey
->KeyData
);
5666 FreePool (HotKey
->HelpString
);
5670 // The registered HotKey is not found.
5672 return EFI_NOT_FOUND
;
5677 // Register HotKey into List.
5679 if (HotKey
== NULL
) {
5681 // Create new Key, and add it into List.
5683 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5684 ASSERT (HotKey
!= NULL
);
5685 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5686 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5687 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5691 // Fill HotKey information.
5693 HotKey
->Action
= Action
;
5694 HotKey
->DefaultId
= DefaultId
;
5695 if (HotKey
->HelpString
!= NULL
) {
5696 FreePool (HotKey
->HelpString
);
5698 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5704 Register Exit handler function.
5705 When more than one handler function is registered, the latter one will override the previous one.
5706 When NULL handler is specified, the previous Exit handler will be unregistered.
5708 @param[in] Handler Pointer to handler function.
5713 RegiserExitHandler (
5714 IN EXIT_HANDLER Handler
5717 ExitHandlerFunction
= Handler
;
5722 Check whether the browser data has been modified.
5724 @retval TRUE Browser data is modified.
5725 @retval FALSE No browser data is modified.
5730 IsBrowserDataModified (
5735 FORM_BROWSER_FORMSET
*FormSet
;
5737 switch (gBrowserSettingScope
) {
5739 if (gCurrentSelection
== NULL
) {
5742 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5745 if (gCurrentSelection
== NULL
) {
5748 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5751 Link
= GetFirstNode (&gBrowserFormSetList
);
5752 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5753 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5754 if (!ValidateFormSet(FormSet
)) {
5758 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5761 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5771 Execute the action requested by the Action parameter.
5773 @param[in] Action Execute the request action.
5774 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5776 @retval EFI_SUCCESS Execute the request action succss.
5777 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5788 FORM_BROWSER_FORMSET
*FormSet
;
5789 FORM_BROWSER_FORM
*Form
;
5791 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5792 return EFI_NOT_READY
;
5795 Status
= EFI_SUCCESS
;
5798 if (gBrowserSettingScope
< SystemLevel
) {
5799 FormSet
= gCurrentSelection
->FormSet
;
5800 Form
= gCurrentSelection
->Form
;
5804 // Executet the discard action.
5806 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5807 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5808 if (EFI_ERROR (Status
)) {
5814 // Executet the difault action.
5816 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5817 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5818 if (EFI_ERROR (Status
)) {
5821 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5825 // Executet the submit action.
5827 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5828 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5829 if (EFI_ERROR (Status
)) {
5835 // Executet the reset action.
5837 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5838 gResetRequired
= TRUE
;
5842 // Executet the exit action.
5844 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5845 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5846 if (gBrowserSettingScope
== SystemLevel
) {
5847 if (ExitHandlerFunction
!= NULL
) {
5848 ExitHandlerFunction ();
5852 gExitRequired
= TRUE
;
5859 Create reminder to let user to choose save or discard the changed browser data.
5860 Caller can use it to actively check the changed browser data.
5862 @retval BROWSER_NO_CHANGES No browser data is changed.
5863 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5864 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5865 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5875 FORM_BROWSER_FORMSET
*FormSet
;
5876 BOOLEAN IsDataChanged
;
5877 UINT32 DataSavedAction
;
5880 DataSavedAction
= BROWSER_NO_CHANGES
;
5881 IsDataChanged
= FALSE
;
5882 Link
= GetFirstNode (&gBrowserFormSetList
);
5883 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5884 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5885 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5886 if (!ValidateFormSet(FormSet
)) {
5889 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5890 IsDataChanged
= TRUE
;
5896 // No data is changed. No save is required.
5898 if (!IsDataChanged
) {
5899 return DataSavedAction
;
5903 // If data is changed, prompt user to save or discard it.
5906 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5908 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5909 SubmitForm (NULL
, NULL
, SystemLevel
);
5910 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5912 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5913 DiscardForm (NULL
, NULL
, SystemLevel
);
5914 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5916 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5917 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5922 return DataSavedAction
;
5926 Check whether the Reset Required for the browser
5928 @retval TRUE Browser required to reset after exit.
5929 @retval FALSE Browser not need to reset after exit.
5938 return gResetRequired
;