2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2017, 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 BOOLEAN gFlagReconnect
;
59 BOOLEAN gCallbackReconnect
;
60 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
61 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
62 EXIT_HANDLER ExitHandlerFunction
= NULL
;
63 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
66 // Browser Global Strings
69 CHAR16
*mUnknownString
= L
"!";
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 (IsZeroGuid (&MenuList
->FormSetGuid
)) {
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
;
489 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
491 if (mFormDisplay
== NULL
) {
492 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
493 return EFI_UNSUPPORTED
;
497 // Save globals used by SendForm()
499 SaveBrowserContext ();
501 gFlagReconnect
= FALSE
;
502 gResetRequired
= FALSE
;
503 gExitRequired
= FALSE
;
504 gCallbackReconnect
= FALSE
;
505 Status
= EFI_SUCCESS
;
507 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
509 for (Index
= 0; Index
< HandleCount
; Index
++) {
510 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
511 ASSERT (Selection
!= NULL
);
513 Selection
->Handle
= Handles
[Index
];
514 if (FormSetGuid
!= NULL
) {
515 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
516 Selection
->FormId
= FormId
;
518 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
522 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
523 ASSERT (FormSet
!= NULL
);
526 // Validate the HiiHandle
527 // if validate failed, find the first validate parent HiiHandle.
529 if (!ValidateHiiHandle(Selection
->Handle
)) {
530 FindNextMenu (Selection
, FormSetLevel
);
534 // Initialize internal data structures of FormSet
536 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
537 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
538 DestroyFormSet (FormSet
);
541 Selection
->FormSet
= FormSet
;
542 mSystemLevelFormSet
= FormSet
;
545 // Display this formset
547 gCurrentSelection
= Selection
;
549 Status
= SetupBrowser (Selection
);
551 gCurrentSelection
= NULL
;
552 mSystemLevelFormSet
= NULL
;
554 if (gFlagReconnect
|| gCallbackReconnect
) {
555 RetVal
= ReconnectController (FormSet
->DriverHandle
);
557 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
559 gFlagReconnect
= FALSE
;
560 gCallbackReconnect
= FALSE
;
564 // If no data is changed, don't need to save current FormSet into the maintain list.
566 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
567 CleanBrowserStorage(FormSet
);
568 RemoveEntryList (&FormSet
->Link
);
569 DestroyFormSet (FormSet
);
572 if (EFI_ERROR (Status
)) {
575 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
577 FreePool (Selection
);
580 if (ActionRequest
!= NULL
) {
581 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
582 if (gResetRequired
) {
583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
587 mFormDisplay
->ExitDisplay();
590 // Clear the menu history data.
592 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
593 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
594 RemoveEntryList (&MenuList
->Link
);
599 // Restore globals used by SendForm()
601 RestoreBrowserContext ();
607 Get or set data to the storage.
609 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
610 @param ResultsData A string returned from an IFR browser or
611 equivalent. The results string will have no
612 routing information in them.
613 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
614 (if RetrieveData = TRUE) data from the uncommitted
615 browser state information or set (if RetrieveData
616 = FALSE) data in the uncommitted browser state
618 @param Storage The pointer to the storage.
620 @retval EFI_SUCCESS The results have been distributed or are awaiting
626 IN OUT UINTN
*ResultsDataSize
,
627 IN OUT EFI_STRING
*ResultsData
,
628 IN BOOLEAN RetrieveData
,
629 IN BROWSER_STORAGE
*Storage
638 FORMSET_STORAGE
*BrowserStorage
;
642 // Generate <ConfigResp>
644 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
645 if (EFI_ERROR (Status
)) {
650 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
651 // Also need to consider add "\0" at first time.
653 StrPtr
= StrStr (ConfigResp
, L
"PATH");
654 ASSERT (StrPtr
!= NULL
);
655 StrPtr
= StrStr (StrPtr
, L
"&");
657 BufferSize
= StrSize (StrPtr
);
660 // Copy the data if the input buffer is bigger enough.
662 if (*ResultsDataSize
>= BufferSize
) {
663 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
666 *ResultsDataSize
= BufferSize
;
667 FreePool (ConfigResp
);
670 // Prepare <ConfigResp>
672 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
673 ASSERT (BrowserStorage
!= NULL
);
674 TmpSize
= StrLen (*ResultsData
);
675 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
676 MaxLen
= BufferSize
/ sizeof (CHAR16
);
677 ConfigResp
= AllocateZeroPool (BufferSize
);
678 ASSERT (ConfigResp
!= NULL
);
680 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
681 StrCatS (ConfigResp
, MaxLen
, L
"&");
682 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
685 // Update Browser uncommited data
687 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
688 FreePool (ConfigResp
);
689 if (EFI_ERROR (Status
)) {
698 This routine called this service in the browser to retrieve or set certain uncommitted
699 state information that resides in the open formsets.
701 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
703 @param ResultsDataSize A pointer to the size of the buffer associated
705 @param ResultsData A string returned from an IFR browser or
706 equivalent. The results string will have no
707 routing information in them.
708 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
709 (if RetrieveData = TRUE) data from the uncommitted
710 browser state information or set (if RetrieveData
711 = FALSE) data in the uncommitted browser state
713 @param VariableGuid An optional field to indicate the target variable
715 @param VariableName An optional field to indicate the target
716 human-readable variable name.
718 @retval EFI_SUCCESS The results have been distributed or are awaiting
720 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
721 contain the results data.
727 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
728 IN OUT UINTN
*ResultsDataSize
,
729 IN OUT EFI_STRING ResultsData
,
730 IN BOOLEAN RetrieveData
,
731 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
732 IN CONST CHAR16
*VariableName OPTIONAL
737 BROWSER_STORAGE
*Storage
;
738 FORMSET_STORAGE
*FormsetStorage
;
742 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
743 return EFI_INVALID_PARAMETER
;
746 TotalSize
= *ResultsDataSize
;
749 Status
= EFI_SUCCESS
;
751 if (VariableGuid
!= NULL
) {
753 // Try to find target storage in the current formset.
755 Link
= GetFirstNode (&gBrowserStorageList
);
756 while (!IsNull (&gBrowserStorageList
, Link
)) {
757 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
758 Link
= GetNextNode (&gBrowserStorageList
, Link
);
760 // Check the current storage.
762 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
766 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
767 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
769 // Buffer storage require both GUID and Name
771 if (VariableName
== NULL
) {
772 return EFI_NOT_FOUND
;
775 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
780 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
781 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
782 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
783 return EFI_NOT_FOUND
;
786 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
791 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
792 if (EFI_ERROR (Status
)) {
796 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
797 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
801 // Different formsets may have same varstore, so here just set the flag
802 // not exit the circle.
809 return EFI_NOT_FOUND
;
813 // GUID/Name is not specified, take the first storage in FormSet
815 if (mSystemLevelFormSet
== NULL
) {
816 return EFI_NOT_READY
;
820 // Generate <ConfigResp>
822 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
823 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
824 return EFI_UNSUPPORTED
;
827 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
829 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
830 if (EFI_ERROR (Status
)) {
836 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
837 *ResultsDataSize
= TotalSize
;
846 Callback function for SimpleTextInEx protocol install events
848 @param Event the event that is signaled.
849 @param Context not used here.
854 FormDisplayCallback (
859 if (mFormDisplay
!= NULL
) {
863 gBS
->LocateProtocol (
864 &gEdkiiFormDisplayEngineProtocolGuid
,
866 (VOID
**) &mFormDisplay
871 Initialize Setup Browser driver.
873 @param ImageHandle The image handle.
874 @param SystemTable The system table.
876 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
877 @return Other value if failed to initialize the Setup Browser module.
883 IN EFI_HANDLE ImageHandle
,
884 IN EFI_SYSTEM_TABLE
*SystemTable
891 // Locate required Hii relative protocols
893 Status
= gBS
->LocateProtocol (
894 &gEfiHiiDatabaseProtocolGuid
,
896 (VOID
**) &mHiiDatabase
898 ASSERT_EFI_ERROR (Status
);
900 Status
= gBS
->LocateProtocol (
901 &gEfiHiiConfigRoutingProtocolGuid
,
903 (VOID
**) &mHiiConfigRouting
905 ASSERT_EFI_ERROR (Status
);
907 Status
= gBS
->LocateProtocol (
908 &gEfiDevicePathFromTextProtocolGuid
,
910 (VOID
**) &mPathFromText
914 // Install FormBrowser2 protocol
916 mPrivateData
.Handle
= NULL
;
917 Status
= gBS
->InstallProtocolInterface (
918 &mPrivateData
.Handle
,
919 &gEfiFormBrowser2ProtocolGuid
,
920 EFI_NATIVE_INTERFACE
,
921 &mPrivateData
.FormBrowser2
923 ASSERT_EFI_ERROR (Status
);
926 // Install FormBrowserEx2 protocol
928 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
929 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
930 mPrivateData
.Handle
= NULL
;
931 Status
= gBS
->InstallProtocolInterface (
932 &mPrivateData
.Handle
,
933 &gEdkiiFormBrowserEx2ProtocolGuid
,
934 EFI_NATIVE_INTERFACE
,
935 &mPrivateData
.FormBrowserEx2
937 ASSERT_EFI_ERROR (Status
);
939 Status
= gBS
->InstallProtocolInterface (
940 &mPrivateData
.Handle
,
941 &gEdkiiFormBrowserExProtocolGuid
,
942 EFI_NATIVE_INTERFACE
,
943 &mPrivateData
.FormBrowserEx
945 ASSERT_EFI_ERROR (Status
);
947 InitializeDisplayFormData ();
949 Status
= gBS
->LocateProtocol (
950 &gEdkiiFormDisplayEngineProtocolGuid
,
952 (VOID
**) &mFormDisplay
955 if (EFI_ERROR (Status
)) {
956 EfiCreateProtocolNotifyEvent (
957 &gEdkiiFormDisplayEngineProtocolGuid
,
970 Create a new string in HII Package List.
972 @param String The String to be added
973 @param HiiHandle The package list in the HII database to insert the
976 @return The output string.
982 IN EFI_HII_HANDLE HiiHandle
985 EFI_STRING_ID StringId
;
987 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
988 ASSERT (StringId
!= 0);
995 Delete a string from HII Package List.
997 @param StringId Id of the string in HII database.
998 @param HiiHandle The HII package list handle.
1000 @retval EFI_SUCCESS The string was deleted successfully.
1005 IN EFI_STRING_ID StringId
,
1006 IN EFI_HII_HANDLE HiiHandle
1011 NullChar
= CHAR_NULL
;
1012 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1018 Get the string based on the StringId and HII Package List Handle.
1020 @param Token The String's ID.
1021 @param HiiHandle The package list in the HII database to search for
1022 the specified string.
1024 @return The output string.
1029 IN EFI_STRING_ID Token
,
1030 IN EFI_HII_HANDLE HiiHandle
1035 if (HiiHandle
== NULL
) {
1039 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1040 if (String
== NULL
) {
1041 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1042 ASSERT (String
!= NULL
);
1044 return (CHAR16
*) String
;
1049 Allocate new memory and then copy the Unicode string Source to Destination.
1051 @param Dest Location to copy string
1052 @param Src String to copy
1057 IN OUT CHAR16
**Dest
,
1061 if (*Dest
!= NULL
) {
1064 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1065 ASSERT (*Dest
!= NULL
);
1070 Allocate new memory and concatinate Source on the end of Destination.
1072 @param Dest String to added to the end of.
1073 @param Src String to concatinate.
1078 IN OUT CHAR16
**Dest
,
1085 if (*Dest
== NULL
) {
1086 NewStringCpy (Dest
, Src
);
1090 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1091 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1092 ASSERT (NewString
!= NULL
);
1094 StrCpyS (NewString
, MaxLen
, *Dest
);
1095 StrCatS (NewString
, MaxLen
, Src
);
1102 Get Value for given Name from a NameValue Storage.
1104 @param Storage The NameValue Storage.
1105 @param Name The Name.
1106 @param Value The retured Value.
1107 @param GetValueFrom Where to get source value, from EditValue or Value.
1109 @retval EFI_SUCCESS Value found for given Name.
1110 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1115 IN BROWSER_STORAGE
*Storage
,
1117 IN OUT CHAR16
**Value
,
1118 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1122 NAME_VALUE_NODE
*Node
;
1124 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1125 return EFI_INVALID_PARAMETER
;
1130 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1131 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1132 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1134 if (StrCmp (Name
, Node
->Name
) == 0) {
1135 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1136 NewStringCpy (Value
, Node
->EditValue
);
1138 NewStringCpy (Value
, Node
->Value
);
1143 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1146 return EFI_NOT_FOUND
;
1151 Set Value of given Name in a NameValue Storage.
1153 @param Storage The NameValue Storage.
1154 @param Name The Name.
1155 @param Value The Value to set.
1156 @param SetValueTo Whether update editValue or Value.
1157 @param ReturnNode The node use the input name.
1159 @retval EFI_SUCCESS Value found for given Name.
1160 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1165 IN BROWSER_STORAGE
*Storage
,
1168 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1169 OUT NAME_VALUE_NODE
**ReturnNode
1173 NAME_VALUE_NODE
*Node
;
1176 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1177 return EFI_INVALID_PARAMETER
;
1180 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1181 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1182 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1184 if (StrCmp (Name
, Node
->Name
) == 0) {
1185 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1186 Buffer
= Node
->EditValue
;
1188 Buffer
= Node
->Value
;
1190 if (Buffer
!= NULL
) {
1193 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1194 ASSERT (Buffer
!= NULL
);
1195 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1196 Node
->EditValue
= Buffer
;
1198 Node
->Value
= Buffer
;
1201 if (ReturnNode
!= NULL
) {
1208 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1211 return EFI_NOT_FOUND
;
1216 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1218 @param Storage The Storage to be conveted.
1219 @param ConfigResp The returned <ConfigResp>.
1220 @param ConfigRequest The ConfigRequest string.
1221 @param GetEditBuf Get the data from editbuffer or buffer.
1223 @retval EFI_SUCCESS Convert success.
1224 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1228 StorageToConfigResp (
1229 IN BROWSER_STORAGE
*Storage
,
1230 IN CHAR16
**ConfigResp
,
1231 IN CHAR16
*ConfigRequest
,
1232 IN BOOLEAN GetEditBuf
1236 EFI_STRING Progress
;
1238 NAME_VALUE_NODE
*Node
;
1240 FORMSET_STORAGE
*FormsetStorage
;
1242 Status
= EFI_SUCCESS
;
1244 switch (Storage
->Type
) {
1245 case EFI_HII_VARSTORE_BUFFER
:
1246 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1247 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1248 Status
= mHiiConfigRouting
->BlockToConfig (
1258 case EFI_HII_VARSTORE_NAME_VALUE
:
1260 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1261 ASSERT (FormsetStorage
!= NULL
);
1262 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1264 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1265 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1266 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1268 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1269 NewStringCat (ConfigResp
, L
"&");
1270 NewStringCat (ConfigResp
, Node
->Name
);
1271 NewStringCat (ConfigResp
, L
"=");
1273 NewStringCat (ConfigResp
, Node
->EditValue
);
1275 NewStringCat (ConfigResp
, Node
->Value
);
1278 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1282 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1284 Status
= EFI_INVALID_PARAMETER
;
1293 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1295 @param Storage The Storage to receive the settings.
1296 @param ConfigResp The <ConfigResp> to be converted.
1298 @retval EFI_SUCCESS Convert success.
1299 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1303 ConfigRespToStorage (
1304 IN BROWSER_STORAGE
*Storage
,
1305 IN CHAR16
*ConfigResp
1309 EFI_STRING Progress
;
1315 Status
= EFI_SUCCESS
;
1317 switch (Storage
->Type
) {
1318 case EFI_HII_VARSTORE_BUFFER
:
1319 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1320 BufferSize
= Storage
->Size
;
1321 Status
= mHiiConfigRouting
->ConfigToBlock (
1324 Storage
->EditBuffer
,
1330 case EFI_HII_VARSTORE_NAME_VALUE
:
1331 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1332 if (StrPtr
== NULL
) {
1335 StrPtr
= StrStr (ConfigResp
, L
"&");
1336 while (StrPtr
!= NULL
) {
1340 StrPtr
= StrPtr
+ 1;
1342 StrPtr
= StrStr (StrPtr
, L
"=");
1343 if (StrPtr
== NULL
) {
1351 StrPtr
= StrPtr
+ 1;
1353 StrPtr
= StrStr (StrPtr
, L
"&");
1354 if (StrPtr
!= NULL
) {
1357 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1361 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1363 Status
= EFI_INVALID_PARAMETER
;
1371 Convert the buffer value to HiiValue.
1373 @param Question The question.
1374 @param Value Unicode buffer save the question value.
1376 @retval Status whether convert the value success.
1381 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1386 BOOLEAN IsBufferStorage
;
1398 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1399 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1400 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1401 IsBufferStorage
= TRUE
;
1403 IsBufferStorage
= FALSE
;
1407 // Question Value is provided by Buffer Storage or NameValue Storage
1409 if (Question
->BufferValue
!= NULL
) {
1411 // This Question is password or orderedlist
1413 Dst
= Question
->BufferValue
;
1416 // Other type of Questions
1418 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1422 // Temp cut at the end of this section, end with '\0' or '&'.
1425 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1428 TempChar
= *StringPtr
;
1431 LengthStr
= StrLen (Value
);
1434 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1435 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1436 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1437 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1439 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1440 Length
= (UINTN
) Question
->StorageWidth
* 2;
1445 Status
= EFI_SUCCESS
;
1446 if (!IsBufferStorage
&& IsString
) {
1448 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1449 // Add string tail char L'\0' into Length
1451 DstBuf
= (CHAR16
*) Dst
;
1452 ZeroMem (TemStr
, sizeof (TemStr
));
1453 for (Index
= 0; Index
< Length
; Index
+= 4) {
1454 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1455 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1458 // Add tailing L'\0' character
1460 DstBuf
[Index
/4] = L
'\0';
1462 ZeroMem (TemStr
, sizeof (TemStr
));
1463 for (Index
= 0; Index
< Length
; Index
++) {
1464 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1465 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1466 if ((Index
& 1) == 0) {
1467 Dst
[Index
/2] = DigitUint8
;
1469 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1474 *StringPtr
= TempChar
;
1480 Get Question's current Value.
1482 @param FormSet FormSet data structure.
1483 @param Form Form data structure.
1484 @param Question Question to be initialized.
1485 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1487 @retval EFI_SUCCESS The function completed successfully.
1492 IN FORM_BROWSER_FORMSET
*FormSet
,
1493 IN FORM_BROWSER_FORM
*Form
,
1494 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1495 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1504 BROWSER_STORAGE
*Storage
;
1505 FORMSET_STORAGE
*FormsetStorage
;
1506 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1507 CHAR16
*ConfigRequest
;
1512 BOOLEAN IsBufferStorage
;
1515 Status
= EFI_SUCCESS
;
1519 if (GetValueFrom
>= GetSetValueWithMax
) {
1520 return EFI_INVALID_PARAMETER
;
1524 // Question value is provided by an Expression, evaluate it
1526 if (Question
->ValueExpression
!= NULL
) {
1527 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1528 if (!EFI_ERROR (Status
)) {
1529 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1530 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1531 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1532 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1533 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1535 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1536 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1538 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1540 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1541 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1547 // Get question value by read expression.
1549 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1550 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1551 if (!EFI_ERROR (Status
) &&
1552 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1554 // Only update question value to the valid result.
1556 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1557 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1558 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1559 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1560 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1562 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1563 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1565 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1567 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1568 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1574 // Question value is provided by RTC
1576 Storage
= Question
->Storage
;
1577 QuestionValue
= &Question
->HiiValue
.Value
;
1578 if (Storage
== NULL
) {
1580 // It's a Question without storage, or RTC date/time
1582 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1584 // Date and time define the same Flags bit
1586 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1587 case QF_DATE_STORAGE_TIME
:
1588 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1591 case QF_DATE_STORAGE_WAKEUP
:
1592 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1595 case QF_DATE_STORAGE_NORMAL
:
1598 // For date/time without storage
1603 if (EFI_ERROR (Status
)) {
1604 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1605 QuestionValue
->date
.Year
= 0xff;
1606 QuestionValue
->date
.Month
= 0xff;
1607 QuestionValue
->date
.Day
= 0xff;
1609 QuestionValue
->time
.Hour
= 0xff;
1610 QuestionValue
->time
.Minute
= 0xff;
1611 QuestionValue
->time
.Second
= 0xff;
1616 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1617 QuestionValue
->date
.Year
= EfiTime
.Year
;
1618 QuestionValue
->date
.Month
= EfiTime
.Month
;
1619 QuestionValue
->date
.Day
= EfiTime
.Day
;
1621 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1622 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1623 QuestionValue
->time
.Second
= EfiTime
.Second
;
1631 // Question value is provided by EFI variable
1633 StorageWidth
= Question
->StorageWidth
;
1634 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1635 if (Question
->BufferValue
!= NULL
) {
1636 Dst
= Question
->BufferValue
;
1638 Dst
= (UINT8
*) QuestionValue
;
1641 Status
= gRT
->GetVariable (
1642 Question
->VariableName
,
1649 // Always return success, even this EFI variable doesn't exist
1655 // Question Value is provided by Buffer Storage or NameValue Storage
1657 if (Question
->BufferValue
!= NULL
) {
1659 // This Question is password or orderedlist
1661 Dst
= Question
->BufferValue
;
1664 // Other type of Questions
1666 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1669 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1670 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1671 IsBufferStorage
= TRUE
;
1673 IsBufferStorage
= FALSE
;
1675 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1676 if (IsBufferStorage
) {
1677 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1679 // Copy from storage Edit buffer
1681 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1684 // Copy from storage Edit buffer
1686 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1690 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1691 if (EFI_ERROR (Status
)) {
1695 ASSERT (Value
!= NULL
);
1696 Status
= BufferToValue (Question
, Value
);
1700 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1701 ASSERT (FormsetStorage
!= NULL
);
1703 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1704 // <ConfigHdr> + "&" + <VariableName>
1706 if (IsBufferStorage
) {
1707 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1708 Length
+= StrLen (Question
->BlockName
);
1710 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1711 Length
+= StrLen (Question
->VariableName
) + 1;
1713 // Allocate buffer include '\0'
1714 MaxLen
= Length
+ 1;
1715 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1716 ASSERT (ConfigRequest
!= NULL
);
1718 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1719 if (IsBufferStorage
) {
1720 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1722 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1723 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1727 // Request current settings from Configuration Driver
1729 Status
= mHiiConfigRouting
->ExtractConfig (
1735 FreePool (ConfigRequest
);
1736 if (EFI_ERROR (Status
)) {
1741 // Skip <ConfigRequest>
1743 if (IsBufferStorage
) {
1744 Value
= StrStr (Result
, L
"&VALUE");
1745 if (Value
== NULL
) {
1747 return EFI_NOT_FOUND
;
1754 Value
= Result
+ Length
;
1756 if (*Value
!= '=') {
1758 return EFI_NOT_FOUND
;
1761 // Skip '=', point to value
1765 Status
= BufferToValue (Question
, Value
);
1766 if (EFI_ERROR (Status
)) {
1772 // Synchronize Edit Buffer
1774 if (IsBufferStorage
) {
1775 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1777 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1780 if (Result
!= NULL
) {
1790 Save Question Value to edit copy(cached) or Storage(uncached).
1792 @param FormSet FormSet data structure.
1793 @param Form Form data structure.
1794 @param Question Pointer to the Question.
1795 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1797 @retval EFI_SUCCESS The function completed successfully.
1802 IN FORM_BROWSER_FORMSET
*FormSet
,
1803 IN FORM_BROWSER_FORM
*Form
,
1804 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1805 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1815 BROWSER_STORAGE
*Storage
;
1816 FORMSET_STORAGE
*FormsetStorage
;
1817 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1822 BOOLEAN IsBufferStorage
;
1828 NAME_VALUE_NODE
*Node
;
1831 Status
= EFI_SUCCESS
;
1834 if (SetValueTo
>= GetSetValueWithMax
) {
1835 return EFI_INVALID_PARAMETER
;
1839 // If Question value is provided by an Expression, then it is read only
1841 if (Question
->ValueExpression
!= NULL
) {
1846 // Before set question value, evaluate its write expression.
1848 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1849 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1850 if (EFI_ERROR (Status
)) {
1856 // Question value is provided by RTC
1858 Storage
= Question
->Storage
;
1859 QuestionValue
= &Question
->HiiValue
.Value
;
1860 if (Storage
== NULL
) {
1862 // It's a Question without storage, or RTC date/time
1864 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1866 // Date and time define the same Flags bit
1868 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1869 case QF_DATE_STORAGE_TIME
:
1870 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1873 case QF_DATE_STORAGE_WAKEUP
:
1874 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1877 case QF_DATE_STORAGE_NORMAL
:
1880 // For date/time without storage
1885 if (EFI_ERROR (Status
)) {
1889 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1890 EfiTime
.Year
= QuestionValue
->date
.Year
;
1891 EfiTime
.Month
= QuestionValue
->date
.Month
;
1892 EfiTime
.Day
= QuestionValue
->date
.Day
;
1894 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1895 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1896 EfiTime
.Second
= QuestionValue
->time
.Second
;
1899 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1900 Status
= gRT
->SetTime (&EfiTime
);
1902 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1910 // Question value is provided by EFI variable
1912 StorageWidth
= Question
->StorageWidth
;
1913 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1914 if (Question
->BufferValue
!= NULL
) {
1915 Src
= Question
->BufferValue
;
1917 Src
= (UINT8
*) QuestionValue
;
1920 Status
= gRT
->SetVariable (
1921 Question
->VariableName
,
1923 Storage
->Attributes
,
1931 // Question Value is provided by Buffer Storage or NameValue Storage
1933 if (Question
->BufferValue
!= NULL
) {
1934 Src
= Question
->BufferValue
;
1936 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1939 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1940 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1941 IsBufferStorage
= TRUE
;
1943 IsBufferStorage
= FALSE
;
1945 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1947 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1948 if (IsBufferStorage
) {
1949 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1951 // Copy to storage edit buffer
1953 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1954 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1956 // Copy to storage edit buffer
1958 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1963 // Allocate enough string buffer.
1966 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1967 Value
= AllocateZeroPool (BufferLen
);
1968 ASSERT (Value
!= NULL
);
1970 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1972 TemName
= (CHAR16
*) Src
;
1974 for (; *TemName
!= L
'\0'; TemName
++) {
1975 UnicodeValueToStringS (
1977 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
1978 PREFIX_ZERO
| RADIX_HEX
,
1982 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
1985 BufferLen
= StorageWidth
* 2 + 1;
1986 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1987 ASSERT (Value
!= NULL
);
1989 // Convert Buffer to Hex String
1991 TemBuffer
= Src
+ StorageWidth
- 1;
1993 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1994 UnicodeValueToStringS (
1996 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
1997 PREFIX_ZERO
| RADIX_HEX
,
2001 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2005 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2007 if (EFI_ERROR (Status
)) {
2011 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2013 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2014 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2016 if (IsBufferStorage
) {
2017 Length
= StrLen (Question
->BlockName
) + 7;
2019 Length
= StrLen (Question
->VariableName
) + 2;
2021 if (!IsBufferStorage
&& IsString
) {
2022 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2024 Length
+= (StorageWidth
* 2);
2026 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2027 ASSERT (FormsetStorage
!= NULL
);
2028 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2029 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2030 ASSERT (ConfigResp
!= NULL
);
2032 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2033 if (IsBufferStorage
) {
2034 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2035 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2037 StrCatS (ConfigResp
, MaxLen
, L
"&");
2038 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2039 StrCatS (ConfigResp
, MaxLen
, L
"=");
2042 Value
= ConfigResp
+ StrLen (ConfigResp
);
2044 if (!IsBufferStorage
&& IsString
) {
2046 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2048 TemName
= (CHAR16
*) Src
;
2050 for (; *TemName
!= L
'\0'; TemName
++) {
2051 UnicodeValueToStringS (
2053 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2054 PREFIX_ZERO
| RADIX_HEX
,
2058 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2062 // Convert Buffer to Hex String
2064 TemBuffer
= Src
+ StorageWidth
- 1;
2066 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2067 UnicodeValueToStringS (
2069 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2070 PREFIX_ZERO
| RADIX_HEX
,
2074 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2079 // Convert to lower char.
2081 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2082 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2083 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2088 // Submit Question Value to Configuration Driver
2090 Status
= mHiiConfigRouting
->RouteConfig (
2095 if (EFI_ERROR (Status
)) {
2096 FreePool (ConfigResp
);
2099 FreePool (ConfigResp
);
2102 // Sync storage, from editbuffer to buffer.
2104 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2112 Perform nosubmitif check for a Form.
2114 @param FormSet FormSet data structure.
2115 @param Form Form data structure.
2116 @param Question The Question to be validated.
2117 @param Type Validation type: NoSubmit
2119 @retval EFI_SUCCESS Form validation pass.
2120 @retval other Form validation failed.
2125 IN FORM_BROWSER_FORMSET
*FormSet
,
2126 IN FORM_BROWSER_FORM
*Form
,
2127 IN FORM_BROWSER_STATEMENT
*Question
,
2133 LIST_ENTRY
*ListHead
;
2134 FORM_EXPRESSION
*Expression
;
2135 UINT32 BrowserStatus
;
2138 BrowserStatus
= BROWSER_SUCCESS
;
2142 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2143 ListHead
= &Question
->InconsistentListHead
;
2146 case EFI_HII_EXPRESSION_WARNING_IF
:
2147 ListHead
= &Question
->WarningListHead
;
2150 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2151 ListHead
= &Question
->NoSubmitListHead
;
2156 return EFI_UNSUPPORTED
;
2159 Link
= GetFirstNode (ListHead
);
2160 while (!IsNull (ListHead
, Link
)) {
2161 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2164 // Evaluate the expression
2166 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2167 if (EFI_ERROR (Status
)) {
2171 if (IsTrue (&Expression
->Result
)) {
2173 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2174 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2177 case EFI_HII_EXPRESSION_WARNING_IF
:
2178 BrowserStatus
= BROWSER_WARNING_IF
;
2181 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2182 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2184 // This code only used to compatible with old display engine,
2185 // New display engine will not use this field.
2187 if (Expression
->Error
!= 0) {
2188 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2197 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2199 // If in system submit process and for no_submit_if check, not popup this error message.
2200 // Will process this fail again later in not system submit process.
2202 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2205 if (ErrorStr
!= NULL
) {
2206 FreePool (ErrorStr
);
2209 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2212 return EFI_NOT_READY
;
2216 Link
= GetNextNode (ListHead
, Link
);
2223 Perform question check.
2225 If one question has more than one check, process form high priority to low.
2226 Only one error info will be popup.
2228 @param FormSet FormSet data structure.
2229 @param Form Form data structure.
2230 @param Question The Question to be validated.
2232 @retval EFI_SUCCESS Form validation pass.
2233 @retval other Form validation failed.
2237 ValueChangedValidation (
2238 IN FORM_BROWSER_FORMSET
*FormSet
,
2239 IN FORM_BROWSER_FORM
*Form
,
2240 IN FORM_BROWSER_STATEMENT
*Question
2245 Status
= EFI_SUCCESS
;
2248 // Do the inconsistentif check.
2250 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2251 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2252 if (EFI_ERROR (Status
)) {
2258 // Do the warningif check.
2260 if (!IsListEmpty (&Question
->WarningListHead
)) {
2261 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2268 Perform NoSubmit check for each Form in FormSet.
2270 @param FormSet FormSet data structure.
2271 @param CurrentForm Current input form data structure.
2272 @param Statement The statement for this check.
2274 @retval EFI_SUCCESS Form validation pass.
2275 @retval other Form validation failed.
2280 IN FORM_BROWSER_FORMSET
*FormSet
,
2281 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2282 OUT FORM_BROWSER_STATEMENT
**Statement
2287 FORM_BROWSER_STATEMENT
*Question
;
2288 FORM_BROWSER_FORM
*Form
;
2289 LIST_ENTRY
*LinkForm
;
2291 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2292 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2293 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2294 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2296 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2300 Link
= GetFirstNode (&Form
->StatementListHead
);
2301 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2302 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2303 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2304 if (EFI_ERROR (Status
)) {
2305 if (*CurrentForm
== NULL
) {
2306 *CurrentForm
= Form
;
2308 if (Statement
!= NULL
) {
2309 *Statement
= Question
;
2314 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2322 Fill storage's edit copy with settings requested from Configuration Driver.
2324 @param Storage The storage which need to sync.
2325 @param ConfigRequest The config request string which used to sync storage.
2326 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2327 editbuffer to buffer
2328 if TRUE, copy the editbuffer to the buffer.
2329 if FALSE, copy the buffer to the editbuffer.
2331 @retval EFI_SUCCESS The function completed successfully.
2335 SynchronizeStorage (
2336 OUT BROWSER_STORAGE
*Storage
,
2337 IN CHAR16
*ConfigRequest
,
2338 IN BOOLEAN SyncOrRestore
2342 EFI_STRING Progress
;
2346 NAME_VALUE_NODE
*Node
;
2350 Status
= EFI_SUCCESS
;
2353 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2354 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2355 BufferSize
= Storage
->Size
;
2357 if (SyncOrRestore
) {
2358 Src
= Storage
->EditBuffer
;
2359 Dst
= Storage
->Buffer
;
2361 Src
= Storage
->Buffer
;
2362 Dst
= Storage
->EditBuffer
;
2365 if (ConfigRequest
!= NULL
) {
2366 Status
= mHiiConfigRouting
->BlockToConfig(
2374 if (EFI_ERROR (Status
)) {
2378 Status
= mHiiConfigRouting
->ConfigToBlock (
2385 if (Result
!= NULL
) {
2389 CopyMem (Dst
, Src
, BufferSize
);
2391 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2392 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2393 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2394 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2396 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2397 (ConfigRequest
== NULL
)) {
2398 if (SyncOrRestore
) {
2399 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2401 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2405 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2413 When discard the question value, call the callback function with Changed type
2414 to inform the hii driver.
2416 @param FormSet FormSet data structure.
2417 @param Form Form data structure.
2421 SendDiscardInfoToDriver (
2422 IN FORM_BROWSER_FORMSET
*FormSet
,
2423 IN FORM_BROWSER_FORM
*Form
2427 FORM_BROWSER_STATEMENT
*Question
;
2428 EFI_IFR_TYPE_VALUE
*TypeValue
;
2429 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2431 if (FormSet
->ConfigAccess
== NULL
) {
2435 Link
= GetFirstNode (&Form
->StatementListHead
);
2436 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2437 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2438 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2440 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2444 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2448 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2452 if (!Question
->ValueChanged
) {
2457 // Restore the question value before call the CHANGED callback type.
2459 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2461 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2462 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2465 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2466 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2468 TypeValue
= &Question
->HiiValue
.Value
;
2471 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2472 FormSet
->ConfigAccess
->Callback (
2473 FormSet
->ConfigAccess
,
2474 EFI_BROWSER_ACTION_CHANGED
,
2475 Question
->QuestionId
,
2476 Question
->HiiValue
.Type
,
2484 When submit the question value, call the callback function with Submitted type
2485 to inform the hii driver.
2487 @param FormSet FormSet data structure.
2488 @param Form Form data structure.
2492 SubmitCallbackForForm (
2493 IN FORM_BROWSER_FORMSET
*FormSet
,
2494 IN FORM_BROWSER_FORM
*Form
2498 FORM_BROWSER_STATEMENT
*Question
;
2499 EFI_IFR_TYPE_VALUE
*TypeValue
;
2500 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2502 if (FormSet
->ConfigAccess
== NULL
) {
2506 Link
= GetFirstNode (&Form
->StatementListHead
);
2507 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2508 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2509 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2511 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2515 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2519 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2523 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2524 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2526 TypeValue
= &Question
->HiiValue
.Value
;
2529 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2530 FormSet
->ConfigAccess
->Callback (
2531 FormSet
->ConfigAccess
,
2532 EFI_BROWSER_ACTION_SUBMITTED
,
2533 Question
->QuestionId
,
2534 Question
->HiiValue
.Type
,
2542 When value set Success, call the submit callback function.
2544 @param FormSet FormSet data structure.
2545 @param Form Form data structure.
2550 IN FORM_BROWSER_FORMSET
*FormSet
,
2551 IN FORM_BROWSER_FORM
*Form
2554 FORM_BROWSER_FORM
*CurrentForm
;
2558 SubmitCallbackForForm(FormSet
, Form
);
2562 Link
= GetFirstNode (&FormSet
->FormListHead
);
2563 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2564 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2565 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2567 SubmitCallbackForForm(FormSet
, CurrentForm
);
2572 Validate the HiiHandle.
2574 @param HiiHandle The input HiiHandle which need to validate.
2576 @retval TRUE The handle is validate.
2577 @retval FALSE The handle is invalidate.
2582 EFI_HII_HANDLE HiiHandle
2585 EFI_HII_HANDLE
*HiiHandles
;
2589 if (HiiHandle
== NULL
) {
2595 HiiHandles
= HiiGetHiiHandles (NULL
);
2596 ASSERT (HiiHandles
!= NULL
);
2598 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2599 if (HiiHandles
[Index
] == HiiHandle
) {
2605 FreePool (HiiHandles
);
2611 Validate the FormSet. If the formset is not validate, remove it from the list.
2613 @param FormSet The input FormSet which need to validate.
2615 @retval TRUE The handle is validate.
2616 @retval FALSE The handle is invalidate.
2621 FORM_BROWSER_FORMSET
*FormSet
2626 ASSERT (FormSet
!= NULL
);
2628 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2630 // Should not remove the formset which is being used.
2632 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2633 CleanBrowserStorage(FormSet
);
2634 RemoveEntryList (&FormSet
->Link
);
2635 DestroyFormSet (FormSet
);
2641 Check whether need to enable the reset flag in form level.
2642 Also clean all ValueChanged flag in question.
2644 @param SetFlag Whether need to set the Reset Flag.
2645 @param FormSet FormSet data structure.
2646 @param Form Form data structure.
2652 IN FORM_BROWSER_FORMSET
*FormSet
,
2653 IN FORM_BROWSER_FORM
*Form
2657 FORM_BROWSER_STATEMENT
*Question
;
2660 Link
= GetFirstNode (&Form
->StatementListHead
);
2661 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2662 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2663 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2665 if (!Question
->ValueChanged
) {
2669 OldValue
= Question
->ValueChanged
;
2672 // Compare the buffer and editbuffer data to see whether the data has been saved.
2674 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2677 // Only the changed data has been saved, then need to set the reset flag.
2679 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2680 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2681 gResetRequired
= TRUE
;
2684 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2685 gFlagReconnect
= TRUE
;
2692 Check whether need to enable the reset flag.
2693 Also clean ValueChanged flag for all statements.
2695 Form level or formset level, only one.
2697 @param SetFlag Whether need to set the Reset Flag.
2698 @param FormSet FormSet data structure.
2699 @param Form Form data structure.
2703 ValueChangeResetFlagUpdate (
2705 IN FORM_BROWSER_FORMSET
*FormSet
,
2706 IN FORM_BROWSER_FORM
*Form
2709 FORM_BROWSER_FORM
*CurrentForm
;
2713 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2717 Link
= GetFirstNode (&FormSet
->FormListHead
);
2718 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2719 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2720 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2722 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2727 Base on the return Progress string to find the form.
2729 Base on the first return Offset/Width (Name) string to find the form
2730 which keep this string.
2732 @param FormSet FormSet data structure.
2733 @param Storage Storage which has this Progress string.
2734 @param Progress The Progress string which has the first fail string.
2735 @param RetForm The return form for this progress string.
2736 @param RetQuestion The return question for the error progress string.
2738 @retval TRUE Find the error form and statement for this error progress string.
2739 @retval FALSE Not find the error form.
2743 FindQuestionFromProgress (
2744 IN FORM_BROWSER_FORMSET
*FormSet
,
2745 IN BROWSER_STORAGE
*Storage
,
2746 IN EFI_STRING Progress
,
2747 OUT FORM_BROWSER_FORM
**RetForm
,
2748 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2752 LIST_ENTRY
*LinkStorage
;
2753 LIST_ENTRY
*LinkStatement
;
2754 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2755 FORM_BROWSER_FORM
*Form
;
2757 FORM_BROWSER_STATEMENT
*Statement
;
2759 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2763 *RetQuestion
= NULL
;
2766 // Skip the first "&" or the ConfigHdr part.
2768 if (*Progress
== '&') {
2772 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2774 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2776 // For Name/Value type, Skip the ConfigHdr part.
2778 EndStr
= StrStr (Progress
, L
"PATH=");
2779 ASSERT (EndStr
!= NULL
);
2780 while (*EndStr
!= '&') {
2787 // For Buffer type, Skip the ConfigHdr part.
2789 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2790 ASSERT (EndStr
!= NULL
);
2794 Progress
= EndStr
+ 1;
2798 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2800 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2802 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2803 // here, just keep the "Fred" string.
2805 EndStr
= StrStr (Progress
, L
"=");
2806 ASSERT (EndStr
!= NULL
);
2810 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2811 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2813 EndStr
= StrStr (Progress
, L
"&VALUE=");
2814 ASSERT (EndStr
!= NULL
);
2819 // Search in the form list.
2821 Link
= GetFirstNode (&FormSet
->FormListHead
);
2822 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2823 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2824 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2827 // Search in the ConfigReqeust list in this form.
2829 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2830 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2831 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2832 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2834 if (Storage
!= ConfigInfo
->Storage
) {
2838 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2840 // Find the OffsetWidth string in this form.
2847 if (*RetForm
!= NULL
) {
2848 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2849 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2850 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2851 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2853 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2854 *RetQuestion
= Statement
;
2858 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2859 *RetQuestion
= Statement
;
2865 if (*RetForm
!= NULL
) {
2871 // restore the OffsetWidth string to the original format.
2873 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2879 return (BOOLEAN
) (*RetForm
!= NULL
);
2883 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2884 for form and formset.
2886 @param Storage Storage which has this Progress string.
2887 @param ConfigRequest The ConfigRequest string.
2888 @param Progress The Progress string which has the first fail string.
2889 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2890 @param SyncConfigRequest Return the SyncConfigRequest string.
2894 GetSyncRestoreConfigRequest(
2895 IN BROWSER_STORAGE
*Storage
,
2896 IN EFI_STRING ConfigRequest
,
2897 IN EFI_STRING Progress
,
2898 OUT EFI_STRING
*RestoreConfigRequest
,
2899 OUT EFI_STRING
*SyncConfigRequest
2903 EFI_STRING ConfigHdrEndStr
;
2904 EFI_STRING ElementStr
;
2906 UINTN RestoreEleSize
;
2909 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
2911 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
2912 // Need to restore all the fields in the ConfigRequest.
2914 if (*Progress
== L
'G') {
2915 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2916 ASSERT (*RestoreConfigRequest
!= NULL
);
2921 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2923 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2925 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2926 // here, just keep the "Fred" string.
2928 EndStr
= StrStr (Progress
, L
"=");
2929 ASSERT (EndStr
!= NULL
);
2932 // Find the ConfigHdr in ConfigRequest.
2934 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
2935 ASSERT (ConfigHdrEndStr
!= NULL
);
2936 while (*ConfigHdrEndStr
!= L
'&') {
2941 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2942 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2944 EndStr
= StrStr (Progress
, L
"&VALUE=");
2945 ASSERT (EndStr
!= NULL
);
2948 // Find the ConfigHdr in ConfigRequest.
2950 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
2953 // Find the first fail pair in the ConfigRequest.
2955 ElementStr
= StrStr (ConfigRequest
, Progress
);
2956 ASSERT (ElementStr
!= NULL
);
2958 // To get the RestoreConfigRequest.
2960 RestoreEleSize
= StrSize (ElementStr
);
2961 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
2962 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
2963 ASSERT (*RestoreConfigRequest
!= NULL
);
2964 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
2965 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
2967 // To get the SyncConfigRequest.
2969 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
2970 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
2971 ASSERT (*SyncConfigRequest
!= NULL
);
2972 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
2975 // restore the Progress string to the original format.
2977 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2985 Popup an save error info and get user input.
2987 @param TitleId The form title id.
2988 @param HiiHandle The hii handle for this package.
2990 @retval UINT32 The user select option for the save fail.
2991 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2995 IN EFI_STRING_ID TitleId
,
2996 IN EFI_HII_HANDLE HiiHandle
3000 CHAR16
*StringBuffer
;
3003 FormTitle
= GetToken (TitleId
, HiiHandle
);
3005 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3006 ASSERT (StringBuffer
!= NULL
);
3010 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3011 L
"Submit Fail For Form: %s.",
3015 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3017 FreePool (StringBuffer
);
3018 FreePool (FormTitle
);
3024 Popup an NO_SUBMIT_IF error info and get user input.
3026 @param TitleId The form title id.
3027 @param HiiHandle The hii handle for this package.
3029 @retval UINT32 The user select option for the save fail.
3030 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3033 ConfirmNoSubmitFail (
3034 IN EFI_STRING_ID TitleId
,
3035 IN EFI_HII_HANDLE HiiHandle
3039 CHAR16
*StringBuffer
;
3042 FormTitle
= GetToken (TitleId
, HiiHandle
);
3044 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3045 ASSERT (StringBuffer
!= NULL
);
3049 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3050 L
"NO_SUBMIT_IF error For Form: %s.",
3054 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3056 FreePool (StringBuffer
);
3057 FreePool (FormTitle
);
3063 Discard data based on the input setting scope (Form, FormSet or System).
3065 @param FormSet FormSet data structure.
3066 @param Form Form data structure.
3067 @param SettingScope Setting Scope for Discard action.
3069 @retval EFI_SUCCESS The function completed successfully.
3070 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3075 IN FORM_BROWSER_FORMSET
*FormSet
,
3076 IN FORM_BROWSER_FORM
*Form
,
3077 IN BROWSER_SETTING_SCOPE SettingScope
3081 FORMSET_STORAGE
*Storage
;
3082 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3083 FORM_BROWSER_FORMSET
*LocalFormSet
;
3084 FORM_BROWSER_FORMSET
*OldFormSet
;
3087 // Check the supported setting level.
3089 if (SettingScope
>= MaxLevel
) {
3090 return EFI_UNSUPPORTED
;
3093 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3095 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3096 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3097 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3098 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3100 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3105 // Skip if there is no RequestElement
3107 if (ConfigInfo
->ElementCount
== 0) {
3112 // Prepare <ConfigResp>
3114 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3117 // Call callback with Changed type to inform the driver.
3119 SendDiscardInfoToDriver (FormSet
, Form
);
3122 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3123 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3126 // Discard Buffer storage or Name/Value storage
3128 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3129 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3130 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3131 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3133 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3138 // Skip if there is no RequestElement
3140 if (Storage
->ElementCount
== 0) {
3144 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3147 Link
= GetFirstNode (&FormSet
->FormListHead
);
3148 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3149 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3150 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3153 // Call callback with Changed type to inform the driver.
3155 SendDiscardInfoToDriver (FormSet
, Form
);
3158 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3159 } else if (SettingScope
== SystemLevel
) {
3161 // System Level Discard.
3163 OldFormSet
= mSystemLevelFormSet
;
3166 // Discard changed value for each FormSet in the maintain list.
3168 Link
= GetFirstNode (&gBrowserFormSetList
);
3169 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3170 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3171 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3172 if (!ValidateFormSet(LocalFormSet
)) {
3176 mSystemLevelFormSet
= LocalFormSet
;
3178 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3179 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3181 // Remove maintain backup list after discard except for the current using FormSet.
3183 CleanBrowserStorage(LocalFormSet
);
3184 RemoveEntryList (&LocalFormSet
->Link
);
3185 DestroyFormSet (LocalFormSet
);
3189 mSystemLevelFormSet
= OldFormSet
;
3196 Submit data for a form.
3198 @param FormSet FormSet data structure.
3199 @param Form Form data structure.
3201 @retval EFI_SUCCESS The function completed successfully.
3202 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3207 IN FORM_BROWSER_FORMSET
*FormSet
,
3208 IN FORM_BROWSER_FORM
*Form
3213 EFI_STRING ConfigResp
;
3214 EFI_STRING Progress
;
3215 BROWSER_STORAGE
*Storage
;
3216 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3217 BOOLEAN SubmitFormFail
;
3219 SubmitFormFail
= FALSE
;
3221 if (!IsNvUpdateRequiredForForm (Form
)) {
3225 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3226 if (EFI_ERROR (Status
)) {
3230 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3231 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3232 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3233 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3235 Storage
= ConfigInfo
->Storage
;
3236 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3241 // Skip if there is no RequestElement
3243 if (ConfigInfo
->ElementCount
== 0) {
3248 // 1. Prepare <ConfigResp>
3250 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3251 if (EFI_ERROR (Status
)) {
3256 // 2. Set value to hii config routine protocol.
3258 Status
= mHiiConfigRouting
->RouteConfig (
3264 if (EFI_ERROR (Status
)) {
3266 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3268 SubmitFormFail
= TRUE
;
3269 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3270 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3271 FreePool (ConfigResp
);
3275 FreePool (ConfigResp
);
3277 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3279 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3283 // 4. Process the save failed storage.
3285 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3286 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3287 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3288 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3289 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3290 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3292 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3293 // base on the SyncConfigRequest to Sync the buffer.
3295 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3296 FreePool (ConfigInfo
->RestoreConfigRequest
);
3297 ConfigInfo
->RestoreConfigRequest
= NULL
;
3298 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3299 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3300 FreePool (ConfigInfo
->SyncConfigRequest
);
3301 ConfigInfo
->SyncConfigRequest
= NULL
;
3304 Status
= EFI_SUCCESS
;
3306 SendDiscardInfoToDriver (FormSet
,Form
);
3308 Status
= EFI_UNSUPPORTED
;
3312 // Free Form save fail list.
3314 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3315 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3316 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3317 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3322 // 5. Update the NV flag.
3324 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3327 // 6 Call callback with Submitted type to inform the driver.
3329 if (!SubmitFormFail
) {
3330 SubmitCallback (FormSet
, Form
);
3337 Submit data for a formset.
3339 @param FormSet FormSet data structure.
3340 @param SkipProcessFail Whether skip to process the save failed storage.
3341 If submit formset is called when do system level save,
3342 set this value to true and process the failed formset
3344 if submit formset is called when do formset level save,
3345 set the value to false and process the failed storage
3346 right after process all storages for this formset.
3348 @retval EFI_SUCCESS The function completed successfully.
3349 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3354 IN FORM_BROWSER_FORMSET
*FormSet
,
3355 IN BOOLEAN SkipProcessFail
3360 EFI_STRING ConfigResp
;
3361 EFI_STRING Progress
;
3362 BROWSER_STORAGE
*Storage
;
3363 FORMSET_STORAGE
*FormSetStorage
;
3364 FORM_BROWSER_FORM
*Form
;
3365 BOOLEAN HasInserted
;
3366 FORM_BROWSER_STATEMENT
*Question
;
3367 BOOLEAN SubmitFormSetFail
;
3368 BOOLEAN DiscardChange
;
3370 HasInserted
= FALSE
;
3371 SubmitFormSetFail
= FALSE
;
3372 DiscardChange
= FALSE
;
3374 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3379 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3380 if (EFI_ERROR (Status
)) {
3381 if (SkipProcessFail
) {
3383 // Process NO_SUBMIT check first, so insert it at head.
3385 FormSet
->SaveFailForm
= Form
;
3386 FormSet
->SaveFailStatement
= Question
;
3387 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3396 // Submit Buffer storage or Name/Value storage
3398 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3399 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3400 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3401 Storage
= FormSetStorage
->BrowserStorage
;
3402 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3404 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3409 // Skip if there is no RequestElement
3411 if (FormSetStorage
->ElementCount
== 0) {
3416 // 1. Prepare <ConfigResp>
3418 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3419 if (EFI_ERROR (Status
)) {
3424 // 2. Send <ConfigResp> to Routine config Protocol.
3426 Status
= mHiiConfigRouting
->RouteConfig (
3431 if (EFI_ERROR (Status
)) {
3433 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3435 SubmitFormSetFail
= TRUE
;
3436 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3437 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3440 // Call submit formset for system level, save the formset info
3441 // and process later.
3443 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3444 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3445 FormSet
->SaveFailForm
= Form
;
3446 FormSet
->SaveFailStatement
= Question
;
3447 if (SkipProcessFail
) {
3448 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3453 FreePool (ConfigResp
);
3457 FreePool (ConfigResp
);
3459 // 3. Config success, update storage shadow Buffer
3461 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3465 // 4. Has save fail storage need to handle.
3468 if (!SkipProcessFail
) {
3470 // If not in system level, just handl the save failed storage here.
3472 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3473 DiscardChange
= TRUE
;
3474 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3475 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3476 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3477 Storage
= FormSetStorage
->BrowserStorage
;
3478 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3480 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3481 // base on the SyncConfigRequest to Sync the buffer.
3483 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3484 FreePool (FormSetStorage
->RestoreConfigRequest
);
3485 FormSetStorage
->RestoreConfigRequest
= NULL
;
3486 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3487 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3488 FreePool (FormSetStorage
->SyncConfigRequest
);
3489 FormSetStorage
->SyncConfigRequest
= NULL
;
3492 Status
= EFI_SUCCESS
;
3495 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3497 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3498 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3499 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3500 gCurrentSelection
->FormId
= Form
->FormId
;
3501 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3503 Status
= EFI_UNSUPPORTED
;
3507 // Free FormSet save fail list.
3509 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3510 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3511 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3512 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3516 // If in system level, just return error and handle the failed formset later.
3518 Status
= EFI_UNSUPPORTED
;
3523 // If user discard the change, send the discard info to driver.
3525 if (DiscardChange
) {
3526 Link
= GetFirstNode (&FormSet
->FormListHead
);
3527 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3528 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3529 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3531 // Call callback with Changed type to inform the driver.
3533 SendDiscardInfoToDriver (FormSet
, Form
);
3538 // 5. Update the NV flag.
3540 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3543 // 6. Call callback with Submitted type to inform the driver.
3545 if (!SubmitFormSetFail
) {
3546 SubmitCallback (FormSet
, NULL
);
3553 Submit data for all formsets.
3555 @retval EFI_SUCCESS The function completed successfully.
3556 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3566 LIST_ENTRY
*FormLink
;
3567 LIST_ENTRY
*StorageLink
;
3568 FORMSET_STORAGE
*FormSetStorage
;
3569 FORM_BROWSER_FORM
*Form
;
3570 FORM_BROWSER_FORMSET
*LocalFormSet
;
3571 UINT32 UserSelection
;
3572 FORM_BROWSER_STATEMENT
*Question
;
3574 mSystemSubmit
= TRUE
;
3575 Link
= GetFirstNode (&gBrowserFormSetList
);
3576 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3577 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3578 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3579 if (!ValidateFormSet(LocalFormSet
)) {
3583 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3584 if (EFI_ERROR (Status
)) {
3589 // Remove maintain backup list after save except for the current using FormSet.
3591 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3592 CleanBrowserStorage(LocalFormSet
);
3593 RemoveEntryList (&LocalFormSet
->Link
);
3594 DestroyFormSet (LocalFormSet
);
3597 mSystemSubmit
= FALSE
;
3599 Status
= EFI_SUCCESS
;
3602 // Process the save failed formsets.
3604 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3605 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3606 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3607 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3609 if (!ValidateFormSet(LocalFormSet
)) {
3613 Form
= LocalFormSet
->SaveFailForm
;
3614 Question
= LocalFormSet
->SaveFailStatement
;
3617 // Confirm with user, get user input.
3619 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3621 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3623 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3625 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3628 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3629 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3630 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3631 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3632 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3633 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3635 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3638 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3639 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3640 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3641 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3643 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3644 // base on the SyncConfigRequest to Sync the buffer.
3646 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3647 FreePool (FormSetStorage
->RestoreConfigRequest
);
3648 FormSetStorage
->RestoreConfigRequest
= NULL
;
3649 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3650 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3651 FreePool (FormSetStorage
->SyncConfigRequest
);
3652 FormSetStorage
->SyncConfigRequest
= NULL
;
3657 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3658 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3659 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3660 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3662 // Call callback with Changed type to inform the driver.
3664 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3667 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3668 CleanBrowserStorage(LocalFormSet
);
3669 RemoveEntryList (&LocalFormSet
->Link
);
3670 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3671 DestroyFormSet (LocalFormSet
);
3673 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3676 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3677 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3680 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3682 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3683 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3684 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3685 gCurrentSelection
->FormId
= Form
->FormId
;
3686 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3688 Status
= EFI_UNSUPPORTED
;
3694 // Clean the list which will not process.
3696 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3697 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3698 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3699 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3701 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3702 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3703 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3704 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3712 Submit data based on the input Setting level (Form, FormSet or System).
3714 @param FormSet FormSet data structure.
3715 @param Form Form data structure.
3716 @param SettingScope Setting Scope for Submit action.
3718 @retval EFI_SUCCESS The function completed successfully.
3719 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3724 IN FORM_BROWSER_FORMSET
*FormSet
,
3725 IN FORM_BROWSER_FORM
*Form
,
3726 IN BROWSER_SETTING_SCOPE SettingScope
3731 switch (SettingScope
) {
3733 Status
= SubmitForForm(FormSet
, Form
);
3737 Status
= SubmitForFormSet (FormSet
, FALSE
);
3741 Status
= SubmitForSystem ();
3745 Status
= EFI_UNSUPPORTED
;
3753 Converts the unicode character of the string from uppercase to lowercase.
3754 This is a internal function.
3756 @param ConfigString String to be converted
3762 IN EFI_STRING ConfigString
3768 ASSERT (ConfigString
!= NULL
);
3771 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3773 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3774 if (*String
== L
'=') {
3776 } else if (*String
== L
'&') {
3778 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3779 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3785 Find the point in the ConfigResp string for this question.
3787 @param Question The question.
3788 @param ConfigResp Get ConfigResp string.
3790 @retval point to the offset where is for this question.
3794 GetOffsetFromConfigResp (
3795 IN FORM_BROWSER_STATEMENT
*Question
,
3796 IN CHAR16
*ConfigResp
3799 CHAR16
*RequestElement
;
3803 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3805 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3806 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3807 if (RequestElement
!= NULL
) {
3809 // Skip the "VariableName=" field.
3811 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3814 return RequestElement
;
3818 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3822 // Convert all hex digits in ConfigResp to lower case before searching.
3824 HiiToLower (ConfigResp
);
3827 // 1. Directly use Question->BlockName to find.
3829 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3830 if (RequestElement
!= NULL
) {
3832 // Skip the "Question->BlockName&VALUE=" field.
3834 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3835 return RequestElement
;
3839 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3841 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3842 ASSERT (BlockData
!= NULL
);
3843 HiiToLower (BlockData
);
3844 RequestElement
= StrStr (ConfigResp
, BlockData
);
3845 FreePool (BlockData
);
3847 if (RequestElement
!= NULL
) {
3849 // Skip the "Question->BlockName&VALUE=" field.
3851 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3854 return RequestElement
;
3858 Get Question default value from AltCfg string.
3860 @param FormSet The form set.
3861 @param Form The form
3862 @param Question The question.
3864 @retval EFI_SUCCESS Question is reset to default value.
3868 GetDefaultValueFromAltCfg (
3869 IN FORM_BROWSER_FORMSET
*FormSet
,
3870 IN FORM_BROWSER_FORM
*Form
,
3871 IN OUT FORM_BROWSER_STATEMENT
*Question
3874 BROWSER_STORAGE
*Storage
;
3875 FORMSET_STORAGE
*FormSetStorage
;
3879 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3881 Storage
= Question
->Storage
;
3882 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3883 return EFI_NOT_FOUND
;
3887 // Try to get AltCfg string from form. If not found it, then
3888 // try to get it from formset.
3891 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3892 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3893 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3894 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3896 if (Storage
== ConfigInfo
->Storage
) {
3897 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3902 if (ConfigResp
== NULL
) {
3903 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3904 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3905 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3906 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3908 if (Storage
== FormSetStorage
->BrowserStorage
) {
3909 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3915 if (ConfigResp
== NULL
) {
3916 return EFI_NOT_FOUND
;
3919 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3920 if (Value
== NULL
) {
3921 return EFI_NOT_FOUND
;
3924 return BufferToValue (Question
, Value
);
3928 Get default Id value used for browser.
3930 @param DefaultId The default id value used by hii.
3932 @retval Browser used default value.
3936 GetDefaultIdForCallBack (
3940 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3941 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3942 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3943 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3944 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3945 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3946 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3947 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3948 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3949 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3950 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3951 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3960 Return data element in an Array by its Index.
3962 @param Array The data array.
3963 @param Type Type of the data in this array.
3964 @param Index Zero based index for data in this array.
3966 @retval Value The data to be returned
3978 ASSERT (Array
!= NULL
);
3982 case EFI_IFR_TYPE_NUM_SIZE_8
:
3983 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3986 case EFI_IFR_TYPE_NUM_SIZE_16
:
3987 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3990 case EFI_IFR_TYPE_NUM_SIZE_32
:
3991 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3994 case EFI_IFR_TYPE_NUM_SIZE_64
:
3995 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4007 Set value of a data element in an Array by its Index.
4009 @param Array The data array.
4010 @param Type Type of the data in this array.
4011 @param Index Zero based index for data in this array.
4012 @param Value The value to be set.
4024 ASSERT (Array
!= NULL
);
4027 case EFI_IFR_TYPE_NUM_SIZE_8
:
4028 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4031 case EFI_IFR_TYPE_NUM_SIZE_16
:
4032 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4035 case EFI_IFR_TYPE_NUM_SIZE_32
:
4036 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4039 case EFI_IFR_TYPE_NUM_SIZE_64
:
4040 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4049 Search an Option of a Question by its value.
4051 @param Question The Question
4052 @param OptionValue Value for Option to be searched.
4054 @retval Pointer Pointer to the found Option.
4055 @retval NULL Option not found.
4060 IN FORM_BROWSER_STATEMENT
*Question
,
4061 IN EFI_HII_VALUE
*OptionValue
4065 QUESTION_OPTION
*Option
;
4068 Link
= GetFirstNode (&Question
->OptionListHead
);
4069 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4070 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4072 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4074 // Check the suppressif condition, only a valid option can be return.
4076 if ((Option
->SuppressExpression
== NULL
) ||
4077 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4082 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4090 Reset Question to its default value.
4092 @param FormSet The form set.
4093 @param Form The form.
4094 @param Question The question.
4095 @param DefaultId The Class of the default.
4097 @retval EFI_SUCCESS Question is reset to default value.
4101 GetQuestionDefault (
4102 IN FORM_BROWSER_FORMSET
*FormSet
,
4103 IN FORM_BROWSER_FORM
*Form
,
4104 IN FORM_BROWSER_STATEMENT
*Question
,
4110 QUESTION_DEFAULT
*Default
;
4111 QUESTION_OPTION
*Option
;
4112 EFI_HII_VALUE
*HiiValue
;
4114 EFI_STRING StrValue
;
4115 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4116 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4119 EFI_IFR_TYPE_VALUE
*TypeValue
;
4120 UINT16 OriginalDefaultId
;
4121 FORMSET_DEFAULTSTORE
*DefaultStore
;
4122 LIST_ENTRY
*DefaultLink
;
4124 Status
= EFI_NOT_FOUND
;
4126 OriginalDefaultId
= DefaultId
;
4127 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4130 // Statement don't have storage, skip them
4132 if (Question
->QuestionId
== 0) {
4137 // There are Five ways to specify default value for a Question:
4138 // 1, use call back function (highest priority)
4139 // 2, use ExtractConfig function
4140 // 3, use nested EFI_IFR_DEFAULT
4141 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4142 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4145 HiiValue
= &Question
->HiiValue
;
4146 TypeValue
= &HiiValue
->Value
;
4147 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4149 // For orderedlist, need to pass the BufferValue to Callback function.
4151 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4155 // Get Question defaut value from call back function.
4157 ConfigAccess
= FormSet
->ConfigAccess
;
4158 Action
= GetDefaultIdForCallBack (DefaultId
);
4159 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4160 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4161 Status
= ConfigAccess
->Callback (
4164 Question
->QuestionId
,
4169 if (!EFI_ERROR (Status
)) {
4170 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4171 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4172 ASSERT (NewString
!= NULL
);
4174 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4175 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4176 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4177 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4179 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4182 FreePool (NewString
);
4189 // Get default value from altcfg string.
4191 if (ConfigAccess
!= NULL
) {
4192 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4193 if (!EFI_ERROR (Status
)) {
4199 // EFI_IFR_DEFAULT has highest priority
4201 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4202 Link
= GetFirstNode (&Question
->DefaultListHead
);
4203 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4204 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4206 if (Default
->DefaultId
== DefaultId
) {
4207 if (Default
->ValueExpression
!= NULL
) {
4209 // Default is provided by an Expression, evaluate it
4211 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4212 if (EFI_ERROR (Status
)) {
4216 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4217 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4218 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4219 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4220 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4222 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4223 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4225 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4227 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4228 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4231 // Default value is embedded in EFI_IFR_DEFAULT
4233 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4234 ASSERT (HiiValue
->Buffer
!= NULL
);
4235 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4237 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4241 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4242 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4243 if (StrValue
== NULL
) {
4244 return EFI_NOT_FOUND
;
4246 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4247 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4248 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4250 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4257 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4262 // EFI_ONE_OF_OPTION
4264 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4265 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4267 // OneOfOption could only provide Standard and Manufacturing default
4269 Link
= GetFirstNode (&Question
->OptionListHead
);
4270 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4271 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4272 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4274 if ((Option
->SuppressExpression
!= NULL
) &&
4275 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4279 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4280 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4282 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4291 // EFI_IFR_CHECKBOX - lowest priority
4293 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4294 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4296 // Checkbox could only provide Standard and Manufacturing default
4298 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4299 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4301 HiiValue
->Value
.b
= TRUE
;
4309 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4310 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4311 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4313 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4314 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4315 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4316 DefaultId
= DefaultStore
->DefaultId
;
4317 if (DefaultId
== OriginalDefaultId
) {
4324 // For Questions without default value for all the default id in the DefaultStoreList.
4326 Status
= EFI_NOT_FOUND
;
4327 switch (Question
->Operand
) {
4328 case EFI_IFR_CHECKBOX_OP
:
4329 HiiValue
->Value
.b
= FALSE
;
4330 Status
= EFI_SUCCESS
;
4333 case EFI_IFR_NUMERIC_OP
:
4335 // Take minimum value as numeric default value
4337 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4339 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4341 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4342 case EFI_IFR_NUMERIC_SIZE_1
:
4343 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4344 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4345 Status
= EFI_SUCCESS
;
4348 case EFI_IFR_NUMERIC_SIZE_2
:
4349 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4350 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4351 Status
= EFI_SUCCESS
;
4354 case EFI_IFR_NUMERIC_SIZE_4
:
4355 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4356 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4357 Status
= EFI_SUCCESS
;
4360 case EFI_IFR_NUMERIC_SIZE_8
:
4361 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4362 HiiValue
->Value
.u64
= Question
->Minimum
;
4363 Status
= EFI_SUCCESS
;
4370 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4371 HiiValue
->Value
.u64
= Question
->Minimum
;
4372 Status
= EFI_SUCCESS
;
4377 case EFI_IFR_ONE_OF_OP
:
4379 // Take first oneof option as oneof's default value
4381 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4382 Link
= GetFirstNode (&Question
->OptionListHead
);
4383 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4384 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4385 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4387 if ((Option
->SuppressExpression
!= NULL
) &&
4388 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4392 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4393 Status
= EFI_SUCCESS
;
4399 case EFI_IFR_ORDERED_LIST_OP
:
4401 // Take option sequence in IFR as ordered list's default value
4404 Link
= GetFirstNode (&Question
->OptionListHead
);
4405 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4406 Status
= EFI_SUCCESS
;
4407 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4408 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4410 if ((Option
->SuppressExpression
!= NULL
) &&
4411 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4415 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4418 if (Index
>= Question
->MaxContainers
) {
4432 Get AltCfg string for current form.
4434 @param FormSet Form data structure.
4435 @param Form Form data structure.
4436 @param DefaultId The Class of the default.
4437 @param BrowserStorage The input request storage for the questions.
4441 ExtractAltCfgForForm (
4442 IN FORM_BROWSER_FORMSET
*FormSet
,
4443 IN FORM_BROWSER_FORM
*Form
,
4444 IN UINT16 DefaultId
,
4445 IN BROWSER_STORAGE
*BrowserStorage
4453 BROWSER_STORAGE
*Storage
;
4454 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4455 FORMSET_STORAGE
*FormSetStorage
;
4458 // Check whether has get AltCfg string for this formset.
4459 // If yes, no need to get AltCfg for form.
4461 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4462 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4463 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4464 Storage
= FormSetStorage
->BrowserStorage
;
4465 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4466 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4470 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4471 FormSetStorage
->ElementCount
!= 0 &&
4472 FormSetStorage
->HasCallAltCfg
) {
4478 // Get AltCfg string for each form.
4480 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4481 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4482 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4483 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4485 Storage
= ConfigInfo
->Storage
;
4486 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4490 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4495 // 1. Skip if there is no RequestElement
4497 if (ConfigInfo
->ElementCount
== 0) {
4502 // 2. Get value through hii config routine protocol.
4504 Status
= mHiiConfigRouting
->ExtractConfig (
4506 ConfigInfo
->ConfigRequest
,
4510 if (EFI_ERROR (Status
)) {
4515 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4516 // Get the default configuration string according to the default ID.
4518 Status
= mHiiConfigRouting
->GetAltConfig (
4524 &DefaultId
, // it can be NULL to get the current setting.
4528 if (EFI_ERROR (Status
)) {
4532 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4537 Clean AltCfg string for current form.
4539 @param Form Form data structure.
4543 CleanAltCfgForForm (
4544 IN FORM_BROWSER_FORM
*Form
4548 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4550 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4551 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4552 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4553 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4555 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4556 FreePool (ConfigInfo
->ConfigAltResp
);
4557 ConfigInfo
->ConfigAltResp
= NULL
;
4563 Get AltCfg string for current formset.
4565 @param FormSet Form data structure.
4566 @param DefaultId The Class of the default.
4567 @param BrowserStorage The input request storage for the questions.
4571 ExtractAltCfgForFormSet (
4572 IN FORM_BROWSER_FORMSET
*FormSet
,
4573 IN UINT16 DefaultId
,
4574 IN BROWSER_STORAGE
*BrowserStorage
4582 BROWSER_STORAGE
*Storage
;
4583 FORMSET_STORAGE
*FormSetStorage
;
4585 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4586 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4587 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4588 Storage
= FormSetStorage
->BrowserStorage
;
4589 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4591 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4595 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4600 // 1. Skip if there is no RequestElement
4602 if (FormSetStorage
->ElementCount
== 0) {
4606 FormSetStorage
->HasCallAltCfg
= TRUE
;
4609 // 2. Get value through hii config routine protocol.
4611 Status
= mHiiConfigRouting
->ExtractConfig (
4613 FormSetStorage
->ConfigRequest
,
4617 if (EFI_ERROR (Status
)) {
4622 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4623 // Get the default configuration string according to the default ID.
4625 Status
= mHiiConfigRouting
->GetAltConfig (
4631 &DefaultId
, // it can be NULL to get the current setting.
4636 if (EFI_ERROR (Status
)) {
4640 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4646 Clean AltCfg string for current formset.
4648 @param FormSet Form data structure.
4652 CleanAltCfgForFormSet (
4653 IN FORM_BROWSER_FORMSET
*FormSet
4657 FORMSET_STORAGE
*FormSetStorage
;
4659 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4660 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4661 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4662 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4664 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4665 FreePool (FormSetStorage
->ConfigAltResp
);
4666 FormSetStorage
->ConfigAltResp
= NULL
;
4669 FormSetStorage
->HasCallAltCfg
= FALSE
;
4674 Reset Questions to their initial value or default value in a Form, Formset or System.
4676 GetDefaultValueScope parameter decides which questions will reset
4677 to its default value.
4679 @param FormSet FormSet data structure.
4680 @param Form Form data structure.
4681 @param DefaultId The Class of the default.
4682 @param SettingScope Setting Scope for Default action.
4683 @param GetDefaultValueScope Get default value scope.
4684 @param Storage Get default value only for this storage.
4685 @param RetrieveValueFirst Whether call the retrieve call back to
4686 get the initial value before get default
4688 @param SkipGetAltCfg Whether skip the get altcfg string process.
4690 @retval EFI_SUCCESS The function completed successfully.
4691 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4696 IN FORM_BROWSER_FORMSET
*FormSet
,
4697 IN FORM_BROWSER_FORM
*Form
,
4698 IN UINT16 DefaultId
,
4699 IN BROWSER_SETTING_SCOPE SettingScope
,
4700 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4701 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4702 IN BOOLEAN RetrieveValueFirst
,
4703 IN BOOLEAN SkipGetAltCfg
4707 LIST_ENTRY
*FormLink
;
4709 FORM_BROWSER_STATEMENT
*Question
;
4710 FORM_BROWSER_FORMSET
*LocalFormSet
;
4711 FORM_BROWSER_FORMSET
*OldFormSet
;
4713 Status
= EFI_SUCCESS
;
4716 // Check the supported setting level.
4718 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4719 return EFI_UNSUPPORTED
;
4722 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4723 return EFI_UNSUPPORTED
;
4726 if (SettingScope
== FormLevel
) {
4728 // Prepare the AltCfg String for form.
4730 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4731 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4735 // Extract Form default
4737 Link
= GetFirstNode (&Form
->StatementListHead
);
4738 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4739 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4740 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4743 // If get default value only for this storage, check the storage first.
4745 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4750 // If get default value only for no storage question, just skip the question which has storage.
4752 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4757 // If Question is disabled, don't reset it to default
4759 if (Question
->Expression
!= NULL
) {
4760 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4765 if (RetrieveValueFirst
) {
4767 // Call the Retrieve call back to get the initial question value.
4769 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4773 // If not request to get the initial value or get initial value fail, then get default value.
4775 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4776 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4777 if (EFI_ERROR (Status
)) {
4783 // Synchronize Buffer storage's Edit buffer
4785 if ((Question
->Storage
!= NULL
) &&
4786 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4787 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4792 // Clean the AltCfg String.
4794 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4795 CleanAltCfgForForm(Form
);
4797 } else if (SettingScope
== FormSetLevel
) {
4799 // Prepare the AltCfg String for formset.
4801 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4802 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4805 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4806 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4807 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4808 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4809 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4813 // Clean the AltCfg String.
4815 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4816 CleanAltCfgForFormSet (FormSet
);
4818 } else if (SettingScope
== SystemLevel
) {
4820 // Preload all Hii formset.
4822 LoadAllHiiFormset();
4824 OldFormSet
= mSystemLevelFormSet
;
4827 // Set Default Value for each FormSet in the maintain list.
4829 Link
= GetFirstNode (&gBrowserFormSetList
);
4830 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4831 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4832 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4833 if (!ValidateFormSet(LocalFormSet
)) {
4837 mSystemLevelFormSet
= LocalFormSet
;
4839 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4842 mSystemLevelFormSet
= OldFormSet
;
4850 Validate whether this question's value has changed.
4852 @param FormSet FormSet data structure.
4853 @param Form Form data structure.
4854 @param Question Question to be initialized.
4855 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4857 @retval TRUE Question's value has changed.
4858 @retval FALSE Question's value has not changed
4862 IsQuestionValueChanged (
4863 IN FORM_BROWSER_FORMSET
*FormSet
,
4864 IN FORM_BROWSER_FORM
*Form
,
4865 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4866 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4869 EFI_HII_VALUE BackUpValue
;
4870 CHAR8
*BackUpBuffer
;
4871 EFI_HII_VALUE BackUpValue2
;
4872 CHAR8
*BackUpBuffer2
;
4874 BOOLEAN ValueChanged
;
4878 // For quetion without storage, always mark it as data not changed.
4880 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4884 BackUpBuffer
= NULL
;
4885 BackUpBuffer2
= NULL
;
4886 ValueChanged
= FALSE
;
4888 switch (Question
->Operand
) {
4889 case EFI_IFR_ORDERED_LIST_OP
:
4890 BufferWidth
= Question
->StorageWidth
;
4891 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4892 ASSERT (BackUpBuffer
!= NULL
);
4895 case EFI_IFR_STRING_OP
:
4896 case EFI_IFR_PASSWORD_OP
:
4897 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4898 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4899 ASSERT (BackUpBuffer
!= NULL
);
4906 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4908 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4909 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4910 ASSERT_EFI_ERROR(Status
);
4912 switch (Question
->Operand
) {
4913 case EFI_IFR_ORDERED_LIST_OP
:
4914 BufferWidth
= Question
->StorageWidth
;
4915 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4916 ASSERT (BackUpBuffer2
!= NULL
);
4919 case EFI_IFR_STRING_OP
:
4920 case EFI_IFR_PASSWORD_OP
:
4921 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4922 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4923 ASSERT (BackUpBuffer2
!= NULL
);
4930 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4932 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4933 ASSERT_EFI_ERROR(Status
);
4935 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4936 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4937 ValueChanged
= TRUE
;
4940 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4941 ASSERT_EFI_ERROR(Status
);
4943 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4944 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4945 ValueChanged
= TRUE
;
4949 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4950 if (BackUpBuffer
!= NULL
) {
4951 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4952 FreePool (BackUpBuffer
);
4955 if (BackUpBuffer2
!= NULL
) {
4956 FreePool (BackUpBuffer2
);
4959 Question
->ValueChanged
= ValueChanged
;
4961 return ValueChanged
;
4965 Initialize Question's Edit copy from Storage.
4967 @param Selection Selection contains the information about
4968 the Selection, form and formset to be displayed.
4969 Selection action may be updated in retrieve callback.
4970 If Selection is NULL, only initialize Question value.
4971 @param FormSet FormSet data structure.
4972 @param Form Form data structure.
4974 @retval EFI_SUCCESS The function completed successfully.
4979 IN OUT UI_MENU_SELECTION
*Selection
,
4980 IN FORM_BROWSER_FORMSET
*FormSet
,
4981 IN FORM_BROWSER_FORM
*Form
4986 FORM_BROWSER_STATEMENT
*Question
;
4988 Link
= GetFirstNode (&Form
->StatementListHead
);
4989 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4990 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4993 // Initialize local copy of Value for each Question
4995 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4996 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4998 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5000 if (EFI_ERROR (Status
)) {
5004 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5005 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5008 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5015 Initialize Question's Edit copy from Storage for the whole Formset.
5017 @param Selection Selection contains the information about
5018 the Selection, form and formset to be displayed.
5019 Selection action may be updated in retrieve callback.
5020 If Selection is NULL, only initialize Question value.
5021 @param FormSet FormSet data structure.
5023 @retval EFI_SUCCESS The function completed successfully.
5028 IN OUT UI_MENU_SELECTION
*Selection
,
5029 IN FORM_BROWSER_FORMSET
*FormSet
5034 FORM_BROWSER_FORM
*Form
;
5036 Link
= GetFirstNode (&FormSet
->FormListHead
);
5037 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5038 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5041 // Initialize local copy of Value for each Form
5043 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5044 if (EFI_ERROR (Status
)) {
5048 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5052 // Finished question initialization.
5054 FormSet
->QuestionInited
= TRUE
;
5060 Remove the Request element from the Config Request.
5062 @param Storage Pointer to the browser storage.
5063 @param RequestElement The pointer to the Request element.
5068 IN OUT BROWSER_STORAGE
*Storage
,
5069 IN CHAR16
*RequestElement
5075 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5077 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5079 if (NewStr
== NULL
) {
5084 // Remove this element from this ConfigRequest.
5087 NewStr
+= StrLen (RequestElement
);
5088 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5090 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5094 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5096 @param Storage Pointer to the formset storage.
5097 @param ConfigRequest The pointer to the Request element.
5101 RemoveConfigRequest (
5102 FORMSET_STORAGE
*Storage
,
5103 CHAR16
*ConfigRequest
5106 CHAR16
*RequestElement
;
5107 CHAR16
*NextRequestElement
;
5111 // No request element in it, just return.
5113 if (ConfigRequest
== NULL
) {
5117 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5119 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5124 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5126 SearchKey
= L
"&OFFSET";
5130 // Find SearchKey storage
5132 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5133 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5134 ASSERT (RequestElement
!= NULL
);
5135 RequestElement
= StrStr (RequestElement
, SearchKey
);
5137 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5140 while (RequestElement
!= NULL
) {
5142 // +1 to avoid find header itself.
5144 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5147 // The last Request element in configRequest string.
5149 if (NextRequestElement
!= NULL
) {
5151 // Replace "&" with '\0'.
5153 *NextRequestElement
= L
'\0';
5156 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5158 if (NextRequestElement
!= NULL
) {
5160 // Restore '&' with '\0' for later used.
5162 *NextRequestElement
= L
'&';
5165 RequestElement
= NextRequestElement
;
5169 // If no request element remain, just remove the ConfigRequest string.
5171 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5172 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5173 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5174 Storage
->BrowserStorage
->SpareStrLen
= 0;
5179 Base on the current formset info, clean the ConfigRequest string in browser storage.
5181 @param FormSet Pointer of the FormSet
5185 CleanBrowserStorage (
5186 IN OUT FORM_BROWSER_FORMSET
*FormSet
5190 FORMSET_STORAGE
*Storage
;
5192 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5193 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5194 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5195 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5197 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5198 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5202 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5203 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5204 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5205 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5206 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5207 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5209 Storage
->BrowserStorage
->Initialized
= FALSE
;
5215 Check whether current element in the ConfigReqeust string.
5217 @param BrowserStorage Storage which includes ConfigReqeust.
5218 @param RequestElement New element need to check.
5220 @retval TRUE The Element is in the ConfigReqeust string.
5221 @retval FALSE The Element not in the configReqeust String.
5226 BROWSER_STORAGE
*BrowserStorage
,
5227 CHAR16
*RequestElement
5230 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5234 Append the Request element to the Config Request.
5236 @param ConfigRequest Current ConfigRequest info.
5237 @param SpareStrLen Current remain free buffer for config reqeust.
5238 @param RequestElement New Request element.
5242 AppendConfigRequest (
5243 IN OUT CHAR16
**ConfigRequest
,
5244 IN OUT UINTN
*SpareStrLen
,
5245 IN CHAR16
*RequestElement
5253 StrLength
= StrLen (RequestElement
);
5254 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5255 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5258 // Append <RequestElement> to <ConfigRequest>
5260 if (StrLength
> *SpareStrLen
) {
5262 // Old String buffer is not sufficient for RequestElement, allocate a new one
5264 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5265 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5266 ASSERT (NewStr
!= NULL
);
5268 if (*ConfigRequest
!= NULL
) {
5269 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5270 FreePool (*ConfigRequest
);
5272 *ConfigRequest
= NewStr
;
5273 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5276 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5277 *SpareStrLen
-= StrLength
;
5281 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5283 @param Storage Form set Storage.
5284 @param Request The input request string.
5285 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5287 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5288 @retval FALSE All elements covered by current used elements.
5292 ConfigRequestAdjust (
5293 IN BROWSER_STORAGE
*Storage
,
5295 IN BOOLEAN RespString
5298 CHAR16
*RequestElement
;
5299 CHAR16
*NextRequestElement
;
5300 CHAR16
*NextElementBakup
;
5304 CHAR16
*ConfigRequest
;
5307 NextElementBakup
= NULL
;
5310 if (Request
!= NULL
) {
5311 ConfigRequest
= Request
;
5313 ConfigRequest
= Storage
->ConfigRequest
;
5316 if (Storage
->ConfigRequest
== NULL
) {
5317 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5321 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5323 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5328 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5330 SearchKey
= L
"&OFFSET";
5331 ValueKey
= L
"&VALUE";
5335 // Find SearchKey storage
5337 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5338 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5339 ASSERT (RequestElement
!= NULL
);
5340 RequestElement
= StrStr (RequestElement
, SearchKey
);
5342 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5345 while (RequestElement
!= NULL
) {
5348 // +1 to avoid find header itself.
5350 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5353 // The last Request element in configRequest string.
5355 if (NextRequestElement
!= NULL
) {
5356 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5357 NextElementBakup
= NextRequestElement
;
5358 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5359 ASSERT (NextRequestElement
!= NULL
);
5362 // Replace "&" with '\0'.
5364 *NextRequestElement
= L
'\0';
5366 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5367 NextElementBakup
= NextRequestElement
;
5368 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5369 ASSERT (NextRequestElement
!= NULL
);
5371 // Replace "&" with '\0'.
5373 *NextRequestElement
= L
'\0';
5377 if (!ElementValidation (Storage
, RequestElement
)) {
5379 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5381 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5385 if (NextRequestElement
!= NULL
) {
5387 // Restore '&' with '\0' for later used.
5389 *NextRequestElement
= L
'&';
5392 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5393 RequestElement
= NextElementBakup
;
5395 RequestElement
= NextRequestElement
;
5403 Fill storage's edit copy with settings requested from Configuration Driver.
5405 @param FormSet FormSet data structure.
5406 @param Storage Buffer Storage.
5411 IN FORM_BROWSER_FORMSET
*FormSet
,
5412 IN FORMSET_STORAGE
*Storage
5416 EFI_STRING Progress
;
5419 EFI_STRING ConfigRequest
;
5422 ConfigRequest
= NULL
;
5424 switch (Storage
->BrowserStorage
->Type
) {
5425 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5428 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5429 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5430 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5435 case EFI_HII_VARSTORE_BUFFER
:
5436 case EFI_HII_VARSTORE_NAME_VALUE
:
5438 // Skip if there is no RequestElement.
5440 if (Storage
->ElementCount
== 0) {
5445 // Just update the ConfigRequest, if storage already initialized.
5447 if (Storage
->BrowserStorage
->Initialized
) {
5448 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5452 Storage
->BrowserStorage
->Initialized
= TRUE
;
5459 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5461 // Create the config request string to get all fields for this storage.
5462 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5463 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5465 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5466 ConfigRequest
= AllocateZeroPool (StrLen
);
5467 ASSERT (ConfigRequest
!= NULL
);
5471 L
"%s&OFFSET=0&WIDTH=%04x",
5473 Storage
->BrowserStorage
->Size
);
5475 ConfigRequest
= Storage
->ConfigRequest
;
5479 // Request current settings from Configuration Driver
5481 Status
= mHiiConfigRouting
->ExtractConfig (
5489 // If get value fail, extract default from IFR binary
5491 if (EFI_ERROR (Status
)) {
5492 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5495 // Convert Result from <ConfigAltResp> to <ConfigResp>
5497 StrPtr
= StrStr (Result
, L
"&GUID=");
5498 if (StrPtr
!= NULL
) {
5502 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5506 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5509 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5511 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5513 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5514 if (ConfigRequest
!= NULL
) {
5515 FreePool (ConfigRequest
);
5521 Get Value changed status from old question.
5523 @param NewFormSet FormSet data structure.
5524 @param OldQuestion Old question which has value changed.
5528 SyncStatusForQuestion (
5529 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5530 IN FORM_BROWSER_STATEMENT
*OldQuestion
5534 LIST_ENTRY
*QuestionLink
;
5535 FORM_BROWSER_FORM
*Form
;
5536 FORM_BROWSER_STATEMENT
*Question
;
5539 // For each form in one formset.
5541 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5542 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5543 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5544 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5547 // for each question in one form.
5549 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5550 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5551 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5552 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5554 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5555 Question
->ValueChanged
= TRUE
;
5563 Get Value changed status from old formset.
5565 @param NewFormSet FormSet data structure.
5566 @param OldFormSet FormSet data structure.
5570 SyncStatusForFormSet (
5571 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5572 IN FORM_BROWSER_FORMSET
*OldFormSet
5576 LIST_ENTRY
*QuestionLink
;
5577 FORM_BROWSER_FORM
*Form
;
5578 FORM_BROWSER_STATEMENT
*Question
;
5581 // For each form in one formset.
5583 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5584 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5585 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5586 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5589 // for each question in one form.
5591 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5592 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5593 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5594 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5596 if (!Question
->ValueChanged
) {
5601 // Find the same question in new formset and update the value changed flag.
5603 SyncStatusForQuestion (NewFormSet
, Question
);
5609 Get current setting of Questions.
5611 @param FormSet FormSet data structure.
5615 InitializeCurrentSetting (
5616 IN OUT FORM_BROWSER_FORMSET
*FormSet
5620 FORMSET_STORAGE
*Storage
;
5621 FORM_BROWSER_FORMSET
*OldFormSet
;
5624 // Try to find pre FormSet in the maintain backup list.
5625 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5627 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5628 if (OldFormSet
!= NULL
) {
5629 SyncStatusForFormSet (FormSet
, OldFormSet
);
5630 RemoveEntryList (&OldFormSet
->Link
);
5631 DestroyFormSet (OldFormSet
);
5633 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5636 // Extract default from IFR binary for no storage questions.
5638 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5641 // Request current settings from Configuration Driver
5643 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5644 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5645 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5647 LoadStorage (FormSet
, Storage
);
5649 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5655 Fetch the Ifr binary data of a FormSet.
5657 @param Handle PackageList Handle
5658 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5659 specified (NULL or zero GUID), take the first
5660 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5661 found in package list.
5662 On output, GUID of the formset found(if not NULL).
5663 @param BinaryLength The length of the FormSet IFR binary.
5664 @param BinaryData The buffer designed to receive the FormSet.
5666 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5667 BufferLength was updated.
5668 @retval EFI_INVALID_PARAMETER The handle is unknown.
5669 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5670 be found with the requested FormId.
5675 IN EFI_HII_HANDLE Handle
,
5676 IN OUT EFI_GUID
*FormSetGuid
,
5677 OUT UINTN
*BinaryLength
,
5678 OUT UINT8
**BinaryData
5682 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5688 UINT32 PackageListLength
;
5689 EFI_HII_PACKAGE_HEADER PackageHeader
;
5691 UINT8 NumberOfClassGuid
;
5692 BOOLEAN ClassGuidMatch
;
5693 EFI_GUID
*ClassGuid
;
5694 EFI_GUID
*ComparingGuid
;
5698 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5701 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5703 if (FormSetGuid
== NULL
) {
5704 ComparingGuid
= &gZeroGuid
;
5706 ComparingGuid
= FormSetGuid
;
5710 // Get HII PackageList
5713 HiiPackageList
= NULL
;
5714 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5715 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5716 HiiPackageList
= AllocatePool (BufferSize
);
5717 ASSERT (HiiPackageList
!= NULL
);
5719 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5721 if (EFI_ERROR (Status
)) {
5724 ASSERT (HiiPackageList
!= NULL
);
5727 // Get Form package from this HII package List
5729 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5731 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5733 ClassGuidMatch
= FALSE
;
5734 while (Offset
< PackageListLength
) {
5735 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5736 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5738 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5740 // Search FormSet in this Form Package
5742 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5743 while (Offset2
< PackageHeader
.Length
) {
5744 OpCodeData
= Package
+ Offset2
;
5746 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5748 // Try to compare against formset GUID
5750 if (IsZeroGuid (FormSetGuid
) ||
5751 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5755 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5757 // Try to compare against formset class GUID
5759 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5760 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5761 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5762 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5763 ClassGuidMatch
= TRUE
;
5767 if (ClassGuidMatch
) {
5770 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5771 ClassGuidMatch
= TRUE
;
5776 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5779 if (Offset2
< PackageHeader
.Length
) {
5781 // Target formset found
5787 Offset
+= PackageHeader
.Length
;
5790 if (Offset
>= PackageListLength
) {
5792 // Form package not found in this Package List
5794 FreePool (HiiPackageList
);
5795 return EFI_NOT_FOUND
;
5798 if (FormSetGuid
!= NULL
) {
5800 // Return the FormSet GUID
5802 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5806 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5807 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5808 // of the Form Package.
5810 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5811 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5813 FreePool (HiiPackageList
);
5815 if (*BinaryData
== NULL
) {
5816 return EFI_OUT_OF_RESOURCES
;
5824 Initialize the internal data structure of a FormSet.
5826 @param Handle PackageList Handle
5827 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5828 specified (NULL or zero GUID), take the first
5829 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5830 found in package list.
5831 On output, GUID of the formset found(if not NULL).
5832 @param FormSet FormSet data structure.
5834 @retval EFI_SUCCESS The function completed successfully.
5835 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5840 IN EFI_HII_HANDLE Handle
,
5841 IN OUT EFI_GUID
*FormSetGuid
,
5842 OUT FORM_BROWSER_FORMSET
*FormSet
5846 EFI_HANDLE DriverHandle
;
5848 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5849 if (EFI_ERROR (Status
)) {
5853 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5854 FormSet
->HiiHandle
= Handle
;
5855 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5856 FormSet
->QuestionInited
= FALSE
;
5859 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5861 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5862 if (EFI_ERROR (Status
)) {
5865 FormSet
->DriverHandle
= DriverHandle
;
5866 Status
= gBS
->HandleProtocol (
5868 &gEfiHiiConfigAccessProtocolGuid
,
5869 (VOID
**) &FormSet
->ConfigAccess
5871 if (EFI_ERROR (Status
)) {
5873 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5874 // list, then there will be no configuration action required
5876 FormSet
->ConfigAccess
= NULL
;
5880 // Parse the IFR binary OpCodes
5882 Status
= ParseOpCodes (FormSet
);
5889 Save globals used by previous call to SendForm(). SendForm() may be called from
5890 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5891 So, save globals of previous call to SendForm() and restore them upon exit.
5895 SaveBrowserContext (
5899 BROWSER_CONTEXT
*Context
;
5900 FORM_ENTRY_INFO
*MenuList
;
5901 FORM_BROWSER_FORMSET
*FormSet
;
5903 gBrowserContextCount
++;
5904 if (gBrowserContextCount
== 1) {
5906 // This is not reentry of SendForm(), no context to save
5911 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5912 ASSERT (Context
!= NULL
);
5914 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5917 // Save FormBrowser context
5919 Context
->Selection
= gCurrentSelection
;
5920 Context
->ResetRequired
= gResetRequired
;
5921 Context
->FlagReconnect
= gFlagReconnect
;
5922 Context
->CallbackReconnect
= gCallbackReconnect
;
5923 Context
->ExitRequired
= gExitRequired
;
5924 Context
->HiiHandle
= mCurrentHiiHandle
;
5925 Context
->FormId
= mCurrentFormId
;
5926 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5927 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
5928 Context
->CurFakeQestId
= mCurFakeQestId
;
5929 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
5930 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
5933 // Save the menu history data.
5935 InitializeListHead(&Context
->FormHistoryList
);
5936 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5937 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5938 RemoveEntryList (&MenuList
->Link
);
5940 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5944 // Save formset list.
5946 InitializeListHead(&Context
->FormSetList
);
5947 while (!IsListEmpty (&gBrowserFormSetList
)) {
5948 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
5949 RemoveEntryList (&FormSet
->Link
);
5951 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
5955 // Insert to FormBrowser context list
5957 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5962 Restore globals used by previous call to SendForm().
5966 RestoreBrowserContext (
5971 BROWSER_CONTEXT
*Context
;
5972 FORM_ENTRY_INFO
*MenuList
;
5973 FORM_BROWSER_FORMSET
*FormSet
;
5975 ASSERT (gBrowserContextCount
!= 0);
5976 gBrowserContextCount
--;
5977 if (gBrowserContextCount
== 0) {
5979 // This is not reentry of SendForm(), no context to restore
5984 ASSERT (!IsListEmpty (&gBrowserContextList
));
5986 Link
= GetFirstNode (&gBrowserContextList
);
5987 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5990 // Restore FormBrowser context
5992 gCurrentSelection
= Context
->Selection
;
5993 gResetRequired
= Context
->ResetRequired
;
5994 gFlagReconnect
= Context
->FlagReconnect
;
5995 gCallbackReconnect
= Context
->CallbackReconnect
;
5996 gExitRequired
= Context
->ExitRequired
;
5997 mCurrentHiiHandle
= Context
->HiiHandle
;
5998 mCurrentFormId
= Context
->FormId
;
5999 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6000 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6001 mCurFakeQestId
= Context
->CurFakeQestId
;
6002 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6003 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6006 // Restore the menu history data.
6008 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6009 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6010 RemoveEntryList (&MenuList
->Link
);
6012 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6016 // Restore the Formset data.
6018 while (!IsListEmpty (&Context
->FormSetList
)) {
6019 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6020 RemoveEntryList (&FormSet
->Link
);
6022 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6026 // Remove from FormBrowser context list
6028 RemoveEntryList (&Context
->Link
);
6029 gBS
->FreePool (Context
);
6033 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6035 @param Handle The Hii Handle.
6037 @return the found FormSet context. If no found, NULL will return.
6040 FORM_BROWSER_FORMSET
*
6041 GetFormSetFromHiiHandle (
6042 EFI_HII_HANDLE Handle
6046 FORM_BROWSER_FORMSET
*FormSet
;
6048 Link
= GetFirstNode (&gBrowserFormSetList
);
6049 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6050 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6051 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6052 if (!ValidateFormSet(FormSet
)) {
6055 if (FormSet
->HiiHandle
== Handle
) {
6064 Check whether the input HII handle is the FormSet that is being used.
6066 @param Handle The Hii Handle.
6068 @retval TRUE HII handle is being used.
6069 @retval FALSE HII handle is not being used.
6073 IsHiiHandleInBrowserContext (
6074 EFI_HII_HANDLE Handle
6078 BROWSER_CONTEXT
*Context
;
6081 // HiiHandle is Current FormSet.
6083 if (mCurrentHiiHandle
== Handle
) {
6088 // Check whether HiiHandle is in BrowserContext.
6090 Link
= GetFirstNode (&gBrowserContextList
);
6091 while (!IsNull (&gBrowserContextList
, Link
)) {
6092 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6093 if (Context
->HiiHandle
== Handle
) {
6095 // HiiHandle is in BrowserContext
6099 Link
= GetNextNode (&gBrowserContextList
, Link
);
6106 Perform Password check.
6107 Passwork may be encrypted by driver that requires the specific check.
6109 @param Form Form where Password Statement is in.
6110 @param Statement Password statement
6111 @param PasswordString Password string to be checked. It may be NULL.
6112 NULL means to restore password.
6113 "" string can be used to checked whether old password does exist.
6115 @return Status Status of Password check.
6120 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6121 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6122 IN EFI_STRING PasswordString OPTIONAL
6126 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6127 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6128 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6129 FORM_BROWSER_STATEMENT
*Question
;
6131 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6132 Question
= GetBrowserStatement(Statement
);
6133 ASSERT (Question
!= NULL
);
6135 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6136 if (ConfigAccess
== NULL
) {
6137 return EFI_UNSUPPORTED
;
6141 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6143 return EFI_UNSUPPORTED
;
6147 // Prepare password string in HII database
6149 if (PasswordString
!= NULL
) {
6150 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6152 IfrTypeValue
.string
= 0;
6156 // Send password to Configuration Driver for validation
6158 Status
= ConfigAccess
->Callback (
6160 EFI_BROWSER_ACTION_CHANGING
,
6161 Question
->QuestionId
,
6162 Question
->HiiValue
.Type
,
6168 // Remove password string from HII database
6170 if (PasswordString
!= NULL
) {
6171 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6178 Find the registered HotKey based on KeyData.
6180 @param[in] KeyData A pointer to a buffer that describes the keystroke
6181 information for the hot key.
6183 @return The registered HotKey context. If no found, NULL will return.
6186 GetHotKeyFromRegisterList (
6187 IN EFI_INPUT_KEY
*KeyData
6191 BROWSER_HOT_KEY
*HotKey
;
6193 Link
= GetFirstNode (&gBrowserHotKeyList
);
6194 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6195 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6196 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6199 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6206 Configure what scope the hot key will impact.
6207 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6208 If no scope is set, the default scope will be FormSet level.
6209 After all registered hot keys are removed, previous Scope can reset to another level.
6211 @param[in] Scope Scope level to be set.
6213 @retval EFI_SUCCESS Scope is set correctly.
6214 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6215 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6221 IN BROWSER_SETTING_SCOPE Scope
6224 if (Scope
>= MaxLevel
) {
6225 return EFI_INVALID_PARAMETER
;
6229 // When no hot key registered in system or on the first setting,
6230 // Scope can be set.
6232 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6233 gBrowserSettingScope
= Scope
;
6234 mBrowserScopeFirstSet
= FALSE
;
6235 } else if (Scope
!= gBrowserSettingScope
) {
6236 return EFI_UNSUPPORTED
;
6243 Register the hot key with its browser action, or unregistered the hot key.
6244 Only support hot key that is not printable character (control key, function key, etc.).
6245 If the action value is zero, the hot key will be unregistered if it has been registered.
6246 If the same hot key has been registered, the new action and help string will override the previous ones.
6248 @param[in] KeyData A pointer to a buffer that describes the keystroke
6249 information for the hot key. Its type is EFI_INPUT_KEY to
6250 be supported by all ConsoleIn devices.
6251 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6252 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6253 @param[in] HelpString Help string that describes the hot key information.
6254 Its value may be NULL for the unregistered hot key.
6256 @retval EFI_SUCCESS Hot key is registered or unregistered.
6257 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6258 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6259 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6260 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6265 IN EFI_INPUT_KEY
*KeyData
,
6267 IN UINT16 DefaultId
,
6268 IN EFI_STRING HelpString OPTIONAL
6271 BROWSER_HOT_KEY
*HotKey
;
6274 // Check input parameters.
6276 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6277 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6278 return EFI_INVALID_PARAMETER
;
6282 // Check whether the input KeyData is in BrowserHotKeyList.
6284 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6287 // Unregister HotKey
6289 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6290 if (HotKey
!= NULL
) {
6292 // The registered HotKey is found.
6293 // Remove it from List, and free its resource.
6295 RemoveEntryList (&HotKey
->Link
);
6296 FreePool (HotKey
->KeyData
);
6297 FreePool (HotKey
->HelpString
);
6301 // The registered HotKey is not found.
6303 return EFI_NOT_FOUND
;
6307 if (HotKey
!= NULL
) {
6308 return EFI_ALREADY_STARTED
;
6312 // Create new Key, and add it into List.
6314 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6315 ASSERT (HotKey
!= NULL
);
6316 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6317 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6318 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6321 // Fill HotKey information.
6323 HotKey
->Action
= Action
;
6324 HotKey
->DefaultId
= DefaultId
;
6325 if (HotKey
->HelpString
!= NULL
) {
6326 FreePool (HotKey
->HelpString
);
6328 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6334 Register Exit handler function.
6335 When more than one handler function is registered, the latter one will override the previous one.
6336 When NULL handler is specified, the previous Exit handler will be unregistered.
6338 @param[in] Handler Pointer to handler function.
6343 RegiserExitHandler (
6344 IN EXIT_HANDLER Handler
6347 ExitHandlerFunction
= Handler
;
6352 Check whether the browser data has been modified.
6354 @retval TRUE Browser data is modified.
6355 @retval FALSE No browser data is modified.
6360 IsBrowserDataModified (
6365 FORM_BROWSER_FORMSET
*FormSet
;
6367 switch (gBrowserSettingScope
) {
6369 if (gCurrentSelection
== NULL
) {
6372 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6375 if (gCurrentSelection
== NULL
) {
6378 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6381 Link
= GetFirstNode (&gBrowserFormSetList
);
6382 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6383 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6384 if (!ValidateFormSet(FormSet
)) {
6388 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6391 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6401 Execute the action requested by the Action parameter.
6403 @param[in] Action Execute the request action.
6404 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6406 @retval EFI_SUCCESS Execute the request action succss.
6407 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6418 FORM_BROWSER_FORMSET
*FormSet
;
6419 FORM_BROWSER_FORM
*Form
;
6421 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6422 return EFI_NOT_READY
;
6425 Status
= EFI_SUCCESS
;
6428 if (gBrowserSettingScope
< SystemLevel
) {
6429 FormSet
= gCurrentSelection
->FormSet
;
6430 Form
= gCurrentSelection
->Form
;
6434 // Executet the discard action.
6436 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6437 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6438 if (EFI_ERROR (Status
)) {
6444 // Executet the difault action.
6446 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6447 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6448 if (EFI_ERROR (Status
)) {
6451 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6455 // Executet the submit action.
6457 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6458 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6459 if (EFI_ERROR (Status
)) {
6465 // Executet the reset action.
6467 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6468 gResetRequired
= TRUE
;
6472 // Executet the exit action.
6474 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6475 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6476 if (gBrowserSettingScope
== SystemLevel
) {
6477 if (ExitHandlerFunction
!= NULL
) {
6478 ExitHandlerFunction ();
6482 gExitRequired
= TRUE
;
6489 Create reminder to let user to choose save or discard the changed browser data.
6490 Caller can use it to actively check the changed browser data.
6492 @retval BROWSER_NO_CHANGES No browser data is changed.
6493 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6494 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6495 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6505 FORM_BROWSER_FORMSET
*FormSet
;
6506 BOOLEAN IsDataChanged
;
6507 UINT32 DataSavedAction
;
6510 DataSavedAction
= BROWSER_NO_CHANGES
;
6511 IsDataChanged
= FALSE
;
6512 Link
= GetFirstNode (&gBrowserFormSetList
);
6513 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6514 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6515 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6516 if (!ValidateFormSet(FormSet
)) {
6519 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6520 IsDataChanged
= TRUE
;
6526 // No data is changed. No save is required.
6528 if (!IsDataChanged
) {
6529 return DataSavedAction
;
6533 // If data is changed, prompt user to save or discard it.
6536 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6538 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6539 SubmitForm (NULL
, NULL
, SystemLevel
);
6540 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6542 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6543 DiscardForm (NULL
, NULL
, SystemLevel
);
6544 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6546 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6547 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6552 return DataSavedAction
;
6556 Check whether the Reset Required for the browser
6558 @retval TRUE Browser required to reset after exit.
6559 @retval FALSE Browser not need to reset after exit.
6568 return gResetRequired
;