2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
31 BROWSER_EXTENSION2_VERSION_1_1
,
35 IsBrowserDataModified
,
43 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
44 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
45 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
46 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
48 UINTN gBrowserContextCount
= 0;
49 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
50 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
51 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
52 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
53 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
55 BOOLEAN mSystemSubmit
= FALSE
;
56 BOOLEAN gResetRequired
;
57 BOOLEAN gExitRequired
;
58 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
59 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
60 EXIT_HANDLER ExitHandlerFunction
= NULL
;
61 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
64 // Browser Global Strings
67 CHAR16
*mUnknownString
= L
"!";
69 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
71 extern EFI_GUID mCurrentFormSetGuid
;
72 extern EFI_HII_HANDLE mCurrentHiiHandle
;
73 extern UINT16 mCurrentFormId
;
74 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
77 Create a menu with specified formset GUID and form ID, and add it as a child
78 of the given parent menu.
80 @param HiiHandle Hii handle related to this formset.
81 @param FormSetGuid The Formset Guid of menu to be added.
82 @param FormId The Form ID of menu to be added.
83 @param QuestionId The question id of this menu to be added.
85 @return A pointer to the newly added menu or NULL if memory is insufficient.
90 IN EFI_HII_HANDLE HiiHandle
,
91 IN EFI_GUID
*FormSetGuid
,
96 FORM_ENTRY_INFO
*MenuList
;
98 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
99 if (MenuList
== NULL
) {
103 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
105 MenuList
->HiiHandle
= HiiHandle
;
106 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
107 MenuList
->FormId
= FormId
;
108 MenuList
->QuestionId
= QuestionId
;
111 // If parent is not specified, it is the root Form of a Formset
113 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
119 Return the form id for the input hiihandle and formset.
121 @param HiiHandle HiiHandle for FormSet.
122 @param FormSetGuid The Formset GUID of the menu to search.
124 @return First form's id for this form set.
129 IN EFI_HII_HANDLE HiiHandle
,
130 IN EFI_GUID
*FormSetGuid
134 FORM_BROWSER_FORM
*Form
;
136 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
137 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
143 Search Menu with given FormSetGuid and FormId in all cached menu list.
145 @param HiiHandle HiiHandle for FormSet.
146 @param FormSetGuid The Formset GUID of the menu to search.
147 @param FormId The Form ID of menu to search.
149 @return A pointer to menu found or NULL if not found.
154 IN EFI_HII_HANDLE HiiHandle
,
155 IN EFI_GUID
*FormSetGuid
,
160 FORM_ENTRY_INFO
*MenuList
;
161 FORM_ENTRY_INFO
*RetMenu
;
162 EFI_FORM_ID FirstFormId
;
166 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
167 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
168 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
169 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
172 // If already find the menu, free the menus behind it.
174 if (RetMenu
!= NULL
) {
175 RemoveEntryList (&MenuList
->Link
);
181 // Find the same FromSet.
183 if (MenuList
->HiiHandle
== HiiHandle
) {
184 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
186 // FormSetGuid is not specified.
189 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
190 if (MenuList
->FormId
== FormId
) {
192 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
193 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
194 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
206 Find parent menu for current menu.
208 @param CurrentMenu Current Menu
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.
210 In form level, just find the parent menu;
211 In formset level, find the parent menu which has different
214 @retval The parent menu for current menu.
218 IN FORM_ENTRY_INFO
*CurrentMenu
,
219 IN BROWSER_SETTING_SCOPE SettingLevel
222 FORM_ENTRY_INFO
*ParentMenu
;
225 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
227 if (CurrentMenu
== NULL
) {
232 Link
= &CurrentMenu
->Link
;
234 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
235 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
237 if (SettingLevel
== FormLevel
) {
239 // For FormLevel, just find the parent menu, return.
244 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
246 // For SystemLevel, must find the menu which has different formset.
251 Link
= Link
->BackLink
;
255 // Not find the parent menu, just return NULL.
257 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
265 Free Menu list linked list.
267 @param MenuListHead One Menu list point in the menu list.
272 LIST_ENTRY
*MenuListHead
275 FORM_ENTRY_INFO
*MenuList
;
277 while (!IsListEmpty (MenuListHead
)) {
278 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
279 RemoveEntryList (&MenuList
->Link
);
286 Copy current Menu list to the new menu list.
288 @param NewMenuListHead New create Menu list.
289 @param CurrentMenuListHead Current Menu list.
294 OUT LIST_ENTRY
*NewMenuListHead
,
295 IN LIST_ENTRY
*CurrentMenuListHead
299 FORM_ENTRY_INFO
*MenuList
;
300 FORM_ENTRY_INFO
*NewMenuEntry
;
303 // If new menu list not empty, free it first.
305 UiFreeMenuList (NewMenuListHead
);
307 Link
= GetFirstNode (CurrentMenuListHead
);
308 while (!IsNull (CurrentMenuListHead
, Link
)) {
309 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
310 Link
= GetNextNode (CurrentMenuListHead
, Link
);
312 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
313 ASSERT (NewMenuEntry
!= NULL
);
314 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
315 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
316 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
317 NewMenuEntry
->FormId
= MenuList
->FormId
;
318 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
320 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
325 Load all hii formset to the browser.
333 FORM_BROWSER_FORMSET
*LocalFormSet
;
334 EFI_HII_HANDLE
*HiiHandles
;
338 FORM_BROWSER_FORMSET
*OldFormset
;
340 OldFormset
= mSystemLevelFormSet
;
343 // Get all the Hii handles
345 HiiHandles
= HiiGetHiiHandles (NULL
);
346 ASSERT (HiiHandles
!= NULL
);
349 // Search for formset of each class type
351 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
353 // Check HiiHandles[Index] does exist in global maintain list.
355 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
360 // Initilize FormSet Setting
362 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
363 ASSERT (LocalFormSet
!= NULL
);
364 mSystemLevelFormSet
= LocalFormSet
;
366 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
367 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
368 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
369 DestroyFormSet (LocalFormSet
);
372 InitializeCurrentSetting (LocalFormSet
);
375 // Initilize Questions' Value
377 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
378 if (EFI_ERROR (Status
)) {
379 DestroyFormSet (LocalFormSet
);
385 // Free resources, and restore gOldFormSet and gClassOfVfr
387 FreePool (HiiHandles
);
389 mSystemLevelFormSet
= OldFormset
;
393 Pop up the error info.
395 @param BrowserStatus The input browser status.
396 @param HiiHandle The Hiihandle for this opcode.
397 @param OpCode The opcode use to get the erro info and timeout value.
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
403 IN UINT32 BrowserStatus
,
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
406 IN CHAR16
*ErrorString
409 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
410 USER_INPUT UserInputData
;
414 if (OpCode
!= NULL
) {
415 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
416 ASSERT (Statement
!= NULL
);
417 Statement
->OpCode
= OpCode
;
418 gDisplayFormData
.HighLightedStatement
= Statement
;
422 // Used to compatible with old display engine.
423 // New display engine not use this field.
425 gDisplayFormData
.ErrorString
= ErrorString
;
426 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
428 if (HiiHandle
!= NULL
) {
429 gDisplayFormData
.HiiHandle
= HiiHandle
;
432 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
434 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
435 gDisplayFormData
.ErrorString
= NULL
;
437 if (OpCode
!= NULL
) {
438 FreePool (Statement
);
441 return UserInputData
.Action
;
445 This is the routine which an external caller uses to direct the browser
446 where to obtain it's information.
449 @param This The Form Browser protocol instanse.
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
451 display a list of the formsets for the handles specified.
452 @param HandleCount The number of Handles specified in Handle.
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
454 field in the EFI_IFR_FORM_SET op-code for the specified
455 forms-based package. If FormSetGuid is NULL, then this
456 function will display the first found forms package.
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first
458 displayable page. If this field has a value of 0x0000, then
459 the forms browser will render the specified forms in their encoded order.
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
462 @param ActionRequest Points to the action recommended by the form.
464 @retval EFI_SUCCESS The function completed successfully.
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
466 @retval EFI_NOT_FOUND No valid forms could be found to display.
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
473 IN EFI_HII_HANDLE
*Handles
,
474 IN UINTN HandleCount
,
475 IN EFI_GUID
*FormSetGuid
, OPTIONAL
476 IN UINT16 FormId
, OPTIONAL
477 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
482 UI_MENU_SELECTION
*Selection
;
484 FORM_BROWSER_FORMSET
*FormSet
;
485 FORM_ENTRY_INFO
*MenuList
;
488 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
490 if (mFormDisplay
== NULL
) {
491 return EFI_UNSUPPORTED
;
495 // Save globals used by SendForm()
497 SaveBrowserContext ();
499 gResetRequired
= FALSE
;
500 gExitRequired
= FALSE
;
501 Status
= EFI_SUCCESS
;
503 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
505 for (Index
= 0; Index
< HandleCount
; Index
++) {
506 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
507 ASSERT (Selection
!= NULL
);
509 Selection
->Handle
= Handles
[Index
];
510 if (FormSetGuid
!= NULL
) {
511 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
512 Selection
->FormId
= FormId
;
514 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
518 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
519 ASSERT (FormSet
!= NULL
);
522 // Validate the HiiHandle
523 // if validate failed, find the first validate parent HiiHandle.
525 if (!ValidateHiiHandle(Selection
->Handle
)) {
526 FindNextMenu (Selection
, FormSetLevel
);
530 // Initialize internal data structures of FormSet
532 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
533 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
534 DestroyFormSet (FormSet
);
537 Selection
->FormSet
= FormSet
;
538 mSystemLevelFormSet
= FormSet
;
541 // Display this formset
543 gCurrentSelection
= Selection
;
545 Status
= SetupBrowser (Selection
);
547 gCurrentSelection
= NULL
;
548 mSystemLevelFormSet
= NULL
;
551 // If no data is changed, don't need to save current FormSet into the maintain list.
553 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
554 CleanBrowserStorage(FormSet
);
555 RemoveEntryList (&FormSet
->Link
);
556 DestroyFormSet (FormSet
);
559 if (EFI_ERROR (Status
)) {
562 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
564 FreePool (Selection
);
567 if (ActionRequest
!= NULL
) {
568 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
569 if (gResetRequired
) {
570 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
574 mFormDisplay
->ExitDisplay();
577 // Clear the menu history data.
579 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
580 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
581 RemoveEntryList (&MenuList
->Link
);
586 // Restore globals used by SendForm()
588 RestoreBrowserContext ();
594 Get or set data to the storage.
596 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
597 @param ResultsData A string returned from an IFR browser or
598 equivalent. The results string will have no
599 routing information in them.
600 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
601 (if RetrieveData = TRUE) data from the uncommitted
602 browser state information or set (if RetrieveData
603 = FALSE) data in the uncommitted browser state
605 @param Storage The pointer to the storage.
607 @retval EFI_SUCCESS The results have been distributed or are awaiting
613 IN OUT UINTN
*ResultsDataSize
,
614 IN OUT EFI_STRING
*ResultsData
,
615 IN BOOLEAN RetrieveData
,
616 IN BROWSER_STORAGE
*Storage
627 // Generate <ConfigResp>
629 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
630 if (EFI_ERROR (Status
)) {
635 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
636 // Also need to consider add "\0" at first time.
638 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
639 BufferSize
= StrSize (StrPtr
);
643 // Copy the data if the input buffer is bigger enough.
645 if (*ResultsDataSize
>= BufferSize
) {
646 StrCpy (*ResultsData
, StrPtr
);
649 *ResultsDataSize
= BufferSize
;
650 FreePool (ConfigResp
);
653 // Prepare <ConfigResp>
655 TmpSize
= StrLen (*ResultsData
);
656 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
657 ConfigResp
= AllocateZeroPool (BufferSize
);
658 ASSERT (ConfigResp
!= NULL
);
660 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
661 StrCat (ConfigResp
, L
"&");
662 StrCat (ConfigResp
, *ResultsData
);
665 // Update Browser uncommited data
667 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
668 FreePool (ConfigResp
);
669 if (EFI_ERROR (Status
)) {
678 This routine called this service in the browser to retrieve or set certain uncommitted
679 state information that resides in the open formsets.
681 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
683 @param ResultsDataSize A pointer to the size of the buffer associated
685 @param ResultsData A string returned from an IFR browser or
686 equivalent. The results string will have no
687 routing information in them.
688 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
689 (if RetrieveData = TRUE) data from the uncommitted
690 browser state information or set (if RetrieveData
691 = FALSE) data in the uncommitted browser state
693 @param VariableGuid An optional field to indicate the target variable
695 @param VariableName An optional field to indicate the target
696 human-readable variable name.
698 @retval EFI_SUCCESS The results have been distributed or are awaiting
700 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
701 contain the results data.
707 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
708 IN OUT UINTN
*ResultsDataSize
,
709 IN OUT EFI_STRING ResultsData
,
710 IN BOOLEAN RetrieveData
,
711 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
712 IN CONST CHAR16
*VariableName OPTIONAL
717 BROWSER_STORAGE
*Storage
;
718 FORMSET_STORAGE
*FormsetStorage
;
722 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
723 return EFI_INVALID_PARAMETER
;
726 TotalSize
= *ResultsDataSize
;
729 Status
= EFI_SUCCESS
;
731 if (VariableGuid
!= NULL
) {
733 // Try to find target storage in the current formset.
735 Link
= GetFirstNode (&gBrowserStorageList
);
736 while (!IsNull (&gBrowserStorageList
, Link
)) {
737 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
738 Link
= GetNextNode (&gBrowserStorageList
, Link
);
740 // Check the current storage.
742 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
746 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
747 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
749 // Buffer storage require both GUID and Name
751 if (VariableName
== NULL
) {
752 return EFI_NOT_FOUND
;
755 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
760 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
761 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
762 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
763 return EFI_NOT_FOUND
;
766 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
771 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
772 if (EFI_ERROR (Status
)) {
776 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
777 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
781 // Different formsets may have same varstore, so here just set the flag
782 // not exit the circle.
789 return EFI_NOT_FOUND
;
793 // GUID/Name is not specified, take the first storage in FormSet
795 if (mSystemLevelFormSet
== NULL
) {
796 return EFI_NOT_READY
;
800 // Generate <ConfigResp>
802 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
803 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
804 return EFI_UNSUPPORTED
;
807 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
809 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
810 if (EFI_ERROR (Status
)) {
816 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
817 *ResultsDataSize
= TotalSize
;
826 Callback function for SimpleTextInEx protocol install events
828 @param Event the event that is signaled.
829 @param Context not used here.
834 FormDisplayCallback (
841 if (mFormDisplay
!= NULL
) {
845 Status
= gBS
->LocateProtocol (
846 &gEdkiiFormDisplayEngineProtocolGuid
,
848 (VOID
**) &mFormDisplay
853 Initialize Setup Browser driver.
855 @param ImageHandle The image handle.
856 @param SystemTable The system table.
858 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
859 @return Other value if failed to initialize the Setup Browser module.
865 IN EFI_HANDLE ImageHandle
,
866 IN EFI_SYSTEM_TABLE
*SystemTable
873 // Locate required Hii relative protocols
875 Status
= gBS
->LocateProtocol (
876 &gEfiHiiDatabaseProtocolGuid
,
878 (VOID
**) &mHiiDatabase
880 ASSERT_EFI_ERROR (Status
);
882 Status
= gBS
->LocateProtocol (
883 &gEfiHiiConfigRoutingProtocolGuid
,
885 (VOID
**) &mHiiConfigRouting
887 ASSERT_EFI_ERROR (Status
);
889 Status
= gBS
->LocateProtocol (
890 &gEfiDevicePathFromTextProtocolGuid
,
892 (VOID
**) &mPathFromText
896 // Install FormBrowser2 protocol
898 mPrivateData
.Handle
= NULL
;
899 Status
= gBS
->InstallProtocolInterface (
900 &mPrivateData
.Handle
,
901 &gEfiFormBrowser2ProtocolGuid
,
902 EFI_NATIVE_INTERFACE
,
903 &mPrivateData
.FormBrowser2
905 ASSERT_EFI_ERROR (Status
);
908 // Install FormBrowserEx2 protocol
910 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
911 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
912 mPrivateData
.Handle
= NULL
;
913 Status
= gBS
->InstallProtocolInterface (
914 &mPrivateData
.Handle
,
915 &gEdkiiFormBrowserEx2ProtocolGuid
,
916 EFI_NATIVE_INTERFACE
,
917 &mPrivateData
.FormBrowserEx2
919 ASSERT_EFI_ERROR (Status
);
921 Status
= gBS
->InstallProtocolInterface (
922 &mPrivateData
.Handle
,
923 &gEfiFormBrowserExProtocolGuid
,
924 EFI_NATIVE_INTERFACE
,
925 &mPrivateData
.FormBrowserEx
927 ASSERT_EFI_ERROR (Status
);
929 InitializeDisplayFormData ();
931 Status
= gBS
->LocateProtocol (
932 &gEdkiiFormDisplayEngineProtocolGuid
,
934 (VOID
**) &mFormDisplay
937 if (EFI_ERROR (Status
)) {
938 EfiCreateProtocolNotifyEvent (
939 &gEdkiiFormDisplayEngineProtocolGuid
,
952 Create a new string in HII Package List.
954 @param String The String to be added
955 @param HiiHandle The package list in the HII database to insert the
958 @return The output string.
964 IN EFI_HII_HANDLE HiiHandle
967 EFI_STRING_ID StringId
;
969 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
970 ASSERT (StringId
!= 0);
977 Delete a string from HII Package List.
979 @param StringId Id of the string in HII database.
980 @param HiiHandle The HII package list handle.
982 @retval EFI_SUCCESS The string was deleted successfully.
987 IN EFI_STRING_ID StringId
,
988 IN EFI_HII_HANDLE HiiHandle
993 NullChar
= CHAR_NULL
;
994 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1000 Get the string based on the StringId and HII Package List Handle.
1002 @param Token The String's ID.
1003 @param HiiHandle The package list in the HII database to search for
1004 the specified string.
1006 @return The output string.
1011 IN EFI_STRING_ID Token
,
1012 IN EFI_HII_HANDLE HiiHandle
1017 if (HiiHandle
== NULL
) {
1021 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1022 if (String
== NULL
) {
1023 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1024 ASSERT (String
!= NULL
);
1026 return (CHAR16
*) String
;
1031 Allocate new memory and then copy the Unicode string Source to Destination.
1033 @param Dest Location to copy string
1034 @param Src String to copy
1039 IN OUT CHAR16
**Dest
,
1043 if (*Dest
!= NULL
) {
1046 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1047 ASSERT (*Dest
!= NULL
);
1052 Allocate new memory and concatinate Source on the end of Destination.
1054 @param Dest String to added to the end of.
1055 @param Src String to concatinate.
1060 IN OUT CHAR16
**Dest
,
1067 if (*Dest
== NULL
) {
1068 NewStringCpy (Dest
, Src
);
1072 TmpSize
= StrSize (*Dest
);
1073 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
1074 ASSERT (NewString
!= NULL
);
1076 StrCpy (NewString
, *Dest
);
1077 StrCat (NewString
, Src
);
1084 Get Value for given Name from a NameValue Storage.
1086 @param Storage The NameValue Storage.
1087 @param Name The Name.
1088 @param Value The retured Value.
1089 @param GetValueFrom Where to get source value, from EditValue or Value.
1091 @retval EFI_SUCCESS Value found for given Name.
1092 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1097 IN BROWSER_STORAGE
*Storage
,
1099 IN OUT CHAR16
**Value
,
1100 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1104 NAME_VALUE_NODE
*Node
;
1106 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1107 return EFI_INVALID_PARAMETER
;
1112 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1113 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1114 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1116 if (StrCmp (Name
, Node
->Name
) == 0) {
1117 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1118 NewStringCpy (Value
, Node
->EditValue
);
1120 NewStringCpy (Value
, Node
->Value
);
1125 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1128 return EFI_NOT_FOUND
;
1133 Set Value of given Name in a NameValue Storage.
1135 @param Storage The NameValue Storage.
1136 @param Name The Name.
1137 @param Value The Value to set.
1138 @param SetValueTo Whether update editValue or Value.
1139 @param ReturnNode The node use the input name.
1141 @retval EFI_SUCCESS Value found for given Name.
1142 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1147 IN BROWSER_STORAGE
*Storage
,
1150 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1151 OUT NAME_VALUE_NODE
**ReturnNode
1155 NAME_VALUE_NODE
*Node
;
1158 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1159 return EFI_INVALID_PARAMETER
;
1162 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1163 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1164 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1166 if (StrCmp (Name
, Node
->Name
) == 0) {
1167 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1168 Buffer
= Node
->EditValue
;
1170 Buffer
= Node
->Value
;
1172 if (Buffer
!= NULL
) {
1175 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1176 ASSERT (Buffer
!= NULL
);
1177 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1178 Node
->EditValue
= Buffer
;
1180 Node
->Value
= Buffer
;
1183 if (ReturnNode
!= NULL
) {
1190 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1193 return EFI_NOT_FOUND
;
1198 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1200 @param Storage The Storage to be conveted.
1201 @param ConfigResp The returned <ConfigResp>.
1202 @param ConfigRequest The ConfigRequest string.
1203 @param GetEditBuf Get the data from editbuffer or buffer.
1205 @retval EFI_SUCCESS Convert success.
1206 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1210 StorageToConfigResp (
1211 IN BROWSER_STORAGE
*Storage
,
1212 IN CHAR16
**ConfigResp
,
1213 IN CHAR16
*ConfigRequest
,
1214 IN BOOLEAN GetEditBuf
1218 EFI_STRING Progress
;
1220 NAME_VALUE_NODE
*Node
;
1223 Status
= EFI_SUCCESS
;
1225 switch (Storage
->Type
) {
1226 case EFI_HII_VARSTORE_BUFFER
:
1227 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1228 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1229 Status
= mHiiConfigRouting
->BlockToConfig (
1239 case EFI_HII_VARSTORE_NAME_VALUE
:
1241 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1243 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1244 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1245 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1247 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1248 NewStringCat (ConfigResp
, L
"&");
1249 NewStringCat (ConfigResp
, Node
->Name
);
1250 NewStringCat (ConfigResp
, L
"=");
1252 NewStringCat (ConfigResp
, Node
->EditValue
);
1254 NewStringCat (ConfigResp
, Node
->Value
);
1257 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1261 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1263 Status
= EFI_INVALID_PARAMETER
;
1272 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1274 @param Storage The Storage to receive the settings.
1275 @param ConfigResp The <ConfigResp> to be converted.
1277 @retval EFI_SUCCESS Convert success.
1278 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1282 ConfigRespToStorage (
1283 IN BROWSER_STORAGE
*Storage
,
1284 IN CHAR16
*ConfigResp
1288 EFI_STRING Progress
;
1294 Status
= EFI_SUCCESS
;
1296 switch (Storage
->Type
) {
1297 case EFI_HII_VARSTORE_BUFFER
:
1298 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1299 BufferSize
= Storage
->Size
;
1300 Status
= mHiiConfigRouting
->ConfigToBlock (
1303 Storage
->EditBuffer
,
1309 case EFI_HII_VARSTORE_NAME_VALUE
:
1310 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1311 if (StrPtr
== NULL
) {
1314 StrPtr
= StrStr (ConfigResp
, L
"&");
1315 while (StrPtr
!= NULL
) {
1319 StrPtr
= StrPtr
+ 1;
1321 StrPtr
= StrStr (StrPtr
, L
"=");
1322 if (StrPtr
== NULL
) {
1330 StrPtr
= StrPtr
+ 1;
1332 StrPtr
= StrStr (StrPtr
, L
"&");
1333 if (StrPtr
!= NULL
) {
1336 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1340 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1342 Status
= EFI_INVALID_PARAMETER
;
1351 Get Question's current Value.
1353 @param FormSet FormSet data structure.
1354 @param Form Form data structure.
1355 @param Question Question to be initialized.
1356 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1358 @retval EFI_SUCCESS The function completed successfully.
1363 IN FORM_BROWSER_FORMSET
*FormSet
,
1364 IN FORM_BROWSER_FORM
*Form
,
1365 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1366 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1375 BROWSER_STORAGE
*Storage
;
1376 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1377 CHAR16
*ConfigRequest
;
1385 BOOLEAN IsBufferStorage
;
1390 Status
= EFI_SUCCESS
;
1394 if (GetValueFrom
>= GetSetValueWithMax
) {
1395 return EFI_INVALID_PARAMETER
;
1399 // Question value is provided by an Expression, evaluate it
1401 if (Question
->ValueExpression
!= NULL
) {
1402 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1403 if (!EFI_ERROR (Status
)) {
1404 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1405 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1406 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1407 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1408 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1410 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1411 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1413 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1415 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1416 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1422 // Get question value by read expression.
1424 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1425 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1426 if (!EFI_ERROR (Status
) &&
1427 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1429 // Only update question value to the valid result.
1431 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1432 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1433 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1434 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1435 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1437 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1438 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1440 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1442 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1443 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1449 // Question value is provided by RTC
1451 Storage
= Question
->Storage
;
1452 QuestionValue
= &Question
->HiiValue
.Value
;
1453 if (Storage
== NULL
) {
1455 // It's a Question without storage, or RTC date/time
1457 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1459 // Date and time define the same Flags bit
1461 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1462 case QF_DATE_STORAGE_TIME
:
1463 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1466 case QF_DATE_STORAGE_WAKEUP
:
1467 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1470 case QF_DATE_STORAGE_NORMAL
:
1473 // For date/time without storage
1478 if (EFI_ERROR (Status
)) {
1482 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1483 QuestionValue
->date
.Year
= EfiTime
.Year
;
1484 QuestionValue
->date
.Month
= EfiTime
.Month
;
1485 QuestionValue
->date
.Day
= EfiTime
.Day
;
1487 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1488 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1489 QuestionValue
->time
.Second
= EfiTime
.Second
;
1497 // Question value is provided by EFI variable
1499 StorageWidth
= Question
->StorageWidth
;
1500 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1501 if (Question
->BufferValue
!= NULL
) {
1502 Dst
= Question
->BufferValue
;
1504 Dst
= (UINT8
*) QuestionValue
;
1507 Status
= gRT
->GetVariable (
1508 Question
->VariableName
,
1515 // Always return success, even this EFI variable doesn't exist
1521 // Question Value is provided by Buffer Storage or NameValue Storage
1523 if (Question
->BufferValue
!= NULL
) {
1525 // This Question is password or orderedlist
1527 Dst
= Question
->BufferValue
;
1530 // Other type of Questions
1532 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1535 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1536 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1537 IsBufferStorage
= TRUE
;
1539 IsBufferStorage
= FALSE
;
1541 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1542 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1543 if (IsBufferStorage
) {
1544 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1546 // Copy from storage Edit buffer
1548 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1551 // Copy from storage Edit buffer
1553 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1557 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1558 if (EFI_ERROR (Status
)) {
1562 ASSERT (Value
!= NULL
);
1563 LengthStr
= StrLen (Value
);
1564 Status
= EFI_SUCCESS
;
1567 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1568 // Add string tail char L'\0' into Length
1570 Length
= StorageWidth
+ sizeof (CHAR16
);
1571 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1572 Status
= EFI_BUFFER_TOO_SMALL
;
1574 StringPtr
= (CHAR16
*) Dst
;
1575 ZeroMem (TemStr
, sizeof (TemStr
));
1576 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1577 StrnCpy (TemStr
, Value
+ Index
, 4);
1578 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1581 // Add tailing L'\0' character
1583 StringPtr
[Index
/4] = L
'\0';
1586 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1587 Status
= EFI_BUFFER_TOO_SMALL
;
1589 ZeroMem (TemStr
, sizeof (TemStr
));
1590 for (Index
= 0; Index
< LengthStr
; Index
++) {
1591 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1592 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1593 if ((Index
& 1) == 0) {
1594 Dst
[Index
/2] = DigitUint8
;
1596 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1606 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1607 // <ConfigHdr> + "&" + <VariableName>
1609 if (IsBufferStorage
) {
1610 Length
= StrLen (Storage
->ConfigHdr
);
1611 Length
+= StrLen (Question
->BlockName
);
1613 Length
= StrLen (Storage
->ConfigHdr
);
1614 Length
+= StrLen (Question
->VariableName
) + 1;
1616 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1617 ASSERT (ConfigRequest
!= NULL
);
1619 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1620 if (IsBufferStorage
) {
1621 StrCat (ConfigRequest
, Question
->BlockName
);
1623 StrCat (ConfigRequest
, L
"&");
1624 StrCat (ConfigRequest
, Question
->VariableName
);
1628 // Request current settings from Configuration Driver
1630 Status
= mHiiConfigRouting
->ExtractConfig (
1636 FreePool (ConfigRequest
);
1637 if (EFI_ERROR (Status
)) {
1642 // Skip <ConfigRequest>
1644 if (IsBufferStorage
) {
1645 Value
= StrStr (Result
, L
"&VALUE");
1646 if (Value
== NULL
) {
1648 return EFI_NOT_FOUND
;
1655 Value
= Result
+ Length
;
1657 if (*Value
!= '=') {
1659 return EFI_NOT_FOUND
;
1662 // Skip '=', point to value
1667 // Suppress <AltResp> if any
1670 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1675 LengthStr
= StrLen (Value
);
1676 Status
= EFI_SUCCESS
;
1677 if (!IsBufferStorage
&& IsString
) {
1679 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1680 // Add string tail char L'\0' into Length
1682 Length
= StorageWidth
+ sizeof (CHAR16
);
1683 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1684 Status
= EFI_BUFFER_TOO_SMALL
;
1686 StringPtr
= (CHAR16
*) Dst
;
1687 ZeroMem (TemStr
, sizeof (TemStr
));
1688 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1689 StrnCpy (TemStr
, Value
+ Index
, 4);
1690 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1693 // Add tailing L'\0' character
1695 StringPtr
[Index
/4] = L
'\0';
1698 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1699 Status
= EFI_BUFFER_TOO_SMALL
;
1701 ZeroMem (TemStr
, sizeof (TemStr
));
1702 for (Index
= 0; Index
< LengthStr
; Index
++) {
1703 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1704 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1705 if ((Index
& 1) == 0) {
1706 Dst
[Index
/2] = DigitUint8
;
1708 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1714 if (EFI_ERROR (Status
)) {
1720 // Synchronize Edit Buffer
1722 if (IsBufferStorage
) {
1723 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1725 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1728 if (Result
!= NULL
) {
1738 Save Question Value to edit copy(cached) or Storage(uncached).
1740 @param FormSet FormSet data structure.
1741 @param Form Form data structure.
1742 @param Question Pointer to the Question.
1743 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1745 @retval EFI_SUCCESS The function completed successfully.
1750 IN FORM_BROWSER_FORMSET
*FormSet
,
1751 IN FORM_BROWSER_FORM
*Form
,
1752 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1753 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1763 BROWSER_STORAGE
*Storage
;
1764 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1769 BOOLEAN IsBufferStorage
;
1775 NAME_VALUE_NODE
*Node
;
1777 Status
= EFI_SUCCESS
;
1780 if (SetValueTo
>= GetSetValueWithMax
) {
1781 return EFI_INVALID_PARAMETER
;
1785 // If Question value is provided by an Expression, then it is read only
1787 if (Question
->ValueExpression
!= NULL
) {
1792 // Before set question value, evaluate its write expression.
1794 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1795 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1796 if (EFI_ERROR (Status
)) {
1802 // Question value is provided by RTC
1804 Storage
= Question
->Storage
;
1805 QuestionValue
= &Question
->HiiValue
.Value
;
1806 if (Storage
== NULL
) {
1808 // It's a Question without storage, or RTC date/time
1810 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1812 // Date and time define the same Flags bit
1814 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1815 case QF_DATE_STORAGE_TIME
:
1816 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1819 case QF_DATE_STORAGE_WAKEUP
:
1820 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1823 case QF_DATE_STORAGE_NORMAL
:
1826 // For date/time without storage
1831 if (EFI_ERROR (Status
)) {
1835 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1836 EfiTime
.Year
= QuestionValue
->date
.Year
;
1837 EfiTime
.Month
= QuestionValue
->date
.Month
;
1838 EfiTime
.Day
= QuestionValue
->date
.Day
;
1840 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1841 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1842 EfiTime
.Second
= QuestionValue
->time
.Second
;
1845 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1846 Status
= gRT
->SetTime (&EfiTime
);
1848 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1856 // Question value is provided by EFI variable
1858 StorageWidth
= Question
->StorageWidth
;
1859 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1860 if (Question
->BufferValue
!= NULL
) {
1861 Src
= Question
->BufferValue
;
1863 Src
= (UINT8
*) QuestionValue
;
1866 Status
= gRT
->SetVariable (
1867 Question
->VariableName
,
1869 Storage
->Attributes
,
1877 // Question Value is provided by Buffer Storage or NameValue Storage
1879 if (Question
->BufferValue
!= NULL
) {
1880 Src
= Question
->BufferValue
;
1882 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1885 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1886 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1887 IsBufferStorage
= TRUE
;
1889 IsBufferStorage
= FALSE
;
1891 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1893 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1894 if (IsBufferStorage
) {
1895 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1897 // Copy to storage edit buffer
1899 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1900 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1902 // Copy to storage edit buffer
1904 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1909 // Allocate enough string buffer.
1912 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1913 Value
= AllocateZeroPool (BufferLen
);
1914 ASSERT (Value
!= NULL
);
1916 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1918 TemName
= (CHAR16
*) Src
;
1920 for (; *TemName
!= L
'\0'; TemName
++) {
1921 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1924 BufferLen
= StorageWidth
* 2 + 1;
1925 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1926 ASSERT (Value
!= NULL
);
1928 // Convert Buffer to Hex String
1930 TemBuffer
= Src
+ StorageWidth
- 1;
1932 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1933 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1937 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1939 if (EFI_ERROR (Status
)) {
1943 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1945 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1946 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1948 if (IsBufferStorage
) {
1949 Length
= StrLen (Question
->BlockName
) + 7;
1951 Length
= StrLen (Question
->VariableName
) + 2;
1953 if (!IsBufferStorage
&& IsString
) {
1954 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1956 Length
+= (StorageWidth
* 2);
1958 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1959 ASSERT (ConfigResp
!= NULL
);
1961 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1962 if (IsBufferStorage
) {
1963 StrCat (ConfigResp
, Question
->BlockName
);
1964 StrCat (ConfigResp
, L
"&VALUE=");
1966 StrCat (ConfigResp
, L
"&");
1967 StrCat (ConfigResp
, Question
->VariableName
);
1968 StrCat (ConfigResp
, L
"=");
1971 Value
= ConfigResp
+ StrLen (ConfigResp
);
1973 if (!IsBufferStorage
&& IsString
) {
1975 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1977 TemName
= (CHAR16
*) Src
;
1979 for (; *TemName
!= L
'\0'; TemName
++) {
1980 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1984 // Convert Buffer to Hex String
1986 TemBuffer
= Src
+ StorageWidth
- 1;
1988 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1989 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1994 // Convert to lower char.
1996 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1997 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1998 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2003 // Submit Question Value to Configuration Driver
2005 Status
= mHiiConfigRouting
->RouteConfig (
2010 if (EFI_ERROR (Status
)) {
2011 FreePool (ConfigResp
);
2014 FreePool (ConfigResp
);
2017 // Sync storage, from editbuffer to buffer.
2019 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2027 Perform nosubmitif check for a Form.
2029 @param FormSet FormSet data structure.
2030 @param Form Form data structure.
2031 @param Question The Question to be validated.
2032 @param Type Validation type: NoSubmit
2034 @retval EFI_SUCCESS Form validation pass.
2035 @retval other Form validation failed.
2040 IN FORM_BROWSER_FORMSET
*FormSet
,
2041 IN FORM_BROWSER_FORM
*Form
,
2042 IN FORM_BROWSER_STATEMENT
*Question
,
2048 LIST_ENTRY
*ListHead
;
2049 FORM_EXPRESSION
*Expression
;
2050 UINT32 BrowserStatus
;
2053 BrowserStatus
= BROWSER_SUCCESS
;
2057 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2058 ListHead
= &Question
->InconsistentListHead
;
2061 case EFI_HII_EXPRESSION_WARNING_IF
:
2062 ListHead
= &Question
->WarningListHead
;
2065 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2066 ListHead
= &Question
->NoSubmitListHead
;
2071 return EFI_UNSUPPORTED
;
2074 Link
= GetFirstNode (ListHead
);
2075 while (!IsNull (ListHead
, Link
)) {
2076 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2079 // Evaluate the expression
2081 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2082 if (EFI_ERROR (Status
)) {
2086 if (IsTrue (&Expression
->Result
)) {
2088 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2089 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2092 case EFI_HII_EXPRESSION_WARNING_IF
:
2093 BrowserStatus
= BROWSER_WARNING_IF
;
2096 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2097 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2099 // This code only used to compatible with old display engine,
2100 // New display engine will not use this field.
2102 if (Expression
->Error
!= 0) {
2103 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2112 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2114 // If in system submit process and for no_submit_if check, not popup this error message.
2115 // Will process this fail again later in not system submit process.
2117 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2120 if (ErrorStr
!= NULL
) {
2121 FreePool (ErrorStr
);
2124 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2127 return EFI_NOT_READY
;
2131 Link
= GetNextNode (ListHead
, Link
);
2138 Perform question check.
2140 If one question has more than one check, process form high priority to low.
2141 Only one error info will be popup.
2143 @param FormSet FormSet data structure.
2144 @param Form Form data structure.
2145 @param Question The Question to be validated.
2147 @retval EFI_SUCCESS Form validation pass.
2148 @retval other Form validation failed.
2152 ValueChangedValidation (
2153 IN FORM_BROWSER_FORMSET
*FormSet
,
2154 IN FORM_BROWSER_FORM
*Form
,
2155 IN FORM_BROWSER_STATEMENT
*Question
2160 Status
= EFI_SUCCESS
;
2163 // Do the inconsistentif check.
2165 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2166 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2167 if (EFI_ERROR (Status
)) {
2173 // Do the warningif check.
2175 if (!IsListEmpty (&Question
->WarningListHead
)) {
2176 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2183 Perform NoSubmit check for each Form in FormSet.
2185 @param FormSet FormSet data structure.
2186 @param CurrentForm Current input form data structure.
2187 @param Statement The statement for this check.
2189 @retval EFI_SUCCESS Form validation pass.
2190 @retval other Form validation failed.
2195 IN FORM_BROWSER_FORMSET
*FormSet
,
2196 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2197 OUT FORM_BROWSER_STATEMENT
**Statement
2202 FORM_BROWSER_STATEMENT
*Question
;
2203 FORM_BROWSER_FORM
*Form
;
2204 LIST_ENTRY
*LinkForm
;
2206 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2207 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2208 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2209 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2211 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2215 Link
= GetFirstNode (&Form
->StatementListHead
);
2216 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2217 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2218 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2219 if (EFI_ERROR (Status
)) {
2220 if (*CurrentForm
== NULL
) {
2221 *CurrentForm
= Form
;
2223 if (Statement
!= NULL
) {
2224 *Statement
= Question
;
2229 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2237 Fill storage's edit copy with settings requested from Configuration Driver.
2239 @param Storage The storage which need to sync.
2240 @param ConfigRequest The config request string which used to sync storage.
2241 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2242 editbuffer to buffer
2243 if TRUE, copy the editbuffer to the buffer.
2244 if FALSE, copy the buffer to the editbuffer.
2246 @retval EFI_SUCCESS The function completed successfully.
2250 SynchronizeStorage (
2251 OUT BROWSER_STORAGE
*Storage
,
2252 IN CHAR16
*ConfigRequest
,
2253 IN BOOLEAN SyncOrRestore
2257 EFI_STRING Progress
;
2261 NAME_VALUE_NODE
*Node
;
2265 Status
= EFI_SUCCESS
;
2268 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2269 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2270 BufferSize
= Storage
->Size
;
2272 if (SyncOrRestore
) {
2273 Src
= Storage
->EditBuffer
;
2274 Dst
= Storage
->Buffer
;
2276 Src
= Storage
->Buffer
;
2277 Dst
= Storage
->EditBuffer
;
2280 if (ConfigRequest
!= NULL
) {
2281 Status
= mHiiConfigRouting
->BlockToConfig(
2289 if (EFI_ERROR (Status
)) {
2293 Status
= mHiiConfigRouting
->ConfigToBlock (
2300 if (Result
!= NULL
) {
2304 CopyMem (Dst
, Src
, BufferSize
);
2306 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2307 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2308 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2309 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2311 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2312 (ConfigRequest
== NULL
)) {
2313 if (SyncOrRestore
) {
2314 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2316 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2320 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2328 When discard the question value, call the callback function with Changed type
2329 to inform the hii driver.
2331 @param FormSet FormSet data structure.
2332 @param Form Form data structure.
2336 SendDiscardInfoToDriver (
2337 IN FORM_BROWSER_FORMSET
*FormSet
,
2338 IN FORM_BROWSER_FORM
*Form
2342 FORM_BROWSER_STATEMENT
*Question
;
2343 EFI_IFR_TYPE_VALUE
*TypeValue
;
2344 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2346 if (FormSet
->ConfigAccess
== NULL
) {
2350 Link
= GetFirstNode (&Form
->StatementListHead
);
2351 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2352 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2353 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2355 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2359 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2363 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2367 if (!Question
->ValueChanged
) {
2372 // Restore the question value before call the CHANGED callback type.
2374 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2376 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2377 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2379 TypeValue
= &Question
->HiiValue
.Value
;
2382 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2383 FormSet
->ConfigAccess
->Callback (
2384 FormSet
->ConfigAccess
,
2385 EFI_BROWSER_ACTION_CHANGED
,
2386 Question
->QuestionId
,
2387 Question
->HiiValue
.Type
,
2395 Validate the HiiHandle.
2397 @param HiiHandle The input HiiHandle which need to validate.
2399 @retval TRUE The handle is validate.
2400 @retval FALSE The handle is invalidate.
2405 EFI_HII_HANDLE HiiHandle
2408 EFI_HII_HANDLE
*HiiHandles
;
2412 if (HiiHandle
== NULL
) {
2418 HiiHandles
= HiiGetHiiHandles (NULL
);
2419 ASSERT (HiiHandles
!= NULL
);
2421 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2422 if (HiiHandles
[Index
] == HiiHandle
) {
2428 FreePool (HiiHandles
);
2434 Validate the FormSet. If the formset is not validate, remove it from the list.
2436 @param FormSet The input FormSet which need to validate.
2438 @retval TRUE The handle is validate.
2439 @retval FALSE The handle is invalidate.
2444 FORM_BROWSER_FORMSET
*FormSet
2449 ASSERT (FormSet
!= NULL
);
2451 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2453 // Should not remove the formset which is being used.
2455 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2456 CleanBrowserStorage(FormSet
);
2457 RemoveEntryList (&FormSet
->Link
);
2458 DestroyFormSet (FormSet
);
2464 Check whether need to enable the reset flag in form level.
2465 Also clean all ValueChanged flag in question.
2467 @param SetFlag Whether need to set the Reset Flag.
2468 @param FormSet FormSet data structure.
2469 @param Form Form data structure.
2475 IN FORM_BROWSER_FORMSET
*FormSet
,
2476 IN FORM_BROWSER_FORM
*Form
2480 FORM_BROWSER_STATEMENT
*Question
;
2483 Link
= GetFirstNode (&Form
->StatementListHead
);
2484 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2485 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2486 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2488 if (!Question
->ValueChanged
) {
2492 OldValue
= Question
->ValueChanged
;
2495 // Compare the buffer and editbuffer data to see whether the data has been saved.
2497 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2500 // Only the changed data has been saved, then need to set the reset flag.
2502 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2503 gResetRequired
= TRUE
;
2509 Check whether need to enable the reset flag.
2510 Also clean ValueChanged flag for all statements.
2512 Form level or formset level, only one.
2514 @param SetFlag Whether need to set the Reset Flag.
2515 @param FormSet FormSet data structure.
2516 @param Form Form data structure.
2520 ValueChangeResetFlagUpdate (
2522 IN FORM_BROWSER_FORMSET
*FormSet
,
2523 IN FORM_BROWSER_FORM
*Form
2526 FORM_BROWSER_FORM
*CurrentForm
;
2530 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2534 Link
= GetFirstNode (&FormSet
->FormListHead
);
2535 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2536 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2537 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2539 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2544 Base on the return Progress string to find the form.
2546 Base on the first return Offset/Width (Name) string to find the form
2547 which keep this string.
2549 @param FormSet FormSet data structure.
2550 @param Storage Storage which has this Progress string.
2551 @param Progress The Progress string which has the first fail string.
2552 @param RetForm The return form for this progress string.
2553 @param RetQuestion The return question for the error progress string.
2555 @retval TRUE Find the error form and statement for this error progress string.
2556 @retval FALSE Not find the error form.
2560 FindQuestionFromProgress (
2561 IN FORM_BROWSER_FORMSET
*FormSet
,
2562 IN BROWSER_STORAGE
*Storage
,
2563 IN EFI_STRING Progress
,
2564 OUT FORM_BROWSER_FORM
**RetForm
,
2565 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2569 LIST_ENTRY
*LinkStorage
;
2570 LIST_ENTRY
*LinkStatement
;
2571 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2572 FORM_BROWSER_FORM
*Form
;
2574 FORM_BROWSER_STATEMENT
*Statement
;
2576 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2580 *RetQuestion
= NULL
;
2583 // Skip the first "&" or the ConfigHdr part.
2585 if (*Progress
== '&') {
2589 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2591 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2593 // For Name/Value type, Skip the ConfigHdr part.
2595 EndStr
= StrStr (Progress
, L
"PATH=");
2596 ASSERT (EndStr
!= NULL
);
2597 while (*EndStr
!= '&') {
2604 // For Buffer type, Skip the ConfigHdr part.
2606 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2607 ASSERT (EndStr
!= NULL
);
2611 Progress
= EndStr
+ 1;
2615 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2617 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2619 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2620 // here, just keep the "Fred" string.
2622 EndStr
= StrStr (Progress
, L
"=");
2623 ASSERT (EndStr
!= NULL
);
2627 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2628 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2630 EndStr
= StrStr (Progress
, L
"&VALUE=");
2631 ASSERT (EndStr
!= NULL
);
2636 // Search in the form list.
2638 Link
= GetFirstNode (&FormSet
->FormListHead
);
2639 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2640 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2641 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2644 // Search in the ConfigReqeust list in this form.
2646 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2647 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2648 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2649 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2651 if (Storage
!= ConfigInfo
->Storage
) {
2655 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2657 // Find the OffsetWidth string in this form.
2664 if (*RetForm
!= NULL
) {
2665 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2666 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2667 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2668 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2670 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2671 *RetQuestion
= Statement
;
2677 if (*RetForm
!= NULL
) {
2683 // restore the OffsetWidth string to the original format.
2685 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2691 return (BOOLEAN
) (*RetForm
!= NULL
);
2695 Popup an save error info and get user input.
2697 @param TitleId The form title id.
2698 @param HiiHandle The hii handle for this package.
2700 @retval UINT32 The user select option for the save fail.
2701 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2705 IN EFI_STRING_ID TitleId
,
2706 IN EFI_HII_HANDLE HiiHandle
2710 CHAR16
*StringBuffer
;
2713 FormTitle
= GetToken (TitleId
, HiiHandle
);
2715 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2716 ASSERT (StringBuffer
!= NULL
);
2720 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2721 L
"Submit Fail For Form: %s.",
2725 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2727 FreePool (StringBuffer
);
2728 FreePool (FormTitle
);
2734 Popup an NO_SUBMIT_IF error info and get user input.
2736 @param TitleId The form title id.
2737 @param HiiHandle The hii handle for this package.
2739 @retval UINT32 The user select option for the save fail.
2740 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2743 ConfirmNoSubmitFail (
2744 IN EFI_STRING_ID TitleId
,
2745 IN EFI_HII_HANDLE HiiHandle
2749 CHAR16
*StringBuffer
;
2752 FormTitle
= GetToken (TitleId
, HiiHandle
);
2754 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2755 ASSERT (StringBuffer
!= NULL
);
2759 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2760 L
"NO_SUBMIT_IF error For Form: %s.",
2764 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
2766 FreePool (StringBuffer
);
2767 FreePool (FormTitle
);
2773 Discard data based on the input setting scope (Form, FormSet or System).
2775 @param FormSet FormSet data structure.
2776 @param Form Form data structure.
2777 @param SettingScope Setting Scope for Discard action.
2779 @retval EFI_SUCCESS The function completed successfully.
2780 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2785 IN FORM_BROWSER_FORMSET
*FormSet
,
2786 IN FORM_BROWSER_FORM
*Form
,
2787 IN BROWSER_SETTING_SCOPE SettingScope
2791 FORMSET_STORAGE
*Storage
;
2792 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2793 FORM_BROWSER_FORMSET
*LocalFormSet
;
2794 FORM_BROWSER_FORMSET
*OldFormSet
;
2797 // Check the supported setting level.
2799 if (SettingScope
>= MaxLevel
) {
2800 return EFI_UNSUPPORTED
;
2803 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2805 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2806 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2807 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2808 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2810 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2815 // Skip if there is no RequestElement
2817 if (ConfigInfo
->ElementCount
== 0) {
2822 // Prepare <ConfigResp>
2824 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2827 // Call callback with Changed type to inform the driver.
2829 SendDiscardInfoToDriver (FormSet
, Form
);
2832 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
2833 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2836 // Discard Buffer storage or Name/Value storage
2838 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2839 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2840 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2841 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2843 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2848 // Skip if there is no RequestElement
2850 if (Storage
->ElementCount
== 0) {
2854 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2857 Link
= GetFirstNode (&FormSet
->FormListHead
);
2858 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2859 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2860 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2863 // Call callback with Changed type to inform the driver.
2865 SendDiscardInfoToDriver (FormSet
, Form
);
2868 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2869 } else if (SettingScope
== SystemLevel
) {
2871 // System Level Discard.
2873 OldFormSet
= mSystemLevelFormSet
;
2876 // Discard changed value for each FormSet in the maintain list.
2878 Link
= GetFirstNode (&gBrowserFormSetList
);
2879 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2880 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2881 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2882 if (!ValidateFormSet(LocalFormSet
)) {
2886 mSystemLevelFormSet
= LocalFormSet
;
2888 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2889 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2891 // Remove maintain backup list after discard except for the current using FormSet.
2893 CleanBrowserStorage(LocalFormSet
);
2894 RemoveEntryList (&LocalFormSet
->Link
);
2895 DestroyFormSet (LocalFormSet
);
2899 mSystemLevelFormSet
= OldFormSet
;
2906 Submit data for a form.
2908 @param FormSet FormSet data structure.
2909 @param Form Form data structure.
2911 @retval EFI_SUCCESS The function completed successfully.
2912 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2917 IN FORM_BROWSER_FORMSET
*FormSet
,
2918 IN FORM_BROWSER_FORM
*Form
2923 EFI_STRING ConfigResp
;
2924 EFI_STRING Progress
;
2925 BROWSER_STORAGE
*Storage
;
2926 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2928 if (!IsNvUpdateRequiredForForm (Form
)) {
2932 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
2933 if (EFI_ERROR (Status
)) {
2937 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2938 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2939 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2940 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2942 Storage
= ConfigInfo
->Storage
;
2943 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2948 // Skip if there is no RequestElement
2950 if (ConfigInfo
->ElementCount
== 0) {
2955 // 1. Prepare <ConfigResp>
2957 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2958 if (EFI_ERROR (Status
)) {
2963 // 2. Set value to hii config routine protocol.
2965 Status
= mHiiConfigRouting
->RouteConfig (
2970 FreePool (ConfigResp
);
2972 if (EFI_ERROR (Status
)) {
2973 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
2978 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2980 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2984 // 4. Process the save failed storage.
2986 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
2987 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
2988 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
2989 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
2990 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
2991 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
2993 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2995 Status
= EFI_SUCCESS
;
2998 Status
= EFI_UNSUPPORTED
;
3002 // Free Form save fail list.
3004 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3005 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3006 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3007 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3012 // 5. Update the NV flag.
3014 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3020 Submit data for a formset.
3022 @param FormSet FormSet data structure.
3023 @param SkipProcessFail Whether skip to process the save failed storage.
3024 If submit formset is called when do system level save,
3025 set this value to true and process the failed formset
3027 if submit formset is called when do formset level save,
3028 set the value to false and process the failed storage
3029 right after process all storages for this formset.
3031 @retval EFI_SUCCESS The function completed successfully.
3032 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3037 IN FORM_BROWSER_FORMSET
*FormSet
,
3038 IN BOOLEAN SkipProcessFail
3043 EFI_STRING ConfigResp
;
3044 EFI_STRING Progress
;
3045 BROWSER_STORAGE
*Storage
;
3046 FORMSET_STORAGE
*FormSetStorage
;
3047 FORM_BROWSER_FORM
*Form
;
3048 BOOLEAN HasInserted
;
3049 FORM_BROWSER_STATEMENT
*Question
;
3051 HasInserted
= FALSE
;
3053 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3058 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3059 if (EFI_ERROR (Status
)) {
3060 if (SkipProcessFail
) {
3062 // Process NO_SUBMIT check first, so insert it at head.
3064 FormSet
->SaveFailForm
= Form
;
3065 FormSet
->SaveFailStatement
= Question
;
3066 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3075 // Submit Buffer storage or Name/Value storage
3077 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3078 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3079 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3080 Storage
= FormSetStorage
->BrowserStorage
;
3081 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3083 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3088 // Skip if there is no RequestElement
3090 if (FormSetStorage
->ElementCount
== 0) {
3095 // 1. Prepare <ConfigResp>
3097 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3098 if (EFI_ERROR (Status
)) {
3103 // 2. Send <ConfigResp> to Routine config Protocol.
3105 Status
= mHiiConfigRouting
->RouteConfig (
3110 if (EFI_ERROR (Status
)) {
3111 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3114 // Call submit formset for system level, save the formset info
3115 // and process later.
3117 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3118 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3119 FormSet
->SaveFailForm
= Form
;
3120 FormSet
->SaveFailStatement
= Question
;
3121 if (SkipProcessFail
) {
3122 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3127 FreePool (ConfigResp
);
3131 FreePool (ConfigResp
);
3133 // 3. Config success, update storage shadow Buffer
3135 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3139 // 4. Has save fail storage need to handle.
3142 if (!SkipProcessFail
) {
3144 // If not in system level, just handl the save failed storage here.
3146 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3147 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3148 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3149 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3150 Storage
= FormSetStorage
->BrowserStorage
;
3151 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3153 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3155 Status
= EFI_SUCCESS
;
3158 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3160 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3161 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3162 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3163 gCurrentSelection
->FormId
= Form
->FormId
;
3164 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3166 Status
= EFI_UNSUPPORTED
;
3170 // Free FormSet save fail list.
3172 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3173 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3174 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3175 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3179 // If in system level, just return error and handle the failed formset later.
3181 Status
= EFI_UNSUPPORTED
;
3186 // 5. Update the NV flag.
3188 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3194 Submit data for all formsets.
3196 @retval EFI_SUCCESS The function completed successfully.
3197 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3207 LIST_ENTRY
*StorageLink
;
3208 BROWSER_STORAGE
*Storage
;
3209 FORMSET_STORAGE
*FormSetStorage
;
3210 FORM_BROWSER_FORM
*Form
;
3211 FORM_BROWSER_FORMSET
*LocalFormSet
;
3212 UINT32 UserSelection
;
3213 FORM_BROWSER_STATEMENT
*Question
;
3215 mSystemSubmit
= TRUE
;
3216 Link
= GetFirstNode (&gBrowserFormSetList
);
3217 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3218 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3219 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3220 if (!ValidateFormSet(LocalFormSet
)) {
3224 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3225 if (EFI_ERROR (Status
)) {
3230 // Remove maintain backup list after save except for the current using FormSet.
3232 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3233 CleanBrowserStorage(LocalFormSet
);
3234 RemoveEntryList (&LocalFormSet
->Link
);
3235 DestroyFormSet (LocalFormSet
);
3238 mSystemSubmit
= FALSE
;
3240 Status
= EFI_SUCCESS
;
3243 // Process the save failed formsets.
3245 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3246 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3247 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3248 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3250 if (!ValidateFormSet(LocalFormSet
)) {
3254 Form
= LocalFormSet
->SaveFailForm
;
3255 Question
= LocalFormSet
->SaveFailStatement
;
3258 // Confirm with user, get user input.
3260 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3262 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3264 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3266 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3269 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3270 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3271 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3272 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3273 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3274 Storage
= FormSetStorage
->BrowserStorage
;
3275 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3277 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3280 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3281 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3282 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3283 Storage
= FormSetStorage
->BrowserStorage
;
3284 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3286 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3290 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3291 CleanBrowserStorage(LocalFormSet
);
3292 RemoveEntryList (&LocalFormSet
->Link
);
3293 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3294 DestroyFormSet (LocalFormSet
);
3296 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3299 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3300 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3303 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3305 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3306 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3307 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3308 gCurrentSelection
->FormId
= Form
->FormId
;
3309 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3311 Status
= EFI_UNSUPPORTED
;
3317 // Clean the list which will not process.
3319 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3320 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3321 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3322 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3324 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3325 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3326 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3327 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3335 Submit data based on the input Setting level (Form, FormSet or System).
3337 @param FormSet FormSet data structure.
3338 @param Form Form data structure.
3339 @param SettingScope Setting Scope for Submit action.
3341 @retval EFI_SUCCESS The function completed successfully.
3342 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3347 IN FORM_BROWSER_FORMSET
*FormSet
,
3348 IN FORM_BROWSER_FORM
*Form
,
3349 IN BROWSER_SETTING_SCOPE SettingScope
3354 switch (SettingScope
) {
3356 Status
= SubmitForForm(FormSet
, Form
);
3360 Status
= SubmitForFormSet (FormSet
, FALSE
);
3364 Status
= SubmitForSystem ();
3368 Status
= EFI_UNSUPPORTED
;
3376 Get Question default value from AltCfg string.
3378 @param FormSet The form set.
3379 @param Question The question.
3380 @param DefaultId The default Id.
3382 @retval EFI_SUCCESS Question is reset to default value.
3386 GetDefaultValueFromAltCfg (
3387 IN FORM_BROWSER_FORMSET
*FormSet
,
3388 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3392 BOOLEAN IsBufferStorage
;
3395 BROWSER_STORAGE
*Storage
;
3396 CHAR16
*ConfigRequest
;
3409 Status
= EFI_NOT_FOUND
;
3412 ConfigRequest
= NULL
;
3416 Storage
= Question
->Storage
;
3418 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3423 // Question Value is provided by Buffer Storage or NameValue Storage
3425 if (Question
->BufferValue
!= NULL
) {
3427 // This Question is password or orderedlist
3429 Dst
= Question
->BufferValue
;
3432 // Other type of Questions
3434 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
3437 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3438 IsBufferStorage
= TRUE
;
3440 IsBufferStorage
= FALSE
;
3442 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
3445 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
3446 // <ConfigHdr> + "&" + <VariableName>
3448 if (IsBufferStorage
) {
3449 Length
= StrLen (Storage
->ConfigHdr
);
3450 Length
+= StrLen (Question
->BlockName
);
3452 Length
= StrLen (Storage
->ConfigHdr
);
3453 Length
+= StrLen (Question
->VariableName
) + 1;
3455 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
3456 ASSERT (ConfigRequest
!= NULL
);
3458 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
3459 if (IsBufferStorage
) {
3460 StrCat (ConfigRequest
, Question
->BlockName
);
3462 StrCat (ConfigRequest
, L
"&");
3463 StrCat (ConfigRequest
, Question
->VariableName
);
3466 Status
= mHiiConfigRouting
->ExtractConfig (
3472 if (EFI_ERROR (Status
)) {
3477 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
3478 // Get the default configuration string according to the default ID.
3480 Status
= mHiiConfigRouting
->GetAltConfig (
3486 &DefaultId
, // it can be NULL to get the current setting.
3491 // The required setting can't be found. So, it is not required to be validated and set.
3493 if (EFI_ERROR (Status
)) {
3497 if (ConfigResp
== NULL
) {
3498 Status
= EFI_NOT_FOUND
;
3503 // Skip <ConfigRequest>
3505 if (IsBufferStorage
) {
3506 Value
= StrStr (ConfigResp
, L
"&VALUE");
3507 ASSERT (Value
!= NULL
);
3513 Value
= StrStr (ConfigResp
, Question
->VariableName
);
3514 ASSERT (Value
!= NULL
);
3516 Value
= Value
+ StrLen (Question
->VariableName
);
3518 if (*Value
!= '=') {
3519 Status
= EFI_NOT_FOUND
;
3523 // Skip '=', point to value
3528 // Suppress <AltResp> if any
3531 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3536 LengthStr
= StrLen (Value
);
3537 if (!IsBufferStorage
&& IsString
) {
3538 StringPtr
= (CHAR16
*) Dst
;
3539 ZeroMem (TemStr
, sizeof (TemStr
));
3540 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
3541 StrnCpy (TemStr
, Value
+ Index
, 4);
3542 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
3545 // Add tailing L'\0' character
3547 StringPtr
[Index
/4] = L
'\0';
3549 ZeroMem (TemStr
, sizeof (TemStr
));
3550 for (Index
= 0; Index
< LengthStr
; Index
++) {
3551 TemStr
[0] = Value
[LengthStr
- Index
- 1];
3552 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
3553 if ((Index
& 1) == 0) {
3554 Dst
[Index
/2] = DigitUint8
;
3556 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
3562 if (ConfigRequest
!= NULL
){
3563 FreePool (ConfigRequest
);
3566 if (ConfigResp
!= NULL
) {
3567 FreePool (ConfigResp
);
3570 if (Result
!= NULL
) {
3578 Get default Id value used for browser.
3580 @param DefaultId The default id value used by hii.
3582 @retval Browser used default value.
3586 GetDefaultIdForCallBack (
3590 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3591 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3592 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3593 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3594 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3595 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3596 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3597 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3598 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3599 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3600 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3601 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3610 Return data element in an Array by its Index.
3612 @param Array The data array.
3613 @param Type Type of the data in this array.
3614 @param Index Zero based index for data in this array.
3616 @retval Value The data to be returned
3628 ASSERT (Array
!= NULL
);
3632 case EFI_IFR_TYPE_NUM_SIZE_8
:
3633 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3636 case EFI_IFR_TYPE_NUM_SIZE_16
:
3637 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3640 case EFI_IFR_TYPE_NUM_SIZE_32
:
3641 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3644 case EFI_IFR_TYPE_NUM_SIZE_64
:
3645 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3657 Set value of a data element in an Array by its Index.
3659 @param Array The data array.
3660 @param Type Type of the data in this array.
3661 @param Index Zero based index for data in this array.
3662 @param Value The value to be set.
3674 ASSERT (Array
!= NULL
);
3677 case EFI_IFR_TYPE_NUM_SIZE_8
:
3678 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3681 case EFI_IFR_TYPE_NUM_SIZE_16
:
3682 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3685 case EFI_IFR_TYPE_NUM_SIZE_32
:
3686 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3689 case EFI_IFR_TYPE_NUM_SIZE_64
:
3690 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3699 Search an Option of a Question by its value.
3701 @param Question The Question
3702 @param OptionValue Value for Option to be searched.
3704 @retval Pointer Pointer to the found Option.
3705 @retval NULL Option not found.
3710 IN FORM_BROWSER_STATEMENT
*Question
,
3711 IN EFI_HII_VALUE
*OptionValue
3715 QUESTION_OPTION
*Option
;
3718 Link
= GetFirstNode (&Question
->OptionListHead
);
3719 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3720 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3722 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3724 // Check the suppressif condition, only a valid option can be return.
3726 if ((Option
->SuppressExpression
== NULL
) ||
3727 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3732 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3740 Reset Question to its default value.
3742 @param FormSet The form set.
3743 @param Form The form.
3744 @param Question The question.
3745 @param DefaultId The Class of the default.
3747 @retval EFI_SUCCESS Question is reset to default value.
3751 GetQuestionDefault (
3752 IN FORM_BROWSER_FORMSET
*FormSet
,
3753 IN FORM_BROWSER_FORM
*Form
,
3754 IN FORM_BROWSER_STATEMENT
*Question
,
3760 QUESTION_DEFAULT
*Default
;
3761 QUESTION_OPTION
*Option
;
3762 EFI_HII_VALUE
*HiiValue
;
3764 EFI_STRING StrValue
;
3765 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3766 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3770 Status
= EFI_NOT_FOUND
;
3774 // Statement don't have storage, skip them
3776 if (Question
->QuestionId
== 0) {
3781 // There are Five ways to specify default value for a Question:
3782 // 1, use call back function (highest priority)
3783 // 2, use ExtractConfig function
3784 // 3, use nested EFI_IFR_DEFAULT
3785 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3786 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3788 HiiValue
= &Question
->HiiValue
;
3791 // Get Question defaut value from call back function.
3793 ConfigAccess
= FormSet
->ConfigAccess
;
3794 Action
= GetDefaultIdForCallBack (DefaultId
);
3795 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3796 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3797 Status
= ConfigAccess
->Callback (
3800 Question
->QuestionId
,
3805 if (!EFI_ERROR (Status
)) {
3806 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3807 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3808 ASSERT (NewString
!= NULL
);
3810 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3811 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3812 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3814 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3817 FreePool (NewString
);
3824 // Get default value from altcfg string.
3826 if (ConfigAccess
!= NULL
) {
3827 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3828 if (!EFI_ERROR (Status
)) {
3834 // EFI_IFR_DEFAULT has highest priority
3836 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3837 Link
= GetFirstNode (&Question
->DefaultListHead
);
3838 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3839 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3841 if (Default
->DefaultId
== DefaultId
) {
3842 if (Default
->ValueExpression
!= NULL
) {
3844 // Default is provided by an Expression, evaluate it
3846 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3847 if (EFI_ERROR (Status
)) {
3851 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3852 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3853 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3854 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3855 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3857 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3858 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3860 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3862 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3863 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3866 // Default value is embedded in EFI_IFR_DEFAULT
3868 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3871 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3872 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3873 if (StrValue
== NULL
) {
3874 return EFI_NOT_FOUND
;
3876 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3877 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3879 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3886 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3891 // EFI_ONE_OF_OPTION
3893 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3894 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3896 // OneOfOption could only provide Standard and Manufacturing default
3898 Link
= GetFirstNode (&Question
->OptionListHead
);
3899 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3900 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3901 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3903 if ((Option
->SuppressExpression
!= NULL
) &&
3904 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3908 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3909 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3911 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3920 // EFI_IFR_CHECKBOX - lowest priority
3922 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3923 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3925 // Checkbox could only provide Standard and Manufacturing default
3927 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3928 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3930 HiiValue
->Value
.b
= TRUE
;
3932 HiiValue
->Value
.b
= FALSE
;
3940 // For Questions without default
3942 Status
= EFI_NOT_FOUND
;
3943 switch (Question
->Operand
) {
3944 case EFI_IFR_NUMERIC_OP
:
3946 // Take minimum value as numeric default value
3948 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3949 HiiValue
->Value
.u64
= Question
->Minimum
;
3950 Status
= EFI_SUCCESS
;
3954 case EFI_IFR_ONE_OF_OP
:
3956 // Take first oneof option as oneof's default value
3958 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3959 Link
= GetFirstNode (&Question
->OptionListHead
);
3960 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3961 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3962 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3964 if ((Option
->SuppressExpression
!= NULL
) &&
3965 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3969 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3970 Status
= EFI_SUCCESS
;
3976 case EFI_IFR_ORDERED_LIST_OP
:
3978 // Take option sequence in IFR as ordered list's default value
3981 Link
= GetFirstNode (&Question
->OptionListHead
);
3982 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3983 Status
= EFI_SUCCESS
;
3984 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3985 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3987 if ((Option
->SuppressExpression
!= NULL
) &&
3988 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3992 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3995 if (Index
>= Question
->MaxContainers
) {
4010 Reset Questions to their initial value or default value in a Form, Formset or System.
4012 GetDefaultValueScope parameter decides which questions will reset
4013 to its default value.
4015 @param FormSet FormSet data structure.
4016 @param Form Form data structure.
4017 @param DefaultId The Class of the default.
4018 @param SettingScope Setting Scope for Default action.
4019 @param GetDefaultValueScope Get default value scope.
4020 @param Storage Get default value only for this storage.
4021 @param RetrieveValueFirst Whether call the retrieve call back to
4022 get the initial value before get default
4025 @retval EFI_SUCCESS The function completed successfully.
4026 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4031 IN FORM_BROWSER_FORMSET
*FormSet
,
4032 IN FORM_BROWSER_FORM
*Form
,
4033 IN UINT16 DefaultId
,
4034 IN BROWSER_SETTING_SCOPE SettingScope
,
4035 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4036 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4037 IN BOOLEAN RetrieveValueFirst
4041 LIST_ENTRY
*FormLink
;
4043 FORM_BROWSER_STATEMENT
*Question
;
4044 FORM_BROWSER_FORMSET
*LocalFormSet
;
4045 FORM_BROWSER_FORMSET
*OldFormSet
;
4047 Status
= EFI_SUCCESS
;
4050 // Check the supported setting level.
4052 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4053 return EFI_UNSUPPORTED
;
4056 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4057 return EFI_UNSUPPORTED
;
4060 if (SettingScope
== FormLevel
) {
4062 // Extract Form default
4064 Link
= GetFirstNode (&Form
->StatementListHead
);
4065 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4066 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4067 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4070 // If get default value only for this storage, check the storage first.
4072 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4077 // If get default value only for no storage question, just skip the question which has storage.
4079 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4084 // If Question is disabled, don't reset it to default
4086 if (Question
->Expression
!= NULL
) {
4087 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4092 if (RetrieveValueFirst
) {
4094 // Call the Retrieve call back to get the initial question value.
4096 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4100 // If not request to get the initial value or get initial value fail, then get default value.
4102 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4103 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4104 if (EFI_ERROR (Status
)) {
4110 // Synchronize Buffer storage's Edit buffer
4112 if ((Question
->Storage
!= NULL
) &&
4113 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4114 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4117 } else if (SettingScope
== FormSetLevel
) {
4118 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4119 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4120 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4121 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4122 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4124 } else if (SettingScope
== SystemLevel
) {
4126 // Preload all Hii formset.
4128 LoadAllHiiFormset();
4130 OldFormSet
= mSystemLevelFormSet
;
4133 // Set Default Value for each FormSet in the maintain list.
4135 Link
= GetFirstNode (&gBrowserFormSetList
);
4136 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4137 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4138 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4139 if (!ValidateFormSet(LocalFormSet
)) {
4143 mSystemLevelFormSet
= LocalFormSet
;
4145 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
4148 mSystemLevelFormSet
= OldFormSet
;
4156 Validate whether this question's value has changed.
4158 @param FormSet FormSet data structure.
4159 @param Form Form data structure.
4160 @param Question Question to be initialized.
4161 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4163 @retval TRUE Question's value has changed.
4164 @retval FALSE Question's value has not changed
4168 IsQuestionValueChanged (
4169 IN FORM_BROWSER_FORMSET
*FormSet
,
4170 IN FORM_BROWSER_FORM
*Form
,
4171 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4172 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4175 EFI_HII_VALUE BackUpValue
;
4176 CHAR8
*BackUpBuffer
;
4177 EFI_HII_VALUE BackUpValue2
;
4178 CHAR8
*BackUpBuffer2
;
4180 BOOLEAN ValueChanged
;
4184 // For quetion without storage, always mark it as data not changed.
4186 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4190 BackUpBuffer
= NULL
;
4191 BackUpBuffer2
= NULL
;
4192 ValueChanged
= FALSE
;
4194 switch (Question
->Operand
) {
4195 case EFI_IFR_ORDERED_LIST_OP
:
4196 BufferWidth
= Question
->StorageWidth
;
4197 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4198 ASSERT (BackUpBuffer
!= NULL
);
4201 case EFI_IFR_STRING_OP
:
4202 case EFI_IFR_PASSWORD_OP
:
4203 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4204 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4205 ASSERT (BackUpBuffer
!= NULL
);
4212 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4214 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4215 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4216 ASSERT_EFI_ERROR(Status
);
4218 switch (Question
->Operand
) {
4219 case EFI_IFR_ORDERED_LIST_OP
:
4220 BufferWidth
= Question
->StorageWidth
;
4221 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4222 ASSERT (BackUpBuffer2
!= NULL
);
4225 case EFI_IFR_STRING_OP
:
4226 case EFI_IFR_PASSWORD_OP
:
4227 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4228 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4229 ASSERT (BackUpBuffer2
!= NULL
);
4236 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4238 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4239 ASSERT_EFI_ERROR(Status
);
4241 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4242 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4243 ValueChanged
= TRUE
;
4246 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4247 ASSERT_EFI_ERROR(Status
);
4249 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4250 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4251 ValueChanged
= TRUE
;
4255 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4256 if (BackUpBuffer
!= NULL
) {
4257 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4258 FreePool (BackUpBuffer
);
4261 if (BackUpBuffer2
!= NULL
) {
4262 FreePool (BackUpBuffer2
);
4265 Question
->ValueChanged
= ValueChanged
;
4267 return ValueChanged
;
4271 Initialize Question's Edit copy from Storage.
4273 @param Selection Selection contains the information about
4274 the Selection, form and formset to be displayed.
4275 Selection action may be updated in retrieve callback.
4276 If Selection is NULL, only initialize Question value.
4277 @param FormSet FormSet data structure.
4278 @param Form Form data structure.
4280 @retval EFI_SUCCESS The function completed successfully.
4285 IN OUT UI_MENU_SELECTION
*Selection
,
4286 IN FORM_BROWSER_FORMSET
*FormSet
,
4287 IN FORM_BROWSER_FORM
*Form
4292 FORM_BROWSER_STATEMENT
*Question
;
4294 Link
= GetFirstNode (&Form
->StatementListHead
);
4295 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4296 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4299 // Initialize local copy of Value for each Question
4301 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4302 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4304 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4306 if (EFI_ERROR (Status
)) {
4310 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4311 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4314 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4321 Initialize Question's Edit copy from Storage for the whole Formset.
4323 @param Selection Selection contains the information about
4324 the Selection, form and formset to be displayed.
4325 Selection action may be updated in retrieve callback.
4326 If Selection is NULL, only initialize Question value.
4327 @param FormSet FormSet data structure.
4329 @retval EFI_SUCCESS The function completed successfully.
4334 IN OUT UI_MENU_SELECTION
*Selection
,
4335 IN FORM_BROWSER_FORMSET
*FormSet
4340 FORM_BROWSER_FORM
*Form
;
4342 Link
= GetFirstNode (&FormSet
->FormListHead
);
4343 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4344 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4347 // Initialize local copy of Value for each Form
4349 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4350 if (EFI_ERROR (Status
)) {
4354 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4358 // Finished question initialization.
4360 FormSet
->QuestionInited
= TRUE
;
4366 Remove the Request element from the Config Request.
4368 @param Storage Pointer to the browser storage.
4369 @param RequestElement The pointer to the Request element.
4374 IN OUT BROWSER_STORAGE
*Storage
,
4375 IN CHAR16
*RequestElement
4381 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
4383 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
4385 if (NewStr
== NULL
) {
4390 // Remove this element from this ConfigRequest.
4393 NewStr
+= StrLen (RequestElement
);
4394 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
4396 Storage
->SpareStrLen
+= StrLen (RequestElement
);
4400 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
4402 @param Storage Pointer to the browser storage.
4403 @param ConfigRequest The pointer to the Request element.
4407 RemoveConfigRequest (
4408 BROWSER_STORAGE
*Storage
,
4409 CHAR16
*ConfigRequest
4412 CHAR16
*RequestElement
;
4413 CHAR16
*NextRequestElement
;
4417 // No request element in it, just return.
4419 if (ConfigRequest
== NULL
) {
4423 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4425 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4430 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4432 SearchKey
= L
"&OFFSET";
4436 // Find SearchKey storage
4438 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4439 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4440 ASSERT (RequestElement
!= NULL
);
4441 RequestElement
= StrStr (RequestElement
, SearchKey
);
4443 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4446 while (RequestElement
!= NULL
) {
4448 // +1 to avoid find header itself.
4450 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4453 // The last Request element in configRequest string.
4455 if (NextRequestElement
!= NULL
) {
4457 // Replace "&" with '\0'.
4459 *NextRequestElement
= L
'\0';
4462 RemoveElement (Storage
, RequestElement
);
4464 if (NextRequestElement
!= NULL
) {
4466 // Restore '&' with '\0' for later used.
4468 *NextRequestElement
= L
'&';
4471 RequestElement
= NextRequestElement
;
4475 // If no request element remain, just remove the ConfigRequest string.
4477 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
4478 FreePool (Storage
->ConfigRequest
);
4479 Storage
->ConfigRequest
= NULL
;
4480 Storage
->SpareStrLen
= 0;
4485 Base on the current formset info, clean the ConfigRequest string in browser storage.
4487 @param FormSet Pointer of the FormSet
4491 CleanBrowserStorage (
4492 IN OUT FORM_BROWSER_FORMSET
*FormSet
4496 FORMSET_STORAGE
*Storage
;
4498 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4499 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4500 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4501 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4503 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
4504 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4508 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4509 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4510 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4511 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4512 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
4513 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
4515 Storage
->BrowserStorage
->Initialized
= FALSE
;
4521 Check whether current element in the ConfigReqeust string.
4523 @param BrowserStorage Storage which includes ConfigReqeust.
4524 @param RequestElement New element need to check.
4526 @retval TRUE The Element is in the ConfigReqeust string.
4527 @retval FALSE The Element not in the configReqeust String.
4532 BROWSER_STORAGE
*BrowserStorage
,
4533 CHAR16
*RequestElement
4536 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
4540 Append the Request element to the Config Request.
4542 @param ConfigRequest Current ConfigRequest info.
4543 @param SpareStrLen Current remain free buffer for config reqeust.
4544 @param RequestElement New Request element.
4548 AppendConfigRequest (
4549 IN OUT CHAR16
**ConfigRequest
,
4550 IN OUT UINTN
*SpareStrLen
,
4551 IN CHAR16
*RequestElement
4558 StrLength
= StrLen (RequestElement
);
4561 // Append <RequestElement> to <ConfigRequest>
4563 if (StrLength
> *SpareStrLen
) {
4565 // Old String buffer is not sufficient for RequestElement, allocate a new one
4567 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
4568 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
4569 ASSERT (NewStr
!= NULL
);
4571 if (*ConfigRequest
!= NULL
) {
4572 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
4573 FreePool (*ConfigRequest
);
4575 *ConfigRequest
= NewStr
;
4576 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
4579 StrCat (*ConfigRequest
, RequestElement
);
4580 *SpareStrLen
-= StrLength
;
4584 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
4586 @param Storage Form set Storage.
4587 @param Request The input request string.
4588 @param RespString Whether the input is ConfigRequest or ConfigResp format.
4590 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
4591 @retval FALSE All elements covered by current used elements.
4595 ConfigRequestAdjust (
4596 IN BROWSER_STORAGE
*Storage
,
4598 IN BOOLEAN RespString
4601 CHAR16
*RequestElement
;
4602 CHAR16
*NextRequestElement
;
4603 CHAR16
*NextElementBakup
;
4608 CHAR16
*ConfigRequest
;
4612 NextElementBakup
= NULL
;
4615 if (Request
!= NULL
) {
4616 ConfigRequest
= Request
;
4618 ConfigRequest
= Storage
->ConfigRequest
;
4621 if (Storage
->ConfigRequest
== NULL
) {
4622 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4626 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4628 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4633 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4635 SearchKey
= L
"&OFFSET";
4636 ValueKey
= L
"&VALUE";
4640 // Find SearchKey storage
4642 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4643 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
4644 ASSERT (RequestElement
!= NULL
);
4645 RequestElement
= StrStr (RequestElement
, SearchKey
);
4647 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
4650 while (RequestElement
!= NULL
) {
4653 // +1 to avoid find header itself.
4655 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4658 // The last Request element in configRequest string.
4660 if (NextRequestElement
!= NULL
) {
4661 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4662 NextElementBakup
= NextRequestElement
;
4663 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4664 ASSERT (NextRequestElement
!= NULL
);
4667 // Replace "&" with '\0'.
4669 *NextRequestElement
= L
'\0';
4671 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4672 NextElementBakup
= NextRequestElement
;
4673 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
4674 ASSERT (NextRequestElement
!= NULL
);
4676 // Replace "&" with '\0'.
4678 *NextRequestElement
= L
'\0';
4682 if (!ElementValidation (Storage
, RequestElement
)) {
4684 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4686 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
4690 if (NextRequestElement
!= NULL
) {
4692 // Restore '&' with '\0' for later used.
4694 *NextRequestElement
= L
'&';
4697 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4698 RequestElement
= NextElementBakup
;
4700 RequestElement
= NextRequestElement
;
4709 Base on ConfigRequest info to get default value for current formset.
4711 ConfigRequest info include the info about which questions in current formset need to
4712 get default value. This function only get these questions default value.
4714 @param FormSet FormSet data structure.
4715 @param Storage Storage need to update value.
4716 @param ConfigRequest The config request string.
4720 GetDefaultForFormset (
4721 IN FORM_BROWSER_FORMSET
*FormSet
,
4722 IN BROWSER_STORAGE
*Storage
,
4723 IN CHAR16
*ConfigRequest
4728 LIST_ENTRY BackUpList
;
4729 NAME_VALUE_NODE
*Node
;
4731 LIST_ENTRY
*NodeLink
;
4732 NAME_VALUE_NODE
*TmpNode
;
4734 EFI_STRING Progress
;
4738 InitializeListHead(&BackUpList
);
4741 // Back update the edit buffer.
4743 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4744 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4745 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4746 ASSERT (BackUpBuf
!= NULL
);
4747 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4748 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4749 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4750 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4751 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4754 // Only back Node belong to this formset.
4756 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4760 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4761 ASSERT (TmpNode
!= NULL
);
4762 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4763 ASSERT (TmpNode
->Name
!= NULL
);
4764 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4765 ASSERT (TmpNode
->EditValue
!= NULL
);
4767 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4772 // Get default value.
4774 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4777 // Update the question value based on the input ConfigRequest.
4779 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4780 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4781 ASSERT (BackUpBuf
!= NULL
);
4782 BufferSize
= Storage
->Size
;
4783 Status
= mHiiConfigRouting
->BlockToConfig(
4786 Storage
->EditBuffer
,
4791 ASSERT_EFI_ERROR (Status
);
4793 Status
= mHiiConfigRouting
->ConfigToBlock (
4800 ASSERT_EFI_ERROR (Status
);
4802 if (Result
!= NULL
) {
4806 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4807 FreePool (BackUpBuf
);
4808 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4810 // Update question value, only element in ConfigReqeust will be update.
4812 Link
= GetFirstNode (&BackUpList
);
4813 while (!IsNull (&BackUpList
, Link
)) {
4814 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4815 Link
= GetNextNode (&BackUpList
, Link
);
4817 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4821 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4822 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4823 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4824 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4826 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4830 FreePool (TmpNode
->EditValue
);
4831 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4833 RemoveEntryList (&Node
->Link
);
4834 FreePool (Node
->EditValue
);
4835 FreePool (Node
->Name
);
4841 // Restore the Name/Value node.
4843 Link
= GetFirstNode (&BackUpList
);
4844 while (!IsNull (&BackUpList
, Link
)) {
4845 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4846 Link
= GetNextNode (&BackUpList
, Link
);
4851 RemoveEntryList (&Node
->Link
);
4852 FreePool (Node
->EditValue
);
4853 FreePool (Node
->Name
);
4860 Fill storage's edit copy with settings requested from Configuration Driver.
4862 @param FormSet FormSet data structure.
4863 @param Storage Buffer Storage.
4868 IN FORM_BROWSER_FORMSET
*FormSet
,
4869 IN FORMSET_STORAGE
*Storage
4873 EFI_STRING Progress
;
4876 EFI_STRING ConfigRequest
;
4879 ConfigRequest
= NULL
;
4881 switch (Storage
->BrowserStorage
->Type
) {
4882 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4885 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4886 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4887 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4892 case EFI_HII_VARSTORE_BUFFER
:
4893 case EFI_HII_VARSTORE_NAME_VALUE
:
4895 // Skip if there is no RequestElement.
4897 if (Storage
->ElementCount
== 0) {
4902 // Just update the ConfigRequest, if storage already initialized.
4904 if (Storage
->BrowserStorage
->Initialized
) {
4905 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4909 Storage
->BrowserStorage
->Initialized
= TRUE
;
4916 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4918 // Create the config request string to get all fields for this storage.
4919 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4920 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4922 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4923 ConfigRequest
= AllocateZeroPool (StrLen
);
4924 ASSERT (ConfigRequest
!= NULL
);
4928 L
"%s&OFFSET=0&WIDTH=%04x",
4929 Storage
->BrowserStorage
->ConfigHdr
,
4930 Storage
->BrowserStorage
->Size
);
4932 ConfigRequest
= Storage
->ConfigRequest
;
4936 // Request current settings from Configuration Driver
4938 Status
= mHiiConfigRouting
->ExtractConfig (
4946 // If get value fail, extract default from IFR binary
4948 if (EFI_ERROR (Status
)) {
4949 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4952 // Convert Result from <ConfigAltResp> to <ConfigResp>
4954 StrPtr
= StrStr (Result
, L
"&GUID=");
4955 if (StrPtr
!= NULL
) {
4959 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4963 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4966 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4968 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
4970 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4971 if (ConfigRequest
!= NULL
) {
4972 FreePool (ConfigRequest
);
4978 Get Value changed status from old question.
4980 @param NewFormSet FormSet data structure.
4981 @param OldQuestion Old question which has value changed.
4985 SyncStatusForQuestion (
4986 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4987 IN FORM_BROWSER_STATEMENT
*OldQuestion
4991 LIST_ENTRY
*QuestionLink
;
4992 FORM_BROWSER_FORM
*Form
;
4993 FORM_BROWSER_STATEMENT
*Question
;
4996 // For each form in one formset.
4998 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4999 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5000 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5001 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5004 // for each question in one form.
5006 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5007 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5008 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5009 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5011 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5012 Question
->ValueChanged
= TRUE
;
5020 Get Value changed status from old formset.
5022 @param NewFormSet FormSet data structure.
5023 @param OldFormSet FormSet data structure.
5027 SyncStatusForFormSet (
5028 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5029 IN FORM_BROWSER_FORMSET
*OldFormSet
5033 LIST_ENTRY
*QuestionLink
;
5034 FORM_BROWSER_FORM
*Form
;
5035 FORM_BROWSER_STATEMENT
*Question
;
5038 // For each form in one formset.
5040 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5041 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5042 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5043 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5046 // for each question in one form.
5048 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5049 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5050 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5051 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5053 if (!Question
->ValueChanged
) {
5058 // Find the same question in new formset and update the value changed flag.
5060 SyncStatusForQuestion (NewFormSet
, Question
);
5066 Get current setting of Questions.
5068 @param FormSet FormSet data structure.
5072 InitializeCurrentSetting (
5073 IN OUT FORM_BROWSER_FORMSET
*FormSet
5077 FORMSET_STORAGE
*Storage
;
5078 FORM_BROWSER_FORMSET
*OldFormSet
;
5081 // Try to find pre FormSet in the maintain backup list.
5082 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5084 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5085 if (OldFormSet
!= NULL
) {
5086 SyncStatusForFormSet (FormSet
, OldFormSet
);
5087 RemoveEntryList (&OldFormSet
->Link
);
5088 DestroyFormSet (OldFormSet
);
5090 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5093 // Extract default from IFR binary for no storage questions.
5095 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
5098 // Request current settings from Configuration Driver
5100 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5101 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5102 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5104 LoadStorage (FormSet
, Storage
);
5106 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5112 Fetch the Ifr binary data of a FormSet.
5114 @param Handle PackageList Handle
5115 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5116 specified (NULL or zero GUID), take the first
5117 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5118 found in package list.
5119 On output, GUID of the formset found(if not NULL).
5120 @param BinaryLength The length of the FormSet IFR binary.
5121 @param BinaryData The buffer designed to receive the FormSet.
5123 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5124 BufferLength was updated.
5125 @retval EFI_INVALID_PARAMETER The handle is unknown.
5126 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5127 be found with the requested FormId.
5132 IN EFI_HII_HANDLE Handle
,
5133 IN OUT EFI_GUID
*FormSetGuid
,
5134 OUT UINTN
*BinaryLength
,
5135 OUT UINT8
**BinaryData
5139 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5145 UINT32 PackageListLength
;
5146 EFI_HII_PACKAGE_HEADER PackageHeader
;
5148 UINT8 NumberOfClassGuid
;
5149 BOOLEAN ClassGuidMatch
;
5150 EFI_GUID
*ClassGuid
;
5151 EFI_GUID
*ComparingGuid
;
5155 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5158 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5160 if (FormSetGuid
== NULL
) {
5161 ComparingGuid
= &gZeroGuid
;
5163 ComparingGuid
= FormSetGuid
;
5167 // Get HII PackageList
5170 HiiPackageList
= NULL
;
5171 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5172 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5173 HiiPackageList
= AllocatePool (BufferSize
);
5174 ASSERT (HiiPackageList
!= NULL
);
5176 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5178 if (EFI_ERROR (Status
)) {
5181 ASSERT (HiiPackageList
!= NULL
);
5184 // Get Form package from this HII package List
5186 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5188 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5190 ClassGuidMatch
= FALSE
;
5191 while (Offset
< PackageListLength
) {
5192 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5193 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5195 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5197 // Search FormSet in this Form Package
5199 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5200 while (Offset2
< PackageHeader
.Length
) {
5201 OpCodeData
= Package
+ Offset2
;
5203 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5205 // Try to compare against formset GUID
5207 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5208 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5212 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5214 // Try to compare against formset class GUID
5216 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5217 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5218 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5219 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5220 ClassGuidMatch
= TRUE
;
5224 if (ClassGuidMatch
) {
5227 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5228 ClassGuidMatch
= TRUE
;
5233 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5236 if (Offset2
< PackageHeader
.Length
) {
5238 // Target formset found
5244 Offset
+= PackageHeader
.Length
;
5247 if (Offset
>= PackageListLength
) {
5249 // Form package not found in this Package List
5251 FreePool (HiiPackageList
);
5252 return EFI_NOT_FOUND
;
5255 if (FormSetGuid
!= NULL
) {
5257 // Return the FormSet GUID
5259 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5263 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5264 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5265 // of the Form Package.
5267 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5268 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5270 FreePool (HiiPackageList
);
5272 if (*BinaryData
== NULL
) {
5273 return EFI_OUT_OF_RESOURCES
;
5281 Initialize the internal data structure of a FormSet.
5283 @param Handle PackageList Handle
5284 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5285 specified (NULL or zero GUID), take the first
5286 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5287 found in package list.
5288 On output, GUID of the formset found(if not NULL).
5289 @param FormSet FormSet data structure.
5291 @retval EFI_SUCCESS The function completed successfully.
5292 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5297 IN EFI_HII_HANDLE Handle
,
5298 IN OUT EFI_GUID
*FormSetGuid
,
5299 OUT FORM_BROWSER_FORMSET
*FormSet
5303 EFI_HANDLE DriverHandle
;
5305 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5306 if (EFI_ERROR (Status
)) {
5310 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5311 FormSet
->HiiHandle
= Handle
;
5312 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5313 FormSet
->QuestionInited
= FALSE
;
5316 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5318 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5319 if (EFI_ERROR (Status
)) {
5322 FormSet
->DriverHandle
= DriverHandle
;
5323 Status
= gBS
->HandleProtocol (
5325 &gEfiHiiConfigAccessProtocolGuid
,
5326 (VOID
**) &FormSet
->ConfigAccess
5328 if (EFI_ERROR (Status
)) {
5330 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5331 // list, then there will be no configuration action required
5333 FormSet
->ConfigAccess
= NULL
;
5337 // Parse the IFR binary OpCodes
5339 Status
= ParseOpCodes (FormSet
);
5346 Save globals used by previous call to SendForm(). SendForm() may be called from
5347 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5348 So, save globals of previous call to SendForm() and restore them upon exit.
5352 SaveBrowserContext (
5356 BROWSER_CONTEXT
*Context
;
5357 FORM_ENTRY_INFO
*MenuList
;
5359 gBrowserContextCount
++;
5360 if (gBrowserContextCount
== 1) {
5362 // This is not reentry of SendForm(), no context to save
5367 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5368 ASSERT (Context
!= NULL
);
5370 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5373 // Save FormBrowser context
5375 Context
->Selection
= gCurrentSelection
;
5376 Context
->ResetRequired
= gResetRequired
;
5377 Context
->ExitRequired
= gExitRequired
;
5378 Context
->HiiHandle
= mCurrentHiiHandle
;
5379 Context
->FormId
= mCurrentFormId
;
5380 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5383 // Save the menu history data.
5385 InitializeListHead(&Context
->FormHistoryList
);
5386 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5387 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5388 RemoveEntryList (&MenuList
->Link
);
5390 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5394 // Insert to FormBrowser context list
5396 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5401 Restore globals used by previous call to SendForm().
5405 RestoreBrowserContext (
5410 BROWSER_CONTEXT
*Context
;
5411 FORM_ENTRY_INFO
*MenuList
;
5413 ASSERT (gBrowserContextCount
!= 0);
5414 gBrowserContextCount
--;
5415 if (gBrowserContextCount
== 0) {
5417 // This is not reentry of SendForm(), no context to restore
5422 ASSERT (!IsListEmpty (&gBrowserContextList
));
5424 Link
= GetFirstNode (&gBrowserContextList
);
5425 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5428 // Restore FormBrowser context
5430 gCurrentSelection
= Context
->Selection
;
5431 gResetRequired
= Context
->ResetRequired
;
5432 gExitRequired
= Context
->ExitRequired
;
5433 mCurrentHiiHandle
= Context
->HiiHandle
;
5434 mCurrentFormId
= Context
->FormId
;
5435 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5438 // Restore the menu history data.
5440 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5441 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5442 RemoveEntryList (&MenuList
->Link
);
5444 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5448 // Remove from FormBrowser context list
5450 RemoveEntryList (&Context
->Link
);
5451 gBS
->FreePool (Context
);
5455 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5457 @param Handle The Hii Handle.
5459 @return the found FormSet context. If no found, NULL will return.
5462 FORM_BROWSER_FORMSET
*
5463 GetFormSetFromHiiHandle (
5464 EFI_HII_HANDLE Handle
5468 FORM_BROWSER_FORMSET
*FormSet
;
5470 Link
= GetFirstNode (&gBrowserFormSetList
);
5471 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5472 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5473 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5474 if (!ValidateFormSet(FormSet
)) {
5477 if (FormSet
->HiiHandle
== Handle
) {
5486 Check whether the input HII handle is the FormSet that is being used.
5488 @param Handle The Hii Handle.
5490 @retval TRUE HII handle is being used.
5491 @retval FALSE HII handle is not being used.
5495 IsHiiHandleInBrowserContext (
5496 EFI_HII_HANDLE Handle
5500 BROWSER_CONTEXT
*Context
;
5503 // HiiHandle is Current FormSet.
5505 if (mCurrentHiiHandle
== Handle
) {
5510 // Check whether HiiHandle is in BrowserContext.
5512 Link
= GetFirstNode (&gBrowserContextList
);
5513 while (!IsNull (&gBrowserContextList
, Link
)) {
5514 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5515 if (Context
->HiiHandle
== Handle
) {
5517 // HiiHandle is in BrowserContext
5521 Link
= GetNextNode (&gBrowserContextList
, Link
);
5528 Perform Password check.
5529 Passwork may be encrypted by driver that requires the specific check.
5531 @param Form Form where Password Statement is in.
5532 @param Statement Password statement
5533 @param PasswordString Password string to be checked. It may be NULL.
5534 NULL means to restore password.
5535 "" string can be used to checked whether old password does exist.
5537 @return Status Status of Password check.
5542 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
5543 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
5544 IN EFI_STRING PasswordString OPTIONAL
5548 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5549 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
5550 EFI_IFR_TYPE_VALUE IfrTypeValue
;
5551 FORM_BROWSER_STATEMENT
*Question
;
5553 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
5554 Question
= GetBrowserStatement(Statement
);
5555 ASSERT (Question
!= NULL
);
5557 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
5558 if (ConfigAccess
== NULL
) {
5559 return EFI_UNSUPPORTED
;
5562 if (PasswordString
== NULL
) {
5567 // Check whether has preexisted password.
5569 if (PasswordString
[0] == 0) {
5570 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
5573 return EFI_NOT_READY
;
5578 // Check whether the input password is same as preexisted password.
5580 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
5583 return EFI_NOT_READY
;
5588 // Prepare password string in HII database
5590 if (PasswordString
!= NULL
) {
5591 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
5593 IfrTypeValue
.string
= 0;
5597 // Send password to Configuration Driver for validation
5599 Status
= ConfigAccess
->Callback (
5601 EFI_BROWSER_ACTION_CHANGING
,
5602 Question
->QuestionId
,
5603 Question
->HiiValue
.Type
,
5609 // Remove password string from HII database
5611 if (PasswordString
!= NULL
) {
5612 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
5619 Find the registered HotKey based on KeyData.
5621 @param[in] KeyData A pointer to a buffer that describes the keystroke
5622 information for the hot key.
5624 @return The registered HotKey context. If no found, NULL will return.
5627 GetHotKeyFromRegisterList (
5628 IN EFI_INPUT_KEY
*KeyData
5632 BROWSER_HOT_KEY
*HotKey
;
5634 Link
= GetFirstNode (&gBrowserHotKeyList
);
5635 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
5636 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
5637 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
5640 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
5647 Configure what scope the hot key will impact.
5648 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
5649 If no scope is set, the default scope will be FormSet level.
5650 After all registered hot keys are removed, previous Scope can reset to another level.
5652 @param[in] Scope Scope level to be set.
5654 @retval EFI_SUCCESS Scope is set correctly.
5655 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
5656 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
5662 IN BROWSER_SETTING_SCOPE Scope
5665 if (Scope
>= MaxLevel
) {
5666 return EFI_INVALID_PARAMETER
;
5670 // When no hot key registered in system or on the first setting,
5671 // Scope can be set.
5673 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
5674 gBrowserSettingScope
= Scope
;
5675 mBrowserScopeFirstSet
= FALSE
;
5676 } else if (Scope
!= gBrowserSettingScope
) {
5677 return EFI_UNSUPPORTED
;
5684 Register the hot key with its browser action, or unregistered the hot key.
5685 Only support hot key that is not printable character (control key, function key, etc.).
5686 If the action value is zero, the hot key will be unregistered if it has been registered.
5687 If the same hot key has been registered, the new action and help string will override the previous ones.
5689 @param[in] KeyData A pointer to a buffer that describes the keystroke
5690 information for the hot key. Its type is EFI_INPUT_KEY to
5691 be supported by all ConsoleIn devices.
5692 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
5693 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
5694 @param[in] HelpString Help string that describes the hot key information.
5695 Its value may be NULL for the unregistered hot key.
5697 @retval EFI_SUCCESS Hot key is registered or unregistered.
5698 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
5699 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
5700 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5705 IN EFI_INPUT_KEY
*KeyData
,
5707 IN UINT16 DefaultId
,
5708 IN EFI_STRING HelpString OPTIONAL
5711 BROWSER_HOT_KEY
*HotKey
;
5714 // Check input parameters.
5716 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5717 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5718 return EFI_INVALID_PARAMETER
;
5722 // Check whether the input KeyData is in BrowserHotKeyList.
5724 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5727 // Unregister HotKey
5729 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5730 if (HotKey
!= NULL
) {
5732 // The registered HotKey is found.
5733 // Remove it from List, and free its resource.
5735 RemoveEntryList (&HotKey
->Link
);
5736 FreePool (HotKey
->KeyData
);
5737 FreePool (HotKey
->HelpString
);
5741 // The registered HotKey is not found.
5743 return EFI_NOT_FOUND
;
5748 // Register HotKey into List.
5750 if (HotKey
== NULL
) {
5752 // Create new Key, and add it into List.
5754 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5755 ASSERT (HotKey
!= NULL
);
5756 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5757 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5758 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5762 // Fill HotKey information.
5764 HotKey
->Action
= Action
;
5765 HotKey
->DefaultId
= DefaultId
;
5766 if (HotKey
->HelpString
!= NULL
) {
5767 FreePool (HotKey
->HelpString
);
5769 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5775 Register Exit handler function.
5776 When more than one handler function is registered, the latter one will override the previous one.
5777 When NULL handler is specified, the previous Exit handler will be unregistered.
5779 @param[in] Handler Pointer to handler function.
5784 RegiserExitHandler (
5785 IN EXIT_HANDLER Handler
5788 ExitHandlerFunction
= Handler
;
5793 Check whether the browser data has been modified.
5795 @retval TRUE Browser data is modified.
5796 @retval FALSE No browser data is modified.
5801 IsBrowserDataModified (
5806 FORM_BROWSER_FORMSET
*FormSet
;
5808 switch (gBrowserSettingScope
) {
5810 if (gCurrentSelection
== NULL
) {
5813 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5816 if (gCurrentSelection
== NULL
) {
5819 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5822 Link
= GetFirstNode (&gBrowserFormSetList
);
5823 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5824 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5825 if (!ValidateFormSet(FormSet
)) {
5829 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5832 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5842 Execute the action requested by the Action parameter.
5844 @param[in] Action Execute the request action.
5845 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5847 @retval EFI_SUCCESS Execute the request action succss.
5848 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5859 FORM_BROWSER_FORMSET
*FormSet
;
5860 FORM_BROWSER_FORM
*Form
;
5862 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5863 return EFI_NOT_READY
;
5866 Status
= EFI_SUCCESS
;
5869 if (gBrowserSettingScope
< SystemLevel
) {
5870 FormSet
= gCurrentSelection
->FormSet
;
5871 Form
= gCurrentSelection
->Form
;
5875 // Executet the discard action.
5877 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5878 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5879 if (EFI_ERROR (Status
)) {
5885 // Executet the difault action.
5887 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5888 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5889 if (EFI_ERROR (Status
)) {
5892 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5896 // Executet the submit action.
5898 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5899 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5900 if (EFI_ERROR (Status
)) {
5906 // Executet the reset action.
5908 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5909 gResetRequired
= TRUE
;
5913 // Executet the exit action.
5915 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5916 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5917 if (gBrowserSettingScope
== SystemLevel
) {
5918 if (ExitHandlerFunction
!= NULL
) {
5919 ExitHandlerFunction ();
5923 gExitRequired
= TRUE
;
5930 Create reminder to let user to choose save or discard the changed browser data.
5931 Caller can use it to actively check the changed browser data.
5933 @retval BROWSER_NO_CHANGES No browser data is changed.
5934 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5935 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5936 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5946 FORM_BROWSER_FORMSET
*FormSet
;
5947 BOOLEAN IsDataChanged
;
5948 UINT32 DataSavedAction
;
5951 DataSavedAction
= BROWSER_NO_CHANGES
;
5952 IsDataChanged
= FALSE
;
5953 Link
= GetFirstNode (&gBrowserFormSetList
);
5954 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5955 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5956 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5957 if (!ValidateFormSet(FormSet
)) {
5960 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5961 IsDataChanged
= TRUE
;
5967 // No data is changed. No save is required.
5969 if (!IsDataChanged
) {
5970 return DataSavedAction
;
5974 // If data is changed, prompt user to save or discard it.
5977 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5979 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5980 SubmitForm (NULL
, NULL
, SystemLevel
);
5981 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5983 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5984 DiscardForm (NULL
, NULL
, SystemLevel
);
5985 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5987 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5988 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5993 return DataSavedAction
;
5997 Check whether the Reset Required for the browser
5999 @retval TRUE Browser required to reset after exit.
6000 @retval FALSE Browser not need to reset after exit.
6009 return gResetRequired
;