2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2016, 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 (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
186 // FormSetGuid is not specified.
189 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
190 if (MenuList
->FormId
== FormId
) {
192 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
193 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
194 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
206 Find parent menu for current menu.
208 @param CurrentMenu Current Menu
209 @param SettingLevel Whether find parent menu in Form Level or Formset level.
210 In form level, just find the parent menu;
211 In formset level, find the parent menu which has different
214 @retval The parent menu for current menu.
218 IN FORM_ENTRY_INFO
*CurrentMenu
,
219 IN BROWSER_SETTING_SCOPE SettingLevel
222 FORM_ENTRY_INFO
*ParentMenu
;
225 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
227 if (CurrentMenu
== NULL
) {
232 Link
= &CurrentMenu
->Link
;
234 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
235 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
237 if (SettingLevel
== FormLevel
) {
239 // For FormLevel, just find the parent menu, return.
244 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
246 // For SystemLevel, must find the menu which has different formset.
251 Link
= Link
->BackLink
;
255 // Not find the parent menu, just return NULL.
257 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
265 Free Menu list linked list.
267 @param MenuListHead One Menu list point in the menu list.
272 LIST_ENTRY
*MenuListHead
275 FORM_ENTRY_INFO
*MenuList
;
277 while (!IsListEmpty (MenuListHead
)) {
278 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
279 RemoveEntryList (&MenuList
->Link
);
286 Copy current Menu list to the new menu list.
288 @param NewMenuListHead New create Menu list.
289 @param CurrentMenuListHead Current Menu list.
294 OUT LIST_ENTRY
*NewMenuListHead
,
295 IN LIST_ENTRY
*CurrentMenuListHead
299 FORM_ENTRY_INFO
*MenuList
;
300 FORM_ENTRY_INFO
*NewMenuEntry
;
303 // If new menu list not empty, free it first.
305 UiFreeMenuList (NewMenuListHead
);
307 Link
= GetFirstNode (CurrentMenuListHead
);
308 while (!IsNull (CurrentMenuListHead
, Link
)) {
309 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
310 Link
= GetNextNode (CurrentMenuListHead
, Link
);
312 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
313 ASSERT (NewMenuEntry
!= NULL
);
314 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
315 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
316 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
317 NewMenuEntry
->FormId
= MenuList
->FormId
;
318 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
320 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
325 Load all hii formset to the browser.
333 FORM_BROWSER_FORMSET
*LocalFormSet
;
334 EFI_HII_HANDLE
*HiiHandles
;
338 FORM_BROWSER_FORMSET
*OldFormset
;
340 OldFormset
= mSystemLevelFormSet
;
343 // Get all the Hii handles
345 HiiHandles
= HiiGetHiiHandles (NULL
);
346 ASSERT (HiiHandles
!= NULL
);
349 // Search for formset of each class type
351 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
353 // Check HiiHandles[Index] does exist in global maintain list.
355 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
360 // Initilize FormSet Setting
362 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
363 ASSERT (LocalFormSet
!= NULL
);
364 mSystemLevelFormSet
= LocalFormSet
;
366 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
367 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
368 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
369 DestroyFormSet (LocalFormSet
);
372 InitializeCurrentSetting (LocalFormSet
);
375 // Initilize Questions' Value
377 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
378 if (EFI_ERROR (Status
)) {
379 DestroyFormSet (LocalFormSet
);
385 // Free resources, and restore gOldFormSet and gClassOfVfr
387 FreePool (HiiHandles
);
389 mSystemLevelFormSet
= OldFormset
;
393 Pop up the error info.
395 @param BrowserStatus The input browser status.
396 @param HiiHandle The Hiihandle for this opcode.
397 @param OpCode The opcode use to get the erro info and timeout value.
398 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
403 IN UINT32 BrowserStatus
,
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
406 IN CHAR16
*ErrorString
409 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
410 USER_INPUT UserInputData
;
414 if (OpCode
!= NULL
) {
415 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
416 ASSERT (Statement
!= NULL
);
417 Statement
->OpCode
= OpCode
;
418 gDisplayFormData
.HighLightedStatement
= Statement
;
422 // Used to compatible with old display engine.
423 // New display engine not use this field.
425 gDisplayFormData
.ErrorString
= ErrorString
;
426 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
428 if (HiiHandle
!= NULL
) {
429 gDisplayFormData
.HiiHandle
= HiiHandle
;
432 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
434 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
435 gDisplayFormData
.ErrorString
= NULL
;
437 if (OpCode
!= NULL
) {
438 FreePool (Statement
);
441 return UserInputData
.Action
;
445 This is the routine which an external caller uses to direct the browser
446 where to obtain it's information.
449 @param This The Form Browser protocol instanse.
450 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
451 display a list of the formsets for the handles specified.
452 @param HandleCount The number of Handles specified in Handle.
453 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
454 field in the EFI_IFR_FORM_SET op-code for the specified
455 forms-based package. If FormSetGuid is NULL, then this
456 function will display the first found forms package.
457 @param FormId This field specifies which EFI_IFR_FORM to render as the first
458 displayable page. If this field has a value of 0x0000, then
459 the forms browser will render the specified forms in their encoded order.
460 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
462 @param ActionRequest Points to the action recommended by the form.
464 @retval EFI_SUCCESS The function completed successfully.
465 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
466 @retval EFI_NOT_FOUND No valid forms could be found to display.
472 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
473 IN EFI_HII_HANDLE
*Handles
,
474 IN UINTN HandleCount
,
475 IN EFI_GUID
*FormSetGuid
, OPTIONAL
476 IN UINT16 FormId
, OPTIONAL
477 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
478 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
482 UI_MENU_SELECTION
*Selection
;
484 FORM_BROWSER_FORMSET
*FormSet
;
485 FORM_ENTRY_INFO
*MenuList
;
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 &gEfiFormBrowserExProtocolGuid
,
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 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1978 BufferLen
= StorageWidth
* 2 + 1;
1979 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1980 ASSERT (Value
!= NULL
);
1982 // Convert Buffer to Hex String
1984 TemBuffer
= Src
+ StorageWidth
- 1;
1986 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1987 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1991 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1993 if (EFI_ERROR (Status
)) {
1997 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1999 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2000 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2002 if (IsBufferStorage
) {
2003 Length
= StrLen (Question
->BlockName
) + 7;
2005 Length
= StrLen (Question
->VariableName
) + 2;
2007 if (!IsBufferStorage
&& IsString
) {
2008 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2010 Length
+= (StorageWidth
* 2);
2012 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2013 ASSERT (FormsetStorage
!= NULL
);
2014 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2015 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2016 ASSERT (ConfigResp
!= NULL
);
2018 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2019 if (IsBufferStorage
) {
2020 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2021 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2023 StrCatS (ConfigResp
, MaxLen
, L
"&");
2024 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2025 StrCatS (ConfigResp
, MaxLen
, L
"=");
2028 Value
= ConfigResp
+ StrLen (ConfigResp
);
2030 if (!IsBufferStorage
&& IsString
) {
2032 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2034 TemName
= (CHAR16
*) Src
;
2036 for (; *TemName
!= L
'\0'; TemName
++) {
2037 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
2041 // Convert Buffer to Hex String
2043 TemBuffer
= Src
+ StorageWidth
- 1;
2045 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2046 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2051 // Convert to lower char.
2053 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2054 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2055 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2060 // Submit Question Value to Configuration Driver
2062 Status
= mHiiConfigRouting
->RouteConfig (
2067 if (EFI_ERROR (Status
)) {
2068 FreePool (ConfigResp
);
2071 FreePool (ConfigResp
);
2074 // Sync storage, from editbuffer to buffer.
2076 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2084 Perform nosubmitif check for a Form.
2086 @param FormSet FormSet data structure.
2087 @param Form Form data structure.
2088 @param Question The Question to be validated.
2089 @param Type Validation type: NoSubmit
2091 @retval EFI_SUCCESS Form validation pass.
2092 @retval other Form validation failed.
2097 IN FORM_BROWSER_FORMSET
*FormSet
,
2098 IN FORM_BROWSER_FORM
*Form
,
2099 IN FORM_BROWSER_STATEMENT
*Question
,
2105 LIST_ENTRY
*ListHead
;
2106 FORM_EXPRESSION
*Expression
;
2107 UINT32 BrowserStatus
;
2110 BrowserStatus
= BROWSER_SUCCESS
;
2114 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2115 ListHead
= &Question
->InconsistentListHead
;
2118 case EFI_HII_EXPRESSION_WARNING_IF
:
2119 ListHead
= &Question
->WarningListHead
;
2122 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2123 ListHead
= &Question
->NoSubmitListHead
;
2128 return EFI_UNSUPPORTED
;
2131 Link
= GetFirstNode (ListHead
);
2132 while (!IsNull (ListHead
, Link
)) {
2133 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2136 // Evaluate the expression
2138 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2139 if (EFI_ERROR (Status
)) {
2143 if (IsTrue (&Expression
->Result
)) {
2145 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2146 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2149 case EFI_HII_EXPRESSION_WARNING_IF
:
2150 BrowserStatus
= BROWSER_WARNING_IF
;
2153 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2154 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2156 // This code only used to compatible with old display engine,
2157 // New display engine will not use this field.
2159 if (Expression
->Error
!= 0) {
2160 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2169 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2171 // If in system submit process and for no_submit_if check, not popup this error message.
2172 // Will process this fail again later in not system submit process.
2174 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2177 if (ErrorStr
!= NULL
) {
2178 FreePool (ErrorStr
);
2181 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2184 return EFI_NOT_READY
;
2188 Link
= GetNextNode (ListHead
, Link
);
2195 Perform question check.
2197 If one question has more than one check, process form high priority to low.
2198 Only one error info will be popup.
2200 @param FormSet FormSet data structure.
2201 @param Form Form data structure.
2202 @param Question The Question to be validated.
2204 @retval EFI_SUCCESS Form validation pass.
2205 @retval other Form validation failed.
2209 ValueChangedValidation (
2210 IN FORM_BROWSER_FORMSET
*FormSet
,
2211 IN FORM_BROWSER_FORM
*Form
,
2212 IN FORM_BROWSER_STATEMENT
*Question
2217 Status
= EFI_SUCCESS
;
2220 // Do the inconsistentif check.
2222 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2223 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2224 if (EFI_ERROR (Status
)) {
2230 // Do the warningif check.
2232 if (!IsListEmpty (&Question
->WarningListHead
)) {
2233 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2240 Perform NoSubmit check for each Form in FormSet.
2242 @param FormSet FormSet data structure.
2243 @param CurrentForm Current input form data structure.
2244 @param Statement The statement for this check.
2246 @retval EFI_SUCCESS Form validation pass.
2247 @retval other Form validation failed.
2252 IN FORM_BROWSER_FORMSET
*FormSet
,
2253 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2254 OUT FORM_BROWSER_STATEMENT
**Statement
2259 FORM_BROWSER_STATEMENT
*Question
;
2260 FORM_BROWSER_FORM
*Form
;
2261 LIST_ENTRY
*LinkForm
;
2263 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2264 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2265 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2266 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2268 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2272 Link
= GetFirstNode (&Form
->StatementListHead
);
2273 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2274 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2275 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2276 if (EFI_ERROR (Status
)) {
2277 if (*CurrentForm
== NULL
) {
2278 *CurrentForm
= Form
;
2280 if (Statement
!= NULL
) {
2281 *Statement
= Question
;
2286 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2294 Fill storage's edit copy with settings requested from Configuration Driver.
2296 @param Storage The storage which need to sync.
2297 @param ConfigRequest The config request string which used to sync storage.
2298 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2299 editbuffer to buffer
2300 if TRUE, copy the editbuffer to the buffer.
2301 if FALSE, copy the buffer to the editbuffer.
2303 @retval EFI_SUCCESS The function completed successfully.
2307 SynchronizeStorage (
2308 OUT BROWSER_STORAGE
*Storage
,
2309 IN CHAR16
*ConfigRequest
,
2310 IN BOOLEAN SyncOrRestore
2314 EFI_STRING Progress
;
2318 NAME_VALUE_NODE
*Node
;
2322 Status
= EFI_SUCCESS
;
2325 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2326 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2327 BufferSize
= Storage
->Size
;
2329 if (SyncOrRestore
) {
2330 Src
= Storage
->EditBuffer
;
2331 Dst
= Storage
->Buffer
;
2333 Src
= Storage
->Buffer
;
2334 Dst
= Storage
->EditBuffer
;
2337 if (ConfigRequest
!= NULL
) {
2338 Status
= mHiiConfigRouting
->BlockToConfig(
2346 if (EFI_ERROR (Status
)) {
2350 Status
= mHiiConfigRouting
->ConfigToBlock (
2357 if (Result
!= NULL
) {
2361 CopyMem (Dst
, Src
, BufferSize
);
2363 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2364 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2365 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2366 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2368 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2369 (ConfigRequest
== NULL
)) {
2370 if (SyncOrRestore
) {
2371 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2373 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2377 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2385 When discard the question value, call the callback function with Changed type
2386 to inform the hii driver.
2388 @param FormSet FormSet data structure.
2389 @param Form Form data structure.
2393 SendDiscardInfoToDriver (
2394 IN FORM_BROWSER_FORMSET
*FormSet
,
2395 IN FORM_BROWSER_FORM
*Form
2399 FORM_BROWSER_STATEMENT
*Question
;
2400 EFI_IFR_TYPE_VALUE
*TypeValue
;
2401 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2403 if (FormSet
->ConfigAccess
== NULL
) {
2407 Link
= GetFirstNode (&Form
->StatementListHead
);
2408 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2409 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2410 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2412 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2416 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2420 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2424 if (!Question
->ValueChanged
) {
2429 // Restore the question value before call the CHANGED callback type.
2431 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2433 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2434 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2437 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2438 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2440 TypeValue
= &Question
->HiiValue
.Value
;
2443 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2444 FormSet
->ConfigAccess
->Callback (
2445 FormSet
->ConfigAccess
,
2446 EFI_BROWSER_ACTION_CHANGED
,
2447 Question
->QuestionId
,
2448 Question
->HiiValue
.Type
,
2456 When submit the question value, call the callback function with Submitted type
2457 to inform the hii driver.
2459 @param FormSet FormSet data structure.
2460 @param Form Form data structure.
2464 SubmitCallbackForForm (
2465 IN FORM_BROWSER_FORMSET
*FormSet
,
2466 IN FORM_BROWSER_FORM
*Form
2470 FORM_BROWSER_STATEMENT
*Question
;
2471 EFI_IFR_TYPE_VALUE
*TypeValue
;
2472 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2474 if (FormSet
->ConfigAccess
== NULL
) {
2478 Link
= GetFirstNode (&Form
->StatementListHead
);
2479 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2480 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2481 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2483 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2487 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2491 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2495 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2496 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2498 TypeValue
= &Question
->HiiValue
.Value
;
2501 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2502 FormSet
->ConfigAccess
->Callback (
2503 FormSet
->ConfigAccess
,
2504 EFI_BROWSER_ACTION_SUBMITTED
,
2505 Question
->QuestionId
,
2506 Question
->HiiValue
.Type
,
2514 When value set Success, call the submit callback function.
2516 @param FormSet FormSet data structure.
2517 @param Form Form data structure.
2522 IN FORM_BROWSER_FORMSET
*FormSet
,
2523 IN FORM_BROWSER_FORM
*Form
2526 FORM_BROWSER_FORM
*CurrentForm
;
2530 SubmitCallbackForForm(FormSet
, Form
);
2534 Link
= GetFirstNode (&FormSet
->FormListHead
);
2535 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2536 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2537 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2539 SubmitCallbackForForm(FormSet
, CurrentForm
);
2544 Validate the HiiHandle.
2546 @param HiiHandle The input HiiHandle which need to validate.
2548 @retval TRUE The handle is validate.
2549 @retval FALSE The handle is invalidate.
2554 EFI_HII_HANDLE HiiHandle
2557 EFI_HII_HANDLE
*HiiHandles
;
2561 if (HiiHandle
== NULL
) {
2567 HiiHandles
= HiiGetHiiHandles (NULL
);
2568 ASSERT (HiiHandles
!= NULL
);
2570 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2571 if (HiiHandles
[Index
] == HiiHandle
) {
2577 FreePool (HiiHandles
);
2583 Validate the FormSet. If the formset is not validate, remove it from the list.
2585 @param FormSet The input FormSet which need to validate.
2587 @retval TRUE The handle is validate.
2588 @retval FALSE The handle is invalidate.
2593 FORM_BROWSER_FORMSET
*FormSet
2598 ASSERT (FormSet
!= NULL
);
2600 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2602 // Should not remove the formset which is being used.
2604 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2605 CleanBrowserStorage(FormSet
);
2606 RemoveEntryList (&FormSet
->Link
);
2607 DestroyFormSet (FormSet
);
2613 Check whether need to enable the reset flag in form level.
2614 Also clean all ValueChanged flag in question.
2616 @param SetFlag Whether need to set the Reset Flag.
2617 @param FormSet FormSet data structure.
2618 @param Form Form data structure.
2624 IN FORM_BROWSER_FORMSET
*FormSet
,
2625 IN FORM_BROWSER_FORM
*Form
2629 FORM_BROWSER_STATEMENT
*Question
;
2632 Link
= GetFirstNode (&Form
->StatementListHead
);
2633 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2634 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2635 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2637 if (!Question
->ValueChanged
) {
2641 OldValue
= Question
->ValueChanged
;
2644 // Compare the buffer and editbuffer data to see whether the data has been saved.
2646 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2649 // Only the changed data has been saved, then need to set the reset flag.
2651 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2652 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2653 gResetRequired
= TRUE
;
2656 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2657 gFlagReconnect
= TRUE
;
2664 Check whether need to enable the reset flag.
2665 Also clean ValueChanged flag for all statements.
2667 Form level or formset level, only one.
2669 @param SetFlag Whether need to set the Reset Flag.
2670 @param FormSet FormSet data structure.
2671 @param Form Form data structure.
2675 ValueChangeResetFlagUpdate (
2677 IN FORM_BROWSER_FORMSET
*FormSet
,
2678 IN FORM_BROWSER_FORM
*Form
2681 FORM_BROWSER_FORM
*CurrentForm
;
2685 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2689 Link
= GetFirstNode (&FormSet
->FormListHead
);
2690 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2691 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2692 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2694 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2699 Base on the return Progress string to find the form.
2701 Base on the first return Offset/Width (Name) string to find the form
2702 which keep this string.
2704 @param FormSet FormSet data structure.
2705 @param Storage Storage which has this Progress string.
2706 @param Progress The Progress string which has the first fail string.
2707 @param RetForm The return form for this progress string.
2708 @param RetQuestion The return question for the error progress string.
2710 @retval TRUE Find the error form and statement for this error progress string.
2711 @retval FALSE Not find the error form.
2715 FindQuestionFromProgress (
2716 IN FORM_BROWSER_FORMSET
*FormSet
,
2717 IN BROWSER_STORAGE
*Storage
,
2718 IN EFI_STRING Progress
,
2719 OUT FORM_BROWSER_FORM
**RetForm
,
2720 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2724 LIST_ENTRY
*LinkStorage
;
2725 LIST_ENTRY
*LinkStatement
;
2726 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2727 FORM_BROWSER_FORM
*Form
;
2729 FORM_BROWSER_STATEMENT
*Statement
;
2731 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2735 *RetQuestion
= NULL
;
2738 // Skip the first "&" or the ConfigHdr part.
2740 if (*Progress
== '&') {
2744 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2746 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2748 // For Name/Value type, Skip the ConfigHdr part.
2750 EndStr
= StrStr (Progress
, L
"PATH=");
2751 ASSERT (EndStr
!= NULL
);
2752 while (*EndStr
!= '&') {
2759 // For Buffer type, Skip the ConfigHdr part.
2761 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2762 ASSERT (EndStr
!= NULL
);
2766 Progress
= EndStr
+ 1;
2770 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2772 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2774 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2775 // here, just keep the "Fred" string.
2777 EndStr
= StrStr (Progress
, L
"=");
2778 ASSERT (EndStr
!= NULL
);
2782 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2783 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2785 EndStr
= StrStr (Progress
, L
"&VALUE=");
2786 ASSERT (EndStr
!= NULL
);
2791 // Search in the form list.
2793 Link
= GetFirstNode (&FormSet
->FormListHead
);
2794 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2795 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2796 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2799 // Search in the ConfigReqeust list in this form.
2801 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2802 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2803 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2804 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2806 if (Storage
!= ConfigInfo
->Storage
) {
2810 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2812 // Find the OffsetWidth string in this form.
2819 if (*RetForm
!= NULL
) {
2820 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2821 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2822 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2823 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2825 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2826 *RetQuestion
= Statement
;
2830 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2831 *RetQuestion
= Statement
;
2837 if (*RetForm
!= NULL
) {
2843 // restore the OffsetWidth string to the original format.
2845 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2851 return (BOOLEAN
) (*RetForm
!= NULL
);
2855 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2856 for form and formset.
2858 @param Storage Storage which has this Progress string.
2859 @param ConfigRequest The ConfigRequest string.
2860 @param Progress The Progress string which has the first fail string.
2861 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2862 @param SyncConfigRequest Return the SyncConfigRequest string.
2866 GetSyncRestoreConfigRequest(
2867 IN BROWSER_STORAGE
*Storage
,
2868 IN EFI_STRING ConfigRequest
,
2869 IN EFI_STRING Progress
,
2870 OUT EFI_STRING
*RestoreConfigRequest
,
2871 OUT EFI_STRING
*SyncConfigRequest
2875 EFI_STRING ConfigHdrEndStr
;
2876 EFI_STRING ElementStr
;
2878 UINTN RestoreEleSize
;
2881 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
2883 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
2884 // Need to restore all the fields in the ConfigRequest.
2886 if (*Progress
== L
'G') {
2887 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2888 ASSERT (*RestoreConfigRequest
!= NULL
);
2893 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2895 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2897 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2898 // here, just keep the "Fred" string.
2900 EndStr
= StrStr (Progress
, L
"=");
2901 ASSERT (EndStr
!= NULL
);
2904 // Find the ConfigHdr in ConfigRequest.
2906 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
2907 ASSERT (ConfigHdrEndStr
!= NULL
);
2908 while (*ConfigHdrEndStr
!= L
'&') {
2913 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2914 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2916 EndStr
= StrStr (Progress
, L
"&VALUE=");
2917 ASSERT (EndStr
!= NULL
);
2920 // Find the ConfigHdr in ConfigRequest.
2922 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
2925 // Find the first fail pair in the ConfigRequest.
2927 ElementStr
= StrStr (ConfigRequest
, Progress
);
2928 ASSERT (ElementStr
!= NULL
);
2930 // To get the RestoreConfigRequest.
2932 RestoreEleSize
= StrSize (ElementStr
);
2933 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
2934 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
2935 ASSERT (*RestoreConfigRequest
!= NULL
);
2936 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
2937 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
2939 // To get the SyncConfigRequest.
2941 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
2942 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
2943 ASSERT (*SyncConfigRequest
!= NULL
);
2944 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
2947 // restore the Progress string to the original format.
2949 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2957 Popup an save error info and get user input.
2959 @param TitleId The form title id.
2960 @param HiiHandle The hii handle for this package.
2962 @retval UINT32 The user select option for the save fail.
2963 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
2967 IN EFI_STRING_ID TitleId
,
2968 IN EFI_HII_HANDLE HiiHandle
2972 CHAR16
*StringBuffer
;
2975 FormTitle
= GetToken (TitleId
, HiiHandle
);
2977 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
2978 ASSERT (StringBuffer
!= NULL
);
2982 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
2983 L
"Submit Fail For Form: %s.",
2987 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
2989 FreePool (StringBuffer
);
2990 FreePool (FormTitle
);
2996 Popup an NO_SUBMIT_IF error info and get user input.
2998 @param TitleId The form title id.
2999 @param HiiHandle The hii handle for this package.
3001 @retval UINT32 The user select option for the save fail.
3002 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3005 ConfirmNoSubmitFail (
3006 IN EFI_STRING_ID TitleId
,
3007 IN EFI_HII_HANDLE HiiHandle
3011 CHAR16
*StringBuffer
;
3014 FormTitle
= GetToken (TitleId
, HiiHandle
);
3016 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3017 ASSERT (StringBuffer
!= NULL
);
3021 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3022 L
"NO_SUBMIT_IF error For Form: %s.",
3026 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3028 FreePool (StringBuffer
);
3029 FreePool (FormTitle
);
3035 Discard data based on the input setting scope (Form, FormSet or System).
3037 @param FormSet FormSet data structure.
3038 @param Form Form data structure.
3039 @param SettingScope Setting Scope for Discard action.
3041 @retval EFI_SUCCESS The function completed successfully.
3042 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3047 IN FORM_BROWSER_FORMSET
*FormSet
,
3048 IN FORM_BROWSER_FORM
*Form
,
3049 IN BROWSER_SETTING_SCOPE SettingScope
3053 FORMSET_STORAGE
*Storage
;
3054 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3055 FORM_BROWSER_FORMSET
*LocalFormSet
;
3056 FORM_BROWSER_FORMSET
*OldFormSet
;
3059 // Check the supported setting level.
3061 if (SettingScope
>= MaxLevel
) {
3062 return EFI_UNSUPPORTED
;
3065 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3067 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3068 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3069 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3070 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3072 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3077 // Skip if there is no RequestElement
3079 if (ConfigInfo
->ElementCount
== 0) {
3084 // Prepare <ConfigResp>
3086 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3089 // Call callback with Changed type to inform the driver.
3091 SendDiscardInfoToDriver (FormSet
, Form
);
3094 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3095 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3098 // Discard Buffer storage or Name/Value storage
3100 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3101 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3102 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3103 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3105 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3110 // Skip if there is no RequestElement
3112 if (Storage
->ElementCount
== 0) {
3116 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3119 Link
= GetFirstNode (&FormSet
->FormListHead
);
3120 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3121 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3122 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3125 // Call callback with Changed type to inform the driver.
3127 SendDiscardInfoToDriver (FormSet
, Form
);
3130 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3131 } else if (SettingScope
== SystemLevel
) {
3133 // System Level Discard.
3135 OldFormSet
= mSystemLevelFormSet
;
3138 // Discard changed value for each FormSet in the maintain list.
3140 Link
= GetFirstNode (&gBrowserFormSetList
);
3141 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3142 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3143 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3144 if (!ValidateFormSet(LocalFormSet
)) {
3148 mSystemLevelFormSet
= LocalFormSet
;
3150 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3151 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3153 // Remove maintain backup list after discard except for the current using FormSet.
3155 CleanBrowserStorage(LocalFormSet
);
3156 RemoveEntryList (&LocalFormSet
->Link
);
3157 DestroyFormSet (LocalFormSet
);
3161 mSystemLevelFormSet
= OldFormSet
;
3168 Submit data for a form.
3170 @param FormSet FormSet data structure.
3171 @param Form Form data structure.
3173 @retval EFI_SUCCESS The function completed successfully.
3174 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3179 IN FORM_BROWSER_FORMSET
*FormSet
,
3180 IN FORM_BROWSER_FORM
*Form
3185 EFI_STRING ConfigResp
;
3186 EFI_STRING Progress
;
3187 BROWSER_STORAGE
*Storage
;
3188 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3189 BOOLEAN SubmitFormFail
;
3191 SubmitFormFail
= FALSE
;
3193 if (!IsNvUpdateRequiredForForm (Form
)) {
3197 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3198 if (EFI_ERROR (Status
)) {
3202 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3203 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3204 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3205 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3207 Storage
= ConfigInfo
->Storage
;
3208 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3213 // Skip if there is no RequestElement
3215 if (ConfigInfo
->ElementCount
== 0) {
3220 // 1. Prepare <ConfigResp>
3222 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3223 if (EFI_ERROR (Status
)) {
3228 // 2. Set value to hii config routine protocol.
3230 Status
= mHiiConfigRouting
->RouteConfig (
3236 if (EFI_ERROR (Status
)) {
3238 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3240 SubmitFormFail
= TRUE
;
3241 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3242 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3243 FreePool (ConfigResp
);
3247 FreePool (ConfigResp
);
3249 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3251 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3255 // 4. Process the save failed storage.
3257 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3258 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3259 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3260 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3261 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3262 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3264 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3265 // base on the SyncConfigRequest to Sync the buffer.
3267 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3268 FreePool (ConfigInfo
->RestoreConfigRequest
);
3269 ConfigInfo
->RestoreConfigRequest
= NULL
;
3270 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3271 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3272 FreePool (ConfigInfo
->SyncConfigRequest
);
3273 ConfigInfo
->SyncConfigRequest
= NULL
;
3276 Status
= EFI_SUCCESS
;
3279 Status
= EFI_UNSUPPORTED
;
3283 // Free Form save fail list.
3285 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3286 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3287 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3288 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3293 // 5. Update the NV flag.
3295 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3298 // 6 Call callback with Submitted type to inform the driver.
3300 if (!SubmitFormFail
) {
3301 SubmitCallback (FormSet
, Form
);
3308 Submit data for a formset.
3310 @param FormSet FormSet data structure.
3311 @param SkipProcessFail Whether skip to process the save failed storage.
3312 If submit formset is called when do system level save,
3313 set this value to true and process the failed formset
3315 if submit formset is called when do formset level save,
3316 set the value to false and process the failed storage
3317 right after process all storages for this formset.
3319 @retval EFI_SUCCESS The function completed successfully.
3320 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3325 IN FORM_BROWSER_FORMSET
*FormSet
,
3326 IN BOOLEAN SkipProcessFail
3331 EFI_STRING ConfigResp
;
3332 EFI_STRING Progress
;
3333 BROWSER_STORAGE
*Storage
;
3334 FORMSET_STORAGE
*FormSetStorage
;
3335 FORM_BROWSER_FORM
*Form
;
3336 BOOLEAN HasInserted
;
3337 FORM_BROWSER_STATEMENT
*Question
;
3338 BOOLEAN SubmitFormSetFail
;
3340 HasInserted
= FALSE
;
3341 SubmitFormSetFail
= FALSE
;
3343 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3348 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3349 if (EFI_ERROR (Status
)) {
3350 if (SkipProcessFail
) {
3352 // Process NO_SUBMIT check first, so insert it at head.
3354 FormSet
->SaveFailForm
= Form
;
3355 FormSet
->SaveFailStatement
= Question
;
3356 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3365 // Submit Buffer storage or Name/Value storage
3367 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3368 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3369 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3370 Storage
= FormSetStorage
->BrowserStorage
;
3371 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3373 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3378 // Skip if there is no RequestElement
3380 if (FormSetStorage
->ElementCount
== 0) {
3385 // 1. Prepare <ConfigResp>
3387 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3388 if (EFI_ERROR (Status
)) {
3393 // 2. Send <ConfigResp> to Routine config Protocol.
3395 Status
= mHiiConfigRouting
->RouteConfig (
3400 if (EFI_ERROR (Status
)) {
3402 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3404 SubmitFormSetFail
= TRUE
;
3405 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3406 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3409 // Call submit formset for system level, save the formset info
3410 // and process later.
3412 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3413 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3414 FormSet
->SaveFailForm
= Form
;
3415 FormSet
->SaveFailStatement
= Question
;
3416 if (SkipProcessFail
) {
3417 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3422 FreePool (ConfigResp
);
3426 FreePool (ConfigResp
);
3428 // 3. Config success, update storage shadow Buffer
3430 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3434 // 4. Has save fail storage need to handle.
3437 if (!SkipProcessFail
) {
3439 // If not in system level, just handl the save failed storage here.
3441 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3442 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3443 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3444 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3445 Storage
= FormSetStorage
->BrowserStorage
;
3446 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3448 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3449 // base on the SyncConfigRequest to Sync the buffer.
3451 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3452 FreePool (FormSetStorage
->RestoreConfigRequest
);
3453 FormSetStorage
->RestoreConfigRequest
= NULL
;
3454 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3455 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3456 FreePool (FormSetStorage
->SyncConfigRequest
);
3457 FormSetStorage
->SyncConfigRequest
= NULL
;
3460 Status
= EFI_SUCCESS
;
3463 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3465 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3466 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3467 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3468 gCurrentSelection
->FormId
= Form
->FormId
;
3469 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3471 Status
= EFI_UNSUPPORTED
;
3475 // Free FormSet save fail list.
3477 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3478 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3479 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3480 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3484 // If in system level, just return error and handle the failed formset later.
3486 Status
= EFI_UNSUPPORTED
;
3491 // 5. Update the NV flag.
3493 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3496 // 6. Call callback with Submitted type to inform the driver.
3498 if (!SubmitFormSetFail
) {
3499 SubmitCallback (FormSet
, NULL
);
3506 Submit data for all formsets.
3508 @retval EFI_SUCCESS The function completed successfully.
3509 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3519 LIST_ENTRY
*StorageLink
;
3520 FORMSET_STORAGE
*FormSetStorage
;
3521 FORM_BROWSER_FORM
*Form
;
3522 FORM_BROWSER_FORMSET
*LocalFormSet
;
3523 UINT32 UserSelection
;
3524 FORM_BROWSER_STATEMENT
*Question
;
3526 mSystemSubmit
= TRUE
;
3527 Link
= GetFirstNode (&gBrowserFormSetList
);
3528 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3529 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3530 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3531 if (!ValidateFormSet(LocalFormSet
)) {
3535 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3536 if (EFI_ERROR (Status
)) {
3541 // Remove maintain backup list after save except for the current using FormSet.
3543 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3544 CleanBrowserStorage(LocalFormSet
);
3545 RemoveEntryList (&LocalFormSet
->Link
);
3546 DestroyFormSet (LocalFormSet
);
3549 mSystemSubmit
= FALSE
;
3551 Status
= EFI_SUCCESS
;
3554 // Process the save failed formsets.
3556 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3557 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3558 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3559 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3561 if (!ValidateFormSet(LocalFormSet
)) {
3565 Form
= LocalFormSet
->SaveFailForm
;
3566 Question
= LocalFormSet
->SaveFailStatement
;
3569 // Confirm with user, get user input.
3571 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3573 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3575 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3577 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3580 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3581 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3582 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3583 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3584 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3585 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3587 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3590 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3591 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3592 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3593 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3595 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3596 // base on the SyncConfigRequest to Sync the buffer.
3598 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3599 FreePool (FormSetStorage
->RestoreConfigRequest
);
3600 FormSetStorage
->RestoreConfigRequest
= NULL
;
3601 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3602 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3603 FreePool (FormSetStorage
->SyncConfigRequest
);
3604 FormSetStorage
->SyncConfigRequest
= NULL
;
3609 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3610 CleanBrowserStorage(LocalFormSet
);
3611 RemoveEntryList (&LocalFormSet
->Link
);
3612 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3613 DestroyFormSet (LocalFormSet
);
3615 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3618 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3619 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3622 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3624 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3625 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3626 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3627 gCurrentSelection
->FormId
= Form
->FormId
;
3628 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3630 Status
= EFI_UNSUPPORTED
;
3636 // Clean the list which will not process.
3638 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3639 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3640 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3641 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3643 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3644 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3645 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3646 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3654 Submit data based on the input Setting level (Form, FormSet or System).
3656 @param FormSet FormSet data structure.
3657 @param Form Form data structure.
3658 @param SettingScope Setting Scope for Submit action.
3660 @retval EFI_SUCCESS The function completed successfully.
3661 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3666 IN FORM_BROWSER_FORMSET
*FormSet
,
3667 IN FORM_BROWSER_FORM
*Form
,
3668 IN BROWSER_SETTING_SCOPE SettingScope
3673 switch (SettingScope
) {
3675 Status
= SubmitForForm(FormSet
, Form
);
3679 Status
= SubmitForFormSet (FormSet
, FALSE
);
3683 Status
= SubmitForSystem ();
3687 Status
= EFI_UNSUPPORTED
;
3695 Converts the unicode character of the string from uppercase to lowercase.
3696 This is a internal function.
3698 @param ConfigString String to be converted
3704 IN EFI_STRING ConfigString
3710 ASSERT (ConfigString
!= NULL
);
3713 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3715 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3716 if (*String
== L
'=') {
3718 } else if (*String
== L
'&') {
3720 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3721 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3727 Find the point in the ConfigResp string for this question.
3729 @param Question The question.
3730 @param ConfigResp Get ConfigResp string.
3732 @retval point to the offset where is for this question.
3736 GetOffsetFromConfigResp (
3737 IN FORM_BROWSER_STATEMENT
*Question
,
3738 IN CHAR16
*ConfigResp
3741 CHAR16
*RequestElement
;
3745 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3747 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3748 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3749 if (RequestElement
!= NULL
) {
3751 // Skip the "VariableName=" field.
3753 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3756 return RequestElement
;
3760 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3764 // Convert all hex digits in ConfigResp to lower case before searching.
3766 HiiToLower (ConfigResp
);
3769 // 1. Directly use Question->BlockName to find.
3771 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3772 if (RequestElement
!= NULL
) {
3774 // Skip the "Question->BlockName&VALUE=" field.
3776 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3777 return RequestElement
;
3781 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3783 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3784 ASSERT (BlockData
!= NULL
);
3785 HiiToLower (BlockData
);
3786 RequestElement
= StrStr (ConfigResp
, BlockData
);
3787 FreePool (BlockData
);
3789 if (RequestElement
!= NULL
) {
3791 // Skip the "Question->BlockName&VALUE=" field.
3793 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3796 return RequestElement
;
3800 Get Question default value from AltCfg string.
3802 @param FormSet The form set.
3803 @param Form The form
3804 @param Question The question.
3806 @retval EFI_SUCCESS Question is reset to default value.
3810 GetDefaultValueFromAltCfg (
3811 IN FORM_BROWSER_FORMSET
*FormSet
,
3812 IN FORM_BROWSER_FORM
*Form
,
3813 IN OUT FORM_BROWSER_STATEMENT
*Question
3816 BROWSER_STORAGE
*Storage
;
3817 FORMSET_STORAGE
*FormSetStorage
;
3821 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3823 Storage
= Question
->Storage
;
3824 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3825 return EFI_NOT_FOUND
;
3829 // Try to get AltCfg string from form. If not found it, then
3830 // try to get it from formset.
3833 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3834 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3835 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3836 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3838 if (Storage
== ConfigInfo
->Storage
) {
3839 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3844 if (ConfigResp
== NULL
) {
3845 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3846 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3847 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3848 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3850 if (Storage
== FormSetStorage
->BrowserStorage
) {
3851 ConfigResp
= FormSetStorage
->ConfigAltResp
;
3857 if (ConfigResp
== NULL
) {
3858 return EFI_NOT_FOUND
;
3861 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
3862 if (Value
== NULL
) {
3863 return EFI_NOT_FOUND
;
3866 return BufferToValue (Question
, Value
);
3870 Get default Id value used for browser.
3872 @param DefaultId The default id value used by hii.
3874 @retval Browser used default value.
3878 GetDefaultIdForCallBack (
3882 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
3883 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
3884 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3885 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3886 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3887 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3888 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3889 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3890 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3891 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3892 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3893 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3902 Return data element in an Array by its Index.
3904 @param Array The data array.
3905 @param Type Type of the data in this array.
3906 @param Index Zero based index for data in this array.
3908 @retval Value The data to be returned
3920 ASSERT (Array
!= NULL
);
3924 case EFI_IFR_TYPE_NUM_SIZE_8
:
3925 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3928 case EFI_IFR_TYPE_NUM_SIZE_16
:
3929 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3932 case EFI_IFR_TYPE_NUM_SIZE_32
:
3933 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3936 case EFI_IFR_TYPE_NUM_SIZE_64
:
3937 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3949 Set value of a data element in an Array by its Index.
3951 @param Array The data array.
3952 @param Type Type of the data in this array.
3953 @param Index Zero based index for data in this array.
3954 @param Value The value to be set.
3966 ASSERT (Array
!= NULL
);
3969 case EFI_IFR_TYPE_NUM_SIZE_8
:
3970 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3973 case EFI_IFR_TYPE_NUM_SIZE_16
:
3974 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3977 case EFI_IFR_TYPE_NUM_SIZE_32
:
3978 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3981 case EFI_IFR_TYPE_NUM_SIZE_64
:
3982 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3991 Search an Option of a Question by its value.
3993 @param Question The Question
3994 @param OptionValue Value for Option to be searched.
3996 @retval Pointer Pointer to the found Option.
3997 @retval NULL Option not found.
4002 IN FORM_BROWSER_STATEMENT
*Question
,
4003 IN EFI_HII_VALUE
*OptionValue
4007 QUESTION_OPTION
*Option
;
4010 Link
= GetFirstNode (&Question
->OptionListHead
);
4011 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4012 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4014 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4016 // Check the suppressif condition, only a valid option can be return.
4018 if ((Option
->SuppressExpression
== NULL
) ||
4019 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4024 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4032 Reset Question to its default value.
4034 @param FormSet The form set.
4035 @param Form The form.
4036 @param Question The question.
4037 @param DefaultId The Class of the default.
4039 @retval EFI_SUCCESS Question is reset to default value.
4043 GetQuestionDefault (
4044 IN FORM_BROWSER_FORMSET
*FormSet
,
4045 IN FORM_BROWSER_FORM
*Form
,
4046 IN FORM_BROWSER_STATEMENT
*Question
,
4052 QUESTION_DEFAULT
*Default
;
4053 QUESTION_OPTION
*Option
;
4054 EFI_HII_VALUE
*HiiValue
;
4056 EFI_STRING StrValue
;
4057 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4058 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4061 EFI_IFR_TYPE_VALUE
*TypeValue
;
4062 UINT16 OriginalDefaultId
;
4063 FORMSET_DEFAULTSTORE
*DefaultStore
;
4064 LIST_ENTRY
*DefaultLink
;
4066 Status
= EFI_NOT_FOUND
;
4068 OriginalDefaultId
= DefaultId
;
4069 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4072 // Statement don't have storage, skip them
4074 if (Question
->QuestionId
== 0) {
4079 // There are Five ways to specify default value for a Question:
4080 // 1, use call back function (highest priority)
4081 // 2, use ExtractConfig function
4082 // 3, use nested EFI_IFR_DEFAULT
4083 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4084 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4087 HiiValue
= &Question
->HiiValue
;
4088 TypeValue
= &HiiValue
->Value
;
4089 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4091 // For orderedlist, need to pass the BufferValue to Callback function.
4093 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4097 // Get Question defaut value from call back function.
4099 ConfigAccess
= FormSet
->ConfigAccess
;
4100 Action
= GetDefaultIdForCallBack (DefaultId
);
4101 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4102 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4103 Status
= ConfigAccess
->Callback (
4106 Question
->QuestionId
,
4111 if (!EFI_ERROR (Status
)) {
4112 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4113 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4114 ASSERT (NewString
!= NULL
);
4116 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4117 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4118 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4119 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4121 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4124 FreePool (NewString
);
4131 // Get default value from altcfg string.
4133 if (ConfigAccess
!= NULL
) {
4134 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4135 if (!EFI_ERROR (Status
)) {
4141 // EFI_IFR_DEFAULT has highest priority
4143 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4144 Link
= GetFirstNode (&Question
->DefaultListHead
);
4145 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4146 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4148 if (Default
->DefaultId
== DefaultId
) {
4149 if (Default
->ValueExpression
!= NULL
) {
4151 // Default is provided by an Expression, evaluate it
4153 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4154 if (EFI_ERROR (Status
)) {
4158 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4159 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4160 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4161 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4162 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4164 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4165 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4167 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4169 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4170 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4173 // Default value is embedded in EFI_IFR_DEFAULT
4175 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4176 ASSERT (HiiValue
->Buffer
!= NULL
);
4177 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4179 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4183 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4184 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4185 if (StrValue
== NULL
) {
4186 return EFI_NOT_FOUND
;
4188 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4189 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4190 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4192 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4199 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4204 // EFI_ONE_OF_OPTION
4206 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4207 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4209 // OneOfOption could only provide Standard and Manufacturing default
4211 Link
= GetFirstNode (&Question
->OptionListHead
);
4212 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4213 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4214 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4216 if ((Option
->SuppressExpression
!= NULL
) &&
4217 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4221 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4222 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4224 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4233 // EFI_IFR_CHECKBOX - lowest priority
4235 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4236 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4238 // Checkbox could only provide Standard and Manufacturing default
4240 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4241 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4243 HiiValue
->Value
.b
= TRUE
;
4251 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4252 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4253 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4255 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4256 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4257 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4258 DefaultId
= DefaultStore
->DefaultId
;
4259 if (DefaultId
== OriginalDefaultId
) {
4266 // For Questions without default value for all the default id in the DefaultStoreList.
4268 Status
= EFI_NOT_FOUND
;
4269 switch (Question
->Operand
) {
4270 case EFI_IFR_CHECKBOX_OP
:
4271 HiiValue
->Value
.b
= FALSE
;
4272 Status
= EFI_SUCCESS
;
4275 case EFI_IFR_NUMERIC_OP
:
4277 // Take minimum value as numeric default value
4279 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4281 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4283 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4284 case EFI_IFR_NUMERIC_SIZE_1
:
4285 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4286 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4287 Status
= EFI_SUCCESS
;
4290 case EFI_IFR_NUMERIC_SIZE_2
:
4291 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4292 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4293 Status
= EFI_SUCCESS
;
4296 case EFI_IFR_NUMERIC_SIZE_4
:
4297 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4298 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4299 Status
= EFI_SUCCESS
;
4302 case EFI_IFR_NUMERIC_SIZE_8
:
4303 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4304 HiiValue
->Value
.u64
= Question
->Minimum
;
4305 Status
= EFI_SUCCESS
;
4312 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4313 HiiValue
->Value
.u64
= Question
->Minimum
;
4314 Status
= EFI_SUCCESS
;
4319 case EFI_IFR_ONE_OF_OP
:
4321 // Take first oneof option as oneof's default value
4323 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4324 Link
= GetFirstNode (&Question
->OptionListHead
);
4325 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4326 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4327 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4329 if ((Option
->SuppressExpression
!= NULL
) &&
4330 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4334 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4335 Status
= EFI_SUCCESS
;
4341 case EFI_IFR_ORDERED_LIST_OP
:
4343 // Take option sequence in IFR as ordered list's default value
4346 Link
= GetFirstNode (&Question
->OptionListHead
);
4347 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4348 Status
= EFI_SUCCESS
;
4349 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4350 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4352 if ((Option
->SuppressExpression
!= NULL
) &&
4353 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4357 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4360 if (Index
>= Question
->MaxContainers
) {
4374 Get AltCfg string for current form.
4376 @param FormSet Form data structure.
4377 @param Form Form data structure.
4378 @param DefaultId The Class of the default.
4379 @param BrowserStorage The input request storage for the questions.
4383 ExtractAltCfgForForm (
4384 IN FORM_BROWSER_FORMSET
*FormSet
,
4385 IN FORM_BROWSER_FORM
*Form
,
4386 IN UINT16 DefaultId
,
4387 IN BROWSER_STORAGE
*BrowserStorage
4395 BROWSER_STORAGE
*Storage
;
4396 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4397 FORMSET_STORAGE
*FormSetStorage
;
4400 // Check whether has get AltCfg string for this formset.
4401 // If yes, no need to get AltCfg for form.
4403 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4404 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4405 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4406 Storage
= FormSetStorage
->BrowserStorage
;
4407 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4408 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4412 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4413 FormSetStorage
->ElementCount
!= 0 &&
4414 FormSetStorage
->HasCallAltCfg
) {
4420 // Get AltCfg string for each form.
4422 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4423 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4424 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4425 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4427 Storage
= ConfigInfo
->Storage
;
4428 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4432 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4437 // 1. Skip if there is no RequestElement
4439 if (ConfigInfo
->ElementCount
== 0) {
4444 // 2. Get value through hii config routine protocol.
4446 Status
= mHiiConfigRouting
->ExtractConfig (
4448 ConfigInfo
->ConfigRequest
,
4452 if (EFI_ERROR (Status
)) {
4457 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4458 // Get the default configuration string according to the default ID.
4460 Status
= mHiiConfigRouting
->GetAltConfig (
4466 &DefaultId
, // it can be NULL to get the current setting.
4470 if (EFI_ERROR (Status
)) {
4474 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4479 Clean AltCfg string for current form.
4481 @param Form Form data structure.
4485 CleanAltCfgForForm (
4486 IN FORM_BROWSER_FORM
*Form
4490 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4492 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4493 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4494 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4495 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4497 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4498 FreePool (ConfigInfo
->ConfigAltResp
);
4499 ConfigInfo
->ConfigAltResp
= NULL
;
4505 Get AltCfg string for current formset.
4507 @param FormSet Form data structure.
4508 @param DefaultId The Class of the default.
4509 @param BrowserStorage The input request storage for the questions.
4513 ExtractAltCfgForFormSet (
4514 IN FORM_BROWSER_FORMSET
*FormSet
,
4515 IN UINT16 DefaultId
,
4516 IN BROWSER_STORAGE
*BrowserStorage
4524 BROWSER_STORAGE
*Storage
;
4525 FORMSET_STORAGE
*FormSetStorage
;
4527 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4528 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4529 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4530 Storage
= FormSetStorage
->BrowserStorage
;
4531 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4533 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4537 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4542 // 1. Skip if there is no RequestElement
4544 if (FormSetStorage
->ElementCount
== 0) {
4548 FormSetStorage
->HasCallAltCfg
= TRUE
;
4551 // 2. Get value through hii config routine protocol.
4553 Status
= mHiiConfigRouting
->ExtractConfig (
4555 FormSetStorage
->ConfigRequest
,
4559 if (EFI_ERROR (Status
)) {
4564 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4565 // Get the default configuration string according to the default ID.
4567 Status
= mHiiConfigRouting
->GetAltConfig (
4573 &DefaultId
, // it can be NULL to get the current setting.
4578 if (EFI_ERROR (Status
)) {
4582 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4588 Clean AltCfg string for current formset.
4590 @param FormSet Form data structure.
4594 CleanAltCfgForFormSet (
4595 IN FORM_BROWSER_FORMSET
*FormSet
4599 FORMSET_STORAGE
*FormSetStorage
;
4601 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4602 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4603 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4604 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4606 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4607 FreePool (FormSetStorage
->ConfigAltResp
);
4608 FormSetStorage
->ConfigAltResp
= NULL
;
4611 FormSetStorage
->HasCallAltCfg
= FALSE
;
4616 Reset Questions to their initial value or default value in a Form, Formset or System.
4618 GetDefaultValueScope parameter decides which questions will reset
4619 to its default value.
4621 @param FormSet FormSet data structure.
4622 @param Form Form data structure.
4623 @param DefaultId The Class of the default.
4624 @param SettingScope Setting Scope for Default action.
4625 @param GetDefaultValueScope Get default value scope.
4626 @param Storage Get default value only for this storage.
4627 @param RetrieveValueFirst Whether call the retrieve call back to
4628 get the initial value before get default
4630 @param SkipGetAltCfg Whether skip the get altcfg string process.
4632 @retval EFI_SUCCESS The function completed successfully.
4633 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4638 IN FORM_BROWSER_FORMSET
*FormSet
,
4639 IN FORM_BROWSER_FORM
*Form
,
4640 IN UINT16 DefaultId
,
4641 IN BROWSER_SETTING_SCOPE SettingScope
,
4642 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4643 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4644 IN BOOLEAN RetrieveValueFirst
,
4645 IN BOOLEAN SkipGetAltCfg
4649 LIST_ENTRY
*FormLink
;
4651 FORM_BROWSER_STATEMENT
*Question
;
4652 FORM_BROWSER_FORMSET
*LocalFormSet
;
4653 FORM_BROWSER_FORMSET
*OldFormSet
;
4655 Status
= EFI_SUCCESS
;
4658 // Check the supported setting level.
4660 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4661 return EFI_UNSUPPORTED
;
4664 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4665 return EFI_UNSUPPORTED
;
4668 if (SettingScope
== FormLevel
) {
4670 // Prepare the AltCfg String for form.
4672 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4673 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4677 // Extract Form default
4679 Link
= GetFirstNode (&Form
->StatementListHead
);
4680 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4681 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4682 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4685 // If get default value only for this storage, check the storage first.
4687 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4692 // If get default value only for no storage question, just skip the question which has storage.
4694 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4699 // If Question is disabled, don't reset it to default
4701 if (Question
->Expression
!= NULL
) {
4702 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4707 if (RetrieveValueFirst
) {
4709 // Call the Retrieve call back to get the initial question value.
4711 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4715 // If not request to get the initial value or get initial value fail, then get default value.
4717 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4718 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4719 if (EFI_ERROR (Status
)) {
4725 // Synchronize Buffer storage's Edit buffer
4727 if ((Question
->Storage
!= NULL
) &&
4728 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4729 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4734 // Clean the AltCfg String.
4736 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4737 CleanAltCfgForForm(Form
);
4739 } else if (SettingScope
== FormSetLevel
) {
4741 // Prepare the AltCfg String for formset.
4743 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4744 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4747 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4748 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4749 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4750 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4751 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4755 // Clean the AltCfg String.
4757 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4758 CleanAltCfgForFormSet (FormSet
);
4760 } else if (SettingScope
== SystemLevel
) {
4762 // Preload all Hii formset.
4764 LoadAllHiiFormset();
4766 OldFormSet
= mSystemLevelFormSet
;
4769 // Set Default Value for each FormSet in the maintain list.
4771 Link
= GetFirstNode (&gBrowserFormSetList
);
4772 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4773 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4774 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4775 if (!ValidateFormSet(LocalFormSet
)) {
4779 mSystemLevelFormSet
= LocalFormSet
;
4781 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4784 mSystemLevelFormSet
= OldFormSet
;
4792 Validate whether this question's value has changed.
4794 @param FormSet FormSet data structure.
4795 @param Form Form data structure.
4796 @param Question Question to be initialized.
4797 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4799 @retval TRUE Question's value has changed.
4800 @retval FALSE Question's value has not changed
4804 IsQuestionValueChanged (
4805 IN FORM_BROWSER_FORMSET
*FormSet
,
4806 IN FORM_BROWSER_FORM
*Form
,
4807 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4808 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4811 EFI_HII_VALUE BackUpValue
;
4812 CHAR8
*BackUpBuffer
;
4813 EFI_HII_VALUE BackUpValue2
;
4814 CHAR8
*BackUpBuffer2
;
4816 BOOLEAN ValueChanged
;
4820 // For quetion without storage, always mark it as data not changed.
4822 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4826 BackUpBuffer
= NULL
;
4827 BackUpBuffer2
= NULL
;
4828 ValueChanged
= FALSE
;
4830 switch (Question
->Operand
) {
4831 case EFI_IFR_ORDERED_LIST_OP
:
4832 BufferWidth
= Question
->StorageWidth
;
4833 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4834 ASSERT (BackUpBuffer
!= NULL
);
4837 case EFI_IFR_STRING_OP
:
4838 case EFI_IFR_PASSWORD_OP
:
4839 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4840 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4841 ASSERT (BackUpBuffer
!= NULL
);
4848 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4850 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
4851 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4852 ASSERT_EFI_ERROR(Status
);
4854 switch (Question
->Operand
) {
4855 case EFI_IFR_ORDERED_LIST_OP
:
4856 BufferWidth
= Question
->StorageWidth
;
4857 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4858 ASSERT (BackUpBuffer2
!= NULL
);
4861 case EFI_IFR_STRING_OP
:
4862 case EFI_IFR_PASSWORD_OP
:
4863 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4864 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4865 ASSERT (BackUpBuffer2
!= NULL
);
4872 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
4874 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
4875 ASSERT_EFI_ERROR(Status
);
4877 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4878 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
4879 ValueChanged
= TRUE
;
4882 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
4883 ASSERT_EFI_ERROR(Status
);
4885 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
4886 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
4887 ValueChanged
= TRUE
;
4891 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
4892 if (BackUpBuffer
!= NULL
) {
4893 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
4894 FreePool (BackUpBuffer
);
4897 if (BackUpBuffer2
!= NULL
) {
4898 FreePool (BackUpBuffer2
);
4901 Question
->ValueChanged
= ValueChanged
;
4903 return ValueChanged
;
4907 Initialize Question's Edit copy from Storage.
4909 @param Selection Selection contains the information about
4910 the Selection, form and formset to be displayed.
4911 Selection action may be updated in retrieve callback.
4912 If Selection is NULL, only initialize Question value.
4913 @param FormSet FormSet data structure.
4914 @param Form Form data structure.
4916 @retval EFI_SUCCESS The function completed successfully.
4921 IN OUT UI_MENU_SELECTION
*Selection
,
4922 IN FORM_BROWSER_FORMSET
*FormSet
,
4923 IN FORM_BROWSER_FORM
*Form
4928 FORM_BROWSER_STATEMENT
*Question
;
4930 Link
= GetFirstNode (&Form
->StatementListHead
);
4931 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4932 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4935 // Initialize local copy of Value for each Question
4937 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
4938 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
4940 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4942 if (EFI_ERROR (Status
)) {
4946 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
4947 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
4950 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4957 Initialize Question's Edit copy from Storage for the whole Formset.
4959 @param Selection Selection contains the information about
4960 the Selection, form and formset to be displayed.
4961 Selection action may be updated in retrieve callback.
4962 If Selection is NULL, only initialize Question value.
4963 @param FormSet FormSet data structure.
4965 @retval EFI_SUCCESS The function completed successfully.
4970 IN OUT UI_MENU_SELECTION
*Selection
,
4971 IN FORM_BROWSER_FORMSET
*FormSet
4976 FORM_BROWSER_FORM
*Form
;
4978 Link
= GetFirstNode (&FormSet
->FormListHead
);
4979 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
4980 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4983 // Initialize local copy of Value for each Form
4985 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
4986 if (EFI_ERROR (Status
)) {
4990 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
4994 // Finished question initialization.
4996 FormSet
->QuestionInited
= TRUE
;
5002 Remove the Request element from the Config Request.
5004 @param Storage Pointer to the browser storage.
5005 @param RequestElement The pointer to the Request element.
5010 IN OUT BROWSER_STORAGE
*Storage
,
5011 IN CHAR16
*RequestElement
5017 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5019 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5021 if (NewStr
== NULL
) {
5026 // Remove this element from this ConfigRequest.
5029 NewStr
+= StrLen (RequestElement
);
5030 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5032 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5036 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5038 @param Storage Pointer to the formset storage.
5039 @param ConfigRequest The pointer to the Request element.
5043 RemoveConfigRequest (
5044 FORMSET_STORAGE
*Storage
,
5045 CHAR16
*ConfigRequest
5048 CHAR16
*RequestElement
;
5049 CHAR16
*NextRequestElement
;
5053 // No request element in it, just return.
5055 if (ConfigRequest
== NULL
) {
5059 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5061 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5066 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5068 SearchKey
= L
"&OFFSET";
5072 // Find SearchKey storage
5074 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5075 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5076 ASSERT (RequestElement
!= NULL
);
5077 RequestElement
= StrStr (RequestElement
, SearchKey
);
5079 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5082 while (RequestElement
!= NULL
) {
5084 // +1 to avoid find header itself.
5086 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5089 // The last Request element in configRequest string.
5091 if (NextRequestElement
!= NULL
) {
5093 // Replace "&" with '\0'.
5095 *NextRequestElement
= L
'\0';
5098 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5100 if (NextRequestElement
!= NULL
) {
5102 // Restore '&' with '\0' for later used.
5104 *NextRequestElement
= L
'&';
5107 RequestElement
= NextRequestElement
;
5111 // If no request element remain, just remove the ConfigRequest string.
5113 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5114 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5115 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5116 Storage
->BrowserStorage
->SpareStrLen
= 0;
5121 Base on the current formset info, clean the ConfigRequest string in browser storage.
5123 @param FormSet Pointer of the FormSet
5127 CleanBrowserStorage (
5128 IN OUT FORM_BROWSER_FORMSET
*FormSet
5132 FORMSET_STORAGE
*Storage
;
5134 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5135 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5136 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5137 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5139 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5140 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5144 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5145 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5146 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5147 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5148 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5149 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5151 Storage
->BrowserStorage
->Initialized
= FALSE
;
5157 Check whether current element in the ConfigReqeust string.
5159 @param BrowserStorage Storage which includes ConfigReqeust.
5160 @param RequestElement New element need to check.
5162 @retval TRUE The Element is in the ConfigReqeust string.
5163 @retval FALSE The Element not in the configReqeust String.
5168 BROWSER_STORAGE
*BrowserStorage
,
5169 CHAR16
*RequestElement
5172 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5176 Append the Request element to the Config Request.
5178 @param ConfigRequest Current ConfigRequest info.
5179 @param SpareStrLen Current remain free buffer for config reqeust.
5180 @param RequestElement New Request element.
5184 AppendConfigRequest (
5185 IN OUT CHAR16
**ConfigRequest
,
5186 IN OUT UINTN
*SpareStrLen
,
5187 IN CHAR16
*RequestElement
5195 StrLength
= StrLen (RequestElement
);
5196 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5197 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5200 // Append <RequestElement> to <ConfigRequest>
5202 if (StrLength
> *SpareStrLen
) {
5204 // Old String buffer is not sufficient for RequestElement, allocate a new one
5206 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5207 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5208 ASSERT (NewStr
!= NULL
);
5210 if (*ConfigRequest
!= NULL
) {
5211 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5212 FreePool (*ConfigRequest
);
5214 *ConfigRequest
= NewStr
;
5215 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5218 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5219 *SpareStrLen
-= StrLength
;
5223 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5225 @param Storage Form set Storage.
5226 @param Request The input request string.
5227 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5229 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5230 @retval FALSE All elements covered by current used elements.
5234 ConfigRequestAdjust (
5235 IN BROWSER_STORAGE
*Storage
,
5237 IN BOOLEAN RespString
5240 CHAR16
*RequestElement
;
5241 CHAR16
*NextRequestElement
;
5242 CHAR16
*NextElementBakup
;
5246 CHAR16
*ConfigRequest
;
5249 NextElementBakup
= NULL
;
5252 if (Request
!= NULL
) {
5253 ConfigRequest
= Request
;
5255 ConfigRequest
= Storage
->ConfigRequest
;
5258 if (Storage
->ConfigRequest
== NULL
) {
5259 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5263 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5265 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5270 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5272 SearchKey
= L
"&OFFSET";
5273 ValueKey
= L
"&VALUE";
5277 // Find SearchKey storage
5279 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5280 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5281 ASSERT (RequestElement
!= NULL
);
5282 RequestElement
= StrStr (RequestElement
, SearchKey
);
5284 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5287 while (RequestElement
!= NULL
) {
5290 // +1 to avoid find header itself.
5292 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5295 // The last Request element in configRequest string.
5297 if (NextRequestElement
!= NULL
) {
5298 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5299 NextElementBakup
= NextRequestElement
;
5300 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5301 ASSERT (NextRequestElement
!= NULL
);
5304 // Replace "&" with '\0'.
5306 *NextRequestElement
= L
'\0';
5308 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5309 NextElementBakup
= NextRequestElement
;
5310 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5311 ASSERT (NextRequestElement
!= NULL
);
5313 // Replace "&" with '\0'.
5315 *NextRequestElement
= L
'\0';
5319 if (!ElementValidation (Storage
, RequestElement
)) {
5321 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5323 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5327 if (NextRequestElement
!= NULL
) {
5329 // Restore '&' with '\0' for later used.
5331 *NextRequestElement
= L
'&';
5334 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5335 RequestElement
= NextElementBakup
;
5337 RequestElement
= NextRequestElement
;
5345 Fill storage's edit copy with settings requested from Configuration Driver.
5347 @param FormSet FormSet data structure.
5348 @param Storage Buffer Storage.
5353 IN FORM_BROWSER_FORMSET
*FormSet
,
5354 IN FORMSET_STORAGE
*Storage
5358 EFI_STRING Progress
;
5361 EFI_STRING ConfigRequest
;
5364 ConfigRequest
= NULL
;
5366 switch (Storage
->BrowserStorage
->Type
) {
5367 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5370 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5371 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5372 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5377 case EFI_HII_VARSTORE_BUFFER
:
5378 case EFI_HII_VARSTORE_NAME_VALUE
:
5380 // Skip if there is no RequestElement.
5382 if (Storage
->ElementCount
== 0) {
5387 // Just update the ConfigRequest, if storage already initialized.
5389 if (Storage
->BrowserStorage
->Initialized
) {
5390 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5394 Storage
->BrowserStorage
->Initialized
= TRUE
;
5401 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5403 // Create the config request string to get all fields for this storage.
5404 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5405 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5407 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5408 ConfigRequest
= AllocateZeroPool (StrLen
);
5409 ASSERT (ConfigRequest
!= NULL
);
5413 L
"%s&OFFSET=0&WIDTH=%04x",
5415 Storage
->BrowserStorage
->Size
);
5417 ConfigRequest
= Storage
->ConfigRequest
;
5421 // Request current settings from Configuration Driver
5423 Status
= mHiiConfigRouting
->ExtractConfig (
5431 // If get value fail, extract default from IFR binary
5433 if (EFI_ERROR (Status
)) {
5434 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5437 // Convert Result from <ConfigAltResp> to <ConfigResp>
5439 StrPtr
= StrStr (Result
, L
"&GUID=");
5440 if (StrPtr
!= NULL
) {
5444 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5448 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5451 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5453 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5455 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5456 if (ConfigRequest
!= NULL
) {
5457 FreePool (ConfigRequest
);
5463 Get Value changed status from old question.
5465 @param NewFormSet FormSet data structure.
5466 @param OldQuestion Old question which has value changed.
5470 SyncStatusForQuestion (
5471 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5472 IN FORM_BROWSER_STATEMENT
*OldQuestion
5476 LIST_ENTRY
*QuestionLink
;
5477 FORM_BROWSER_FORM
*Form
;
5478 FORM_BROWSER_STATEMENT
*Question
;
5481 // For each form in one formset.
5483 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5484 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5485 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5486 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5489 // for each question in one form.
5491 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5492 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5493 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5494 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5496 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5497 Question
->ValueChanged
= TRUE
;
5505 Get Value changed status from old formset.
5507 @param NewFormSet FormSet data structure.
5508 @param OldFormSet FormSet data structure.
5512 SyncStatusForFormSet (
5513 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5514 IN FORM_BROWSER_FORMSET
*OldFormSet
5518 LIST_ENTRY
*QuestionLink
;
5519 FORM_BROWSER_FORM
*Form
;
5520 FORM_BROWSER_STATEMENT
*Question
;
5523 // For each form in one formset.
5525 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5526 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5527 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5528 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5531 // for each question in one form.
5533 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5534 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5535 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5536 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5538 if (!Question
->ValueChanged
) {
5543 // Find the same question in new formset and update the value changed flag.
5545 SyncStatusForQuestion (NewFormSet
, Question
);
5551 Get current setting of Questions.
5553 @param FormSet FormSet data structure.
5557 InitializeCurrentSetting (
5558 IN OUT FORM_BROWSER_FORMSET
*FormSet
5562 FORMSET_STORAGE
*Storage
;
5563 FORM_BROWSER_FORMSET
*OldFormSet
;
5566 // Try to find pre FormSet in the maintain backup list.
5567 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5569 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5570 if (OldFormSet
!= NULL
) {
5571 SyncStatusForFormSet (FormSet
, OldFormSet
);
5572 RemoveEntryList (&OldFormSet
->Link
);
5573 DestroyFormSet (OldFormSet
);
5575 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5578 // Extract default from IFR binary for no storage questions.
5580 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5583 // Request current settings from Configuration Driver
5585 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5586 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5587 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5589 LoadStorage (FormSet
, Storage
);
5591 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5597 Fetch the Ifr binary data of a FormSet.
5599 @param Handle PackageList Handle
5600 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5601 specified (NULL or zero GUID), take the first
5602 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5603 found in package list.
5604 On output, GUID of the formset found(if not NULL).
5605 @param BinaryLength The length of the FormSet IFR binary.
5606 @param BinaryData The buffer designed to receive the FormSet.
5608 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5609 BufferLength was updated.
5610 @retval EFI_INVALID_PARAMETER The handle is unknown.
5611 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5612 be found with the requested FormId.
5617 IN EFI_HII_HANDLE Handle
,
5618 IN OUT EFI_GUID
*FormSetGuid
,
5619 OUT UINTN
*BinaryLength
,
5620 OUT UINT8
**BinaryData
5624 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5630 UINT32 PackageListLength
;
5631 EFI_HII_PACKAGE_HEADER PackageHeader
;
5633 UINT8 NumberOfClassGuid
;
5634 BOOLEAN ClassGuidMatch
;
5635 EFI_GUID
*ClassGuid
;
5636 EFI_GUID
*ComparingGuid
;
5640 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5643 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5645 if (FormSetGuid
== NULL
) {
5646 ComparingGuid
= &gZeroGuid
;
5648 ComparingGuid
= FormSetGuid
;
5652 // Get HII PackageList
5655 HiiPackageList
= NULL
;
5656 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5657 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5658 HiiPackageList
= AllocatePool (BufferSize
);
5659 ASSERT (HiiPackageList
!= NULL
);
5661 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5663 if (EFI_ERROR (Status
)) {
5666 ASSERT (HiiPackageList
!= NULL
);
5669 // Get Form package from this HII package List
5671 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5673 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5675 ClassGuidMatch
= FALSE
;
5676 while (Offset
< PackageListLength
) {
5677 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5678 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5680 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5682 // Search FormSet in this Form Package
5684 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5685 while (Offset2
< PackageHeader
.Length
) {
5686 OpCodeData
= Package
+ Offset2
;
5688 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5690 // Try to compare against formset GUID
5692 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
5693 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5697 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5699 // Try to compare against formset class GUID
5701 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5702 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5703 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5704 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5705 ClassGuidMatch
= TRUE
;
5709 if (ClassGuidMatch
) {
5712 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5713 ClassGuidMatch
= TRUE
;
5718 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5721 if (Offset2
< PackageHeader
.Length
) {
5723 // Target formset found
5729 Offset
+= PackageHeader
.Length
;
5732 if (Offset
>= PackageListLength
) {
5734 // Form package not found in this Package List
5736 FreePool (HiiPackageList
);
5737 return EFI_NOT_FOUND
;
5740 if (FormSetGuid
!= NULL
) {
5742 // Return the FormSet GUID
5744 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5748 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5749 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5750 // of the Form Package.
5752 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5753 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5755 FreePool (HiiPackageList
);
5757 if (*BinaryData
== NULL
) {
5758 return EFI_OUT_OF_RESOURCES
;
5766 Initialize the internal data structure of a FormSet.
5768 @param Handle PackageList Handle
5769 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5770 specified (NULL or zero GUID), take the first
5771 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5772 found in package list.
5773 On output, GUID of the formset found(if not NULL).
5774 @param FormSet FormSet data structure.
5776 @retval EFI_SUCCESS The function completed successfully.
5777 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5782 IN EFI_HII_HANDLE Handle
,
5783 IN OUT EFI_GUID
*FormSetGuid
,
5784 OUT FORM_BROWSER_FORMSET
*FormSet
5788 EFI_HANDLE DriverHandle
;
5790 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5791 if (EFI_ERROR (Status
)) {
5795 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5796 FormSet
->HiiHandle
= Handle
;
5797 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5798 FormSet
->QuestionInited
= FALSE
;
5801 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5803 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5804 if (EFI_ERROR (Status
)) {
5807 FormSet
->DriverHandle
= DriverHandle
;
5808 Status
= gBS
->HandleProtocol (
5810 &gEfiHiiConfigAccessProtocolGuid
,
5811 (VOID
**) &FormSet
->ConfigAccess
5813 if (EFI_ERROR (Status
)) {
5815 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5816 // list, then there will be no configuration action required
5818 FormSet
->ConfigAccess
= NULL
;
5822 // Parse the IFR binary OpCodes
5824 Status
= ParseOpCodes (FormSet
);
5831 Save globals used by previous call to SendForm(). SendForm() may be called from
5832 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5833 So, save globals of previous call to SendForm() and restore them upon exit.
5837 SaveBrowserContext (
5841 BROWSER_CONTEXT
*Context
;
5842 FORM_ENTRY_INFO
*MenuList
;
5843 FORM_BROWSER_FORMSET
*FormSet
;
5845 gBrowserContextCount
++;
5846 if (gBrowserContextCount
== 1) {
5848 // This is not reentry of SendForm(), no context to save
5853 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
5854 ASSERT (Context
!= NULL
);
5856 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
5859 // Save FormBrowser context
5861 Context
->Selection
= gCurrentSelection
;
5862 Context
->ResetRequired
= gResetRequired
;
5863 Context
->FlagReconnect
= gFlagReconnect
;
5864 Context
->CallbackReconnect
= gCallbackReconnect
;
5865 Context
->ExitRequired
= gExitRequired
;
5866 Context
->HiiHandle
= mCurrentHiiHandle
;
5867 Context
->FormId
= mCurrentFormId
;
5868 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
5869 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
5870 Context
->CurFakeQestId
= mCurFakeQestId
;
5871 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
5872 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
5875 // Save the menu history data.
5877 InitializeListHead(&Context
->FormHistoryList
);
5878 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
5879 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
5880 RemoveEntryList (&MenuList
->Link
);
5882 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
5886 // Save formset list.
5888 InitializeListHead(&Context
->FormSetList
);
5889 while (!IsListEmpty (&gBrowserFormSetList
)) {
5890 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
5891 RemoveEntryList (&FormSet
->Link
);
5893 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
5897 // Insert to FormBrowser context list
5899 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
5904 Restore globals used by previous call to SendForm().
5908 RestoreBrowserContext (
5913 BROWSER_CONTEXT
*Context
;
5914 FORM_ENTRY_INFO
*MenuList
;
5915 FORM_BROWSER_FORMSET
*FormSet
;
5917 ASSERT (gBrowserContextCount
!= 0);
5918 gBrowserContextCount
--;
5919 if (gBrowserContextCount
== 0) {
5921 // This is not reentry of SendForm(), no context to restore
5926 ASSERT (!IsListEmpty (&gBrowserContextList
));
5928 Link
= GetFirstNode (&gBrowserContextList
);
5929 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
5932 // Restore FormBrowser context
5934 gCurrentSelection
= Context
->Selection
;
5935 gResetRequired
= Context
->ResetRequired
;
5936 gFlagReconnect
= Context
->FlagReconnect
;
5937 gCallbackReconnect
= Context
->CallbackReconnect
;
5938 gExitRequired
= Context
->ExitRequired
;
5939 mCurrentHiiHandle
= Context
->HiiHandle
;
5940 mCurrentFormId
= Context
->FormId
;
5941 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
5942 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
5943 mCurFakeQestId
= Context
->CurFakeQestId
;
5944 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
5945 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
5948 // Restore the menu history data.
5950 while (!IsListEmpty (&Context
->FormHistoryList
)) {
5951 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
5952 RemoveEntryList (&MenuList
->Link
);
5954 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
5958 // Restore the Formset data.
5960 while (!IsListEmpty (&Context
->FormSetList
)) {
5961 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
5962 RemoveEntryList (&FormSet
->Link
);
5964 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
5968 // Remove from FormBrowser context list
5970 RemoveEntryList (&Context
->Link
);
5971 gBS
->FreePool (Context
);
5975 Find the matched FormSet context in the backup maintain list based on HiiHandle.
5977 @param Handle The Hii Handle.
5979 @return the found FormSet context. If no found, NULL will return.
5982 FORM_BROWSER_FORMSET
*
5983 GetFormSetFromHiiHandle (
5984 EFI_HII_HANDLE Handle
5988 FORM_BROWSER_FORMSET
*FormSet
;
5990 Link
= GetFirstNode (&gBrowserFormSetList
);
5991 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5992 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5993 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5994 if (!ValidateFormSet(FormSet
)) {
5997 if (FormSet
->HiiHandle
== Handle
) {
6006 Check whether the input HII handle is the FormSet that is being used.
6008 @param Handle The Hii Handle.
6010 @retval TRUE HII handle is being used.
6011 @retval FALSE HII handle is not being used.
6015 IsHiiHandleInBrowserContext (
6016 EFI_HII_HANDLE Handle
6020 BROWSER_CONTEXT
*Context
;
6023 // HiiHandle is Current FormSet.
6025 if (mCurrentHiiHandle
== Handle
) {
6030 // Check whether HiiHandle is in BrowserContext.
6032 Link
= GetFirstNode (&gBrowserContextList
);
6033 while (!IsNull (&gBrowserContextList
, Link
)) {
6034 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6035 if (Context
->HiiHandle
== Handle
) {
6037 // HiiHandle is in BrowserContext
6041 Link
= GetNextNode (&gBrowserContextList
, Link
);
6048 Perform Password check.
6049 Passwork may be encrypted by driver that requires the specific check.
6051 @param Form Form where Password Statement is in.
6052 @param Statement Password statement
6053 @param PasswordString Password string to be checked. It may be NULL.
6054 NULL means to restore password.
6055 "" string can be used to checked whether old password does exist.
6057 @return Status Status of Password check.
6062 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6063 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6064 IN EFI_STRING PasswordString OPTIONAL
6068 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6069 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6070 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6071 FORM_BROWSER_STATEMENT
*Question
;
6073 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6074 Question
= GetBrowserStatement(Statement
);
6075 ASSERT (Question
!= NULL
);
6077 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6078 if (ConfigAccess
== NULL
) {
6079 return EFI_UNSUPPORTED
;
6082 if (PasswordString
== NULL
) {
6087 // Check whether has preexisted password.
6089 if (PasswordString
[0] == 0) {
6090 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
6093 return EFI_NOT_READY
;
6098 // Check whether the input password is same as preexisted password.
6100 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
6103 return EFI_NOT_READY
;
6108 // Prepare password string in HII database
6110 if (PasswordString
!= NULL
) {
6111 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6113 IfrTypeValue
.string
= 0;
6117 // Send password to Configuration Driver for validation
6119 Status
= ConfigAccess
->Callback (
6121 EFI_BROWSER_ACTION_CHANGING
,
6122 Question
->QuestionId
,
6123 Question
->HiiValue
.Type
,
6129 // Remove password string from HII database
6131 if (PasswordString
!= NULL
) {
6132 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6139 Find the registered HotKey based on KeyData.
6141 @param[in] KeyData A pointer to a buffer that describes the keystroke
6142 information for the hot key.
6144 @return The registered HotKey context. If no found, NULL will return.
6147 GetHotKeyFromRegisterList (
6148 IN EFI_INPUT_KEY
*KeyData
6152 BROWSER_HOT_KEY
*HotKey
;
6154 Link
= GetFirstNode (&gBrowserHotKeyList
);
6155 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6156 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6157 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6160 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6167 Configure what scope the hot key will impact.
6168 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6169 If no scope is set, the default scope will be FormSet level.
6170 After all registered hot keys are removed, previous Scope can reset to another level.
6172 @param[in] Scope Scope level to be set.
6174 @retval EFI_SUCCESS Scope is set correctly.
6175 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6176 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6182 IN BROWSER_SETTING_SCOPE Scope
6185 if (Scope
>= MaxLevel
) {
6186 return EFI_INVALID_PARAMETER
;
6190 // When no hot key registered in system or on the first setting,
6191 // Scope can be set.
6193 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6194 gBrowserSettingScope
= Scope
;
6195 mBrowserScopeFirstSet
= FALSE
;
6196 } else if (Scope
!= gBrowserSettingScope
) {
6197 return EFI_UNSUPPORTED
;
6204 Register the hot key with its browser action, or unregistered the hot key.
6205 Only support hot key that is not printable character (control key, function key, etc.).
6206 If the action value is zero, the hot key will be unregistered if it has been registered.
6207 If the same hot key has been registered, the new action and help string will override the previous ones.
6209 @param[in] KeyData A pointer to a buffer that describes the keystroke
6210 information for the hot key. Its type is EFI_INPUT_KEY to
6211 be supported by all ConsoleIn devices.
6212 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6213 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6214 @param[in] HelpString Help string that describes the hot key information.
6215 Its value may be NULL for the unregistered hot key.
6217 @retval EFI_SUCCESS Hot key is registered or unregistered.
6218 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6219 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6220 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6221 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6226 IN EFI_INPUT_KEY
*KeyData
,
6228 IN UINT16 DefaultId
,
6229 IN EFI_STRING HelpString OPTIONAL
6232 BROWSER_HOT_KEY
*HotKey
;
6235 // Check input parameters.
6237 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6238 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6239 return EFI_INVALID_PARAMETER
;
6243 // Check whether the input KeyData is in BrowserHotKeyList.
6245 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6248 // Unregister HotKey
6250 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6251 if (HotKey
!= NULL
) {
6253 // The registered HotKey is found.
6254 // Remove it from List, and free its resource.
6256 RemoveEntryList (&HotKey
->Link
);
6257 FreePool (HotKey
->KeyData
);
6258 FreePool (HotKey
->HelpString
);
6262 // The registered HotKey is not found.
6264 return EFI_NOT_FOUND
;
6268 if (HotKey
!= NULL
) {
6269 return EFI_ALREADY_STARTED
;
6273 // Create new Key, and add it into List.
6275 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6276 ASSERT (HotKey
!= NULL
);
6277 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6278 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6279 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6282 // Fill HotKey information.
6284 HotKey
->Action
= Action
;
6285 HotKey
->DefaultId
= DefaultId
;
6286 if (HotKey
->HelpString
!= NULL
) {
6287 FreePool (HotKey
->HelpString
);
6289 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6295 Register Exit handler function.
6296 When more than one handler function is registered, the latter one will override the previous one.
6297 When NULL handler is specified, the previous Exit handler will be unregistered.
6299 @param[in] Handler Pointer to handler function.
6304 RegiserExitHandler (
6305 IN EXIT_HANDLER Handler
6308 ExitHandlerFunction
= Handler
;
6313 Check whether the browser data has been modified.
6315 @retval TRUE Browser data is modified.
6316 @retval FALSE No browser data is modified.
6321 IsBrowserDataModified (
6326 FORM_BROWSER_FORMSET
*FormSet
;
6328 switch (gBrowserSettingScope
) {
6330 if (gCurrentSelection
== NULL
) {
6333 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6336 if (gCurrentSelection
== NULL
) {
6339 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6342 Link
= GetFirstNode (&gBrowserFormSetList
);
6343 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6344 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6345 if (!ValidateFormSet(FormSet
)) {
6349 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6352 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6362 Execute the action requested by the Action parameter.
6364 @param[in] Action Execute the request action.
6365 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6367 @retval EFI_SUCCESS Execute the request action succss.
6368 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6379 FORM_BROWSER_FORMSET
*FormSet
;
6380 FORM_BROWSER_FORM
*Form
;
6382 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6383 return EFI_NOT_READY
;
6386 Status
= EFI_SUCCESS
;
6389 if (gBrowserSettingScope
< SystemLevel
) {
6390 FormSet
= gCurrentSelection
->FormSet
;
6391 Form
= gCurrentSelection
->Form
;
6395 // Executet the discard action.
6397 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6398 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6399 if (EFI_ERROR (Status
)) {
6405 // Executet the difault action.
6407 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6408 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6409 if (EFI_ERROR (Status
)) {
6412 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6416 // Executet the submit action.
6418 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6419 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6420 if (EFI_ERROR (Status
)) {
6426 // Executet the reset action.
6428 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6429 gResetRequired
= TRUE
;
6433 // Executet the exit action.
6435 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6436 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6437 if (gBrowserSettingScope
== SystemLevel
) {
6438 if (ExitHandlerFunction
!= NULL
) {
6439 ExitHandlerFunction ();
6443 gExitRequired
= TRUE
;
6450 Create reminder to let user to choose save or discard the changed browser data.
6451 Caller can use it to actively check the changed browser data.
6453 @retval BROWSER_NO_CHANGES No browser data is changed.
6454 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6455 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6456 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6466 FORM_BROWSER_FORMSET
*FormSet
;
6467 BOOLEAN IsDataChanged
;
6468 UINT32 DataSavedAction
;
6471 DataSavedAction
= BROWSER_NO_CHANGES
;
6472 IsDataChanged
= FALSE
;
6473 Link
= GetFirstNode (&gBrowserFormSetList
);
6474 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6475 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6476 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6477 if (!ValidateFormSet(FormSet
)) {
6480 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6481 IsDataChanged
= TRUE
;
6487 // No data is changed. No save is required.
6489 if (!IsDataChanged
) {
6490 return DataSavedAction
;
6494 // If data is changed, prompt user to save or discard it.
6497 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6499 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6500 SubmitForm (NULL
, NULL
, SystemLevel
);
6501 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6503 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6504 DiscardForm (NULL
, NULL
, SystemLevel
);
6505 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6507 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6508 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6513 return DataSavedAction
;
6517 Check whether the Reset Required for the browser
6519 @retval TRUE Browser required to reset after exit.
6520 @retval FALSE Browser not need to reset after exit.
6529 return gResetRequired
;