2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
12 SETUP_DRIVER_SIGNATURE
,
25 BROWSER_EXTENSION2_VERSION_1_1
,
29 IsBrowserDataModified
,
37 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
38 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
39 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
40 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
42 UINTN gBrowserContextCount
= 0;
43 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
44 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
45 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
46 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
47 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
49 BOOLEAN mSystemSubmit
= FALSE
;
50 BOOLEAN gResetRequiredFormLevel
;
51 BOOLEAN gResetRequiredSystemLevel
= FALSE
;
52 BOOLEAN gExitRequired
;
53 BOOLEAN gFlagReconnect
;
54 BOOLEAN gCallbackReconnect
;
55 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
56 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
57 EXIT_HANDLER ExitHandlerFunction
= NULL
;
58 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
61 // Browser Global Strings
64 CHAR16
*mUnknownString
= L
"!";
66 extern EFI_GUID mCurrentFormSetGuid
;
67 extern EFI_HII_HANDLE mCurrentHiiHandle
;
68 extern UINT16 mCurrentFormId
;
69 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
72 Create a menu with specified formset GUID and form ID, and add it as a child
73 of the given parent menu.
75 @param HiiHandle Hii handle related to this formset.
76 @param FormSetGuid The Formset Guid of menu to be added.
77 @param FormId The Form ID of menu to be added.
78 @param QuestionId The question id of this menu to be added.
80 @return A pointer to the newly added menu or NULL if memory is insufficient.
85 IN EFI_HII_HANDLE HiiHandle
,
86 IN EFI_GUID
*FormSetGuid
,
91 FORM_ENTRY_INFO
*MenuList
;
93 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
94 if (MenuList
== NULL
) {
98 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
100 MenuList
->HiiHandle
= HiiHandle
;
101 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
102 MenuList
->FormId
= FormId
;
103 MenuList
->QuestionId
= QuestionId
;
106 // If parent is not specified, it is the root Form of a Formset
108 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
114 Return the form id for the input hiihandle and formset.
116 @param HiiHandle HiiHandle for FormSet.
117 @param FormSetGuid The Formset GUID of the menu to search.
119 @return First form's id for this form set.
124 IN EFI_HII_HANDLE HiiHandle
,
125 IN EFI_GUID
*FormSetGuid
129 FORM_BROWSER_FORM
*Form
;
131 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
132 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
138 Search Menu with given FormSetGuid and FormId in all cached menu list.
140 @param HiiHandle HiiHandle for FormSet.
141 @param FormSetGuid The Formset GUID of the menu to search.
142 @param FormId The Form ID of menu to search.
144 @return A pointer to menu found or NULL if not found.
149 IN EFI_HII_HANDLE HiiHandle
,
150 IN EFI_GUID
*FormSetGuid
,
155 FORM_ENTRY_INFO
*MenuList
;
156 FORM_ENTRY_INFO
*RetMenu
;
157 EFI_FORM_ID FirstFormId
;
161 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
162 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
163 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
164 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
167 // If already find the menu, free the menus behind it.
169 if (RetMenu
!= NULL
) {
170 RemoveEntryList (&MenuList
->Link
);
176 // Find the same FromSet.
178 if (MenuList
->HiiHandle
== HiiHandle
) {
179 if (IsZeroGuid (&MenuList
->FormSetGuid
)) {
181 // FormSetGuid is not specified.
184 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
185 if (MenuList
->FormId
== FormId
) {
187 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
188 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
189 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
201 Find parent menu for current menu.
203 @param CurrentMenu Current Menu
204 @param SettingLevel Whether find parent menu in Form Level or Formset level.
205 In form level, just find the parent menu;
206 In formset level, find the parent menu which has different
209 @retval The parent menu for current menu.
213 IN FORM_ENTRY_INFO
*CurrentMenu
,
214 IN BROWSER_SETTING_SCOPE SettingLevel
217 FORM_ENTRY_INFO
*ParentMenu
;
220 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
222 if (CurrentMenu
== NULL
) {
227 Link
= &CurrentMenu
->Link
;
229 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
230 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
232 if (SettingLevel
== FormLevel
) {
234 // For FormLevel, just find the parent menu, return.
239 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
241 // For SystemLevel, must find the menu which has different formset.
246 Link
= Link
->BackLink
;
250 // Not find the parent menu, just return NULL.
252 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
260 Free Menu list linked list.
262 @param MenuListHead One Menu list point in the menu list.
267 LIST_ENTRY
*MenuListHead
270 FORM_ENTRY_INFO
*MenuList
;
272 while (!IsListEmpty (MenuListHead
)) {
273 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
274 RemoveEntryList (&MenuList
->Link
);
281 Copy current Menu list to the new menu list.
283 @param NewMenuListHead New create Menu list.
284 @param CurrentMenuListHead Current Menu list.
289 OUT LIST_ENTRY
*NewMenuListHead
,
290 IN LIST_ENTRY
*CurrentMenuListHead
294 FORM_ENTRY_INFO
*MenuList
;
295 FORM_ENTRY_INFO
*NewMenuEntry
;
298 // If new menu list not empty, free it first.
300 UiFreeMenuList (NewMenuListHead
);
302 Link
= GetFirstNode (CurrentMenuListHead
);
303 while (!IsNull (CurrentMenuListHead
, Link
)) {
304 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
305 Link
= GetNextNode (CurrentMenuListHead
, Link
);
307 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
308 ASSERT (NewMenuEntry
!= NULL
);
309 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
310 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
311 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
312 NewMenuEntry
->FormId
= MenuList
->FormId
;
313 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
315 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
320 Load all hii formset to the browser.
328 FORM_BROWSER_FORMSET
*LocalFormSet
;
329 EFI_HII_HANDLE
*HiiHandles
;
333 FORM_BROWSER_FORMSET
*OldFormset
;
335 OldFormset
= mSystemLevelFormSet
;
338 // Get all the Hii handles
340 HiiHandles
= HiiGetHiiHandles (NULL
);
341 ASSERT (HiiHandles
!= NULL
);
344 // Search for formset of each class type
346 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
348 // Check HiiHandles[Index] does exist in global maintain list.
350 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
355 // Initilize FormSet Setting
357 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
358 ASSERT (LocalFormSet
!= NULL
);
359 mSystemLevelFormSet
= LocalFormSet
;
361 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
362 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
363 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
364 DestroyFormSet (LocalFormSet
);
367 InitializeCurrentSetting (LocalFormSet
);
370 // Initilize Questions' Value
372 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
373 if (EFI_ERROR (Status
)) {
374 DestroyFormSet (LocalFormSet
);
380 // Free resources, and restore gOldFormSet and gClassOfVfr
382 FreePool (HiiHandles
);
384 mSystemLevelFormSet
= OldFormset
;
388 Pop up the error info.
390 @param BrowserStatus The input browser status.
391 @param HiiHandle The Hiihandle for this opcode.
392 @param OpCode The opcode use to get the erro info and timeout value.
393 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
398 IN UINT32 BrowserStatus
,
399 IN EFI_HII_HANDLE HiiHandle
,
400 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
401 IN CHAR16
*ErrorString
404 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
405 USER_INPUT UserInputData
;
409 if (OpCode
!= NULL
) {
410 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
411 ASSERT (Statement
!= NULL
);
412 Statement
->OpCode
= OpCode
;
413 gDisplayFormData
.HighLightedStatement
= Statement
;
417 // Used to compatible with old display engine.
418 // New display engine not use this field.
420 gDisplayFormData
.ErrorString
= ErrorString
;
421 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
423 if (HiiHandle
!= NULL
) {
424 gDisplayFormData
.HiiHandle
= HiiHandle
;
427 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
429 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
430 gDisplayFormData
.ErrorString
= NULL
;
432 if (OpCode
!= NULL
) {
433 FreePool (Statement
);
436 return UserInputData
.Action
;
440 This is the routine which an external caller uses to direct the browser
441 where to obtain it's information.
444 @param This The Form Browser protocol instanse.
445 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
446 display a list of the formsets for the handles specified.
447 @param HandleCount The number of Handles specified in Handle.
448 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
449 field in the EFI_IFR_FORM_SET op-code for the specified
450 forms-based package. If FormSetGuid is NULL, then this
451 function will display the first found forms package.
452 @param FormId This field specifies which EFI_IFR_FORM to render as the first
453 displayable page. If this field has a value of 0x0000, then
454 the forms browser will render the specified forms in their encoded order.
455 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
457 @param ActionRequest Points to the action recommended by the form.
459 @retval EFI_SUCCESS The function completed successfully.
460 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
461 @retval EFI_NOT_FOUND No valid forms could be found to display.
467 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
468 IN EFI_HII_HANDLE
*Handles
,
469 IN UINTN HandleCount
,
470 IN EFI_GUID
*FormSetGuid
, OPTIONAL
471 IN UINT16 FormId
, OPTIONAL
472 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
473 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
477 UI_MENU_SELECTION
*Selection
;
479 FORM_BROWSER_FORMSET
*FormSet
;
480 FORM_ENTRY_INFO
*MenuList
;
484 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
486 if (mFormDisplay
== NULL
) {
487 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
488 return EFI_UNSUPPORTED
;
492 // Save globals used by SendForm()
494 SaveBrowserContext ();
496 gFlagReconnect
= FALSE
;
497 gResetRequiredFormLevel
= FALSE
;
498 gExitRequired
= FALSE
;
499 gCallbackReconnect
= FALSE
;
500 Status
= EFI_SUCCESS
;
502 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
504 for (Index
= 0; Index
< HandleCount
; Index
++) {
505 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
506 ASSERT (Selection
!= NULL
);
508 Selection
->Handle
= Handles
[Index
];
509 if (FormSetGuid
!= NULL
) {
510 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
511 Selection
->FormId
= FormId
;
513 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
517 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
518 ASSERT (FormSet
!= NULL
);
521 // Validate the HiiHandle
522 // if validate failed, find the first validate parent HiiHandle.
524 if (!ValidateHiiHandle(Selection
->Handle
)) {
525 FindNextMenu (Selection
, FormSetLevel
);
529 // Initialize internal data structures of FormSet
531 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
532 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
533 DestroyFormSet (FormSet
);
536 Selection
->FormSet
= FormSet
;
537 mSystemLevelFormSet
= FormSet
;
540 // Display this formset
542 gCurrentSelection
= Selection
;
544 Status
= SetupBrowser (Selection
);
546 gCurrentSelection
= NULL
;
547 mSystemLevelFormSet
= NULL
;
549 if (gFlagReconnect
|| gCallbackReconnect
) {
550 RetVal
= ReconnectController (FormSet
->DriverHandle
);
552 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
554 gFlagReconnect
= FALSE
;
555 gCallbackReconnect
= FALSE
;
559 // If no data is changed, don't need to save current FormSet into the maintain list.
561 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
562 CleanBrowserStorage(FormSet
);
563 RemoveEntryList (&FormSet
->Link
);
564 DestroyFormSet (FormSet
);
567 if (EFI_ERROR (Status
)) {
570 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
572 FreePool (Selection
);
575 if (ActionRequest
!= NULL
) {
576 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
577 if (gResetRequiredFormLevel
) {
578 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
582 mFormDisplay
->ExitDisplay();
585 // Clear the menu history data.
587 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
588 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
589 RemoveEntryList (&MenuList
->Link
);
594 // Restore globals used by SendForm()
596 RestoreBrowserContext ();
602 Get or set data to the storage.
604 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
605 @param ResultsData A string returned from an IFR browser or
606 equivalent. The results string will have no
607 routing information in them.
608 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
609 (if RetrieveData = TRUE) data from the uncommitted
610 browser state information or set (if RetrieveData
611 = FALSE) data in the uncommitted browser state
613 @param Storage The pointer to the storage.
615 @retval EFI_SUCCESS The results have been distributed or are awaiting
621 IN OUT UINTN
*ResultsDataSize
,
622 IN OUT EFI_STRING
*ResultsData
,
623 IN BOOLEAN RetrieveData
,
624 IN BROWSER_STORAGE
*Storage
633 FORMSET_STORAGE
*BrowserStorage
;
637 // Generate <ConfigResp>
639 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
640 if (EFI_ERROR (Status
)) {
645 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
646 // Also need to consider add "\0" at first time.
648 StrPtr
= StrStr (ConfigResp
, L
"PATH");
649 ASSERT (StrPtr
!= NULL
);
650 StrPtr
= StrStr (StrPtr
, L
"&");
652 BufferSize
= StrSize (StrPtr
);
655 // Copy the data if the input buffer is bigger enough.
657 if (*ResultsDataSize
>= BufferSize
) {
658 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
661 *ResultsDataSize
= BufferSize
;
662 FreePool (ConfigResp
);
665 // Prepare <ConfigResp>
667 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
668 ASSERT (BrowserStorage
!= NULL
);
669 TmpSize
= StrLen (*ResultsData
);
670 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
671 MaxLen
= BufferSize
/ sizeof (CHAR16
);
672 ConfigResp
= AllocateZeroPool (BufferSize
);
673 ASSERT (ConfigResp
!= NULL
);
675 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
676 StrCatS (ConfigResp
, MaxLen
, L
"&");
677 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
680 // Update Browser uncommited data
682 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
683 FreePool (ConfigResp
);
684 if (EFI_ERROR (Status
)) {
693 This routine called this service in the browser to retrieve or set certain uncommitted
694 state information that resides in the open formsets.
696 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
698 @param ResultsDataSize A pointer to the size of the buffer associated
700 @param ResultsData A string returned from an IFR browser or
701 equivalent. The results string will have no
702 routing information in them.
703 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
704 (if RetrieveData = TRUE) data from the uncommitted
705 browser state information or set (if RetrieveData
706 = FALSE) data in the uncommitted browser state
708 @param VariableGuid An optional field to indicate the target variable
710 @param VariableName An optional field to indicate the target
711 human-readable variable name.
713 @retval EFI_SUCCESS The results have been distributed or are awaiting
715 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
716 contain the results data.
722 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
723 IN OUT UINTN
*ResultsDataSize
,
724 IN OUT EFI_STRING ResultsData
,
725 IN BOOLEAN RetrieveData
,
726 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
727 IN CONST CHAR16
*VariableName OPTIONAL
732 BROWSER_STORAGE
*Storage
;
733 FORMSET_STORAGE
*FormsetStorage
;
737 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
738 return EFI_INVALID_PARAMETER
;
741 TotalSize
= *ResultsDataSize
;
744 Status
= EFI_SUCCESS
;
746 if (VariableGuid
!= NULL
) {
748 // Try to find target storage in the current formset.
750 Link
= GetFirstNode (&gBrowserStorageList
);
751 while (!IsNull (&gBrowserStorageList
, Link
)) {
752 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
753 Link
= GetNextNode (&gBrowserStorageList
, Link
);
755 // Check the current storage.
757 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
761 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
762 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
764 // Buffer storage require both GUID and Name
766 if (VariableName
== NULL
) {
767 return EFI_NOT_FOUND
;
770 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
775 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
776 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
777 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
778 return EFI_NOT_FOUND
;
781 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
786 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
787 if (EFI_ERROR (Status
)) {
791 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
792 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
796 // Different formsets may have same varstore, so here just set the flag
797 // not exit the circle.
804 return EFI_NOT_FOUND
;
808 // GUID/Name is not specified, take the first storage in FormSet
810 if (mSystemLevelFormSet
== NULL
) {
811 return EFI_NOT_READY
;
815 // Generate <ConfigResp>
817 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
818 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
819 return EFI_UNSUPPORTED
;
822 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
824 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
825 if (EFI_ERROR (Status
)) {
831 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
832 *ResultsDataSize
= TotalSize
;
841 Callback function for SimpleTextInEx protocol install events
843 @param Event the event that is signaled.
844 @param Context not used here.
849 FormDisplayCallback (
854 if (mFormDisplay
!= NULL
) {
858 gBS
->LocateProtocol (
859 &gEdkiiFormDisplayEngineProtocolGuid
,
861 (VOID
**) &mFormDisplay
866 Initialize Setup Browser driver.
868 @param ImageHandle The image handle.
869 @param SystemTable The system table.
871 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
872 @return Other value if failed to initialize the Setup Browser module.
878 IN EFI_HANDLE ImageHandle
,
879 IN EFI_SYSTEM_TABLE
*SystemTable
886 // Locate required Hii relative protocols
888 Status
= gBS
->LocateProtocol (
889 &gEfiHiiDatabaseProtocolGuid
,
891 (VOID
**) &mHiiDatabase
893 ASSERT_EFI_ERROR (Status
);
895 Status
= gBS
->LocateProtocol (
896 &gEfiHiiConfigRoutingProtocolGuid
,
898 (VOID
**) &mHiiConfigRouting
900 ASSERT_EFI_ERROR (Status
);
902 Status
= gBS
->LocateProtocol (
903 &gEfiDevicePathFromTextProtocolGuid
,
905 (VOID
**) &mPathFromText
909 // Install FormBrowser2 protocol
911 mPrivateData
.Handle
= NULL
;
912 Status
= gBS
->InstallProtocolInterface (
913 &mPrivateData
.Handle
,
914 &gEfiFormBrowser2ProtocolGuid
,
915 EFI_NATIVE_INTERFACE
,
916 &mPrivateData
.FormBrowser2
918 ASSERT_EFI_ERROR (Status
);
921 // Install FormBrowserEx2 protocol
923 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
924 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
925 mPrivateData
.Handle
= NULL
;
926 Status
= gBS
->InstallProtocolInterface (
927 &mPrivateData
.Handle
,
928 &gEdkiiFormBrowserEx2ProtocolGuid
,
929 EFI_NATIVE_INTERFACE
,
930 &mPrivateData
.FormBrowserEx2
932 ASSERT_EFI_ERROR (Status
);
934 Status
= gBS
->InstallProtocolInterface (
935 &mPrivateData
.Handle
,
936 &gEdkiiFormBrowserExProtocolGuid
,
937 EFI_NATIVE_INTERFACE
,
938 &mPrivateData
.FormBrowserEx
940 ASSERT_EFI_ERROR (Status
);
942 InitializeDisplayFormData ();
944 Status
= gBS
->LocateProtocol (
945 &gEdkiiFormDisplayEngineProtocolGuid
,
947 (VOID
**) &mFormDisplay
950 if (EFI_ERROR (Status
)) {
951 EfiCreateProtocolNotifyEvent (
952 &gEdkiiFormDisplayEngineProtocolGuid
,
965 Create a new string in HII Package List.
967 @param String The String to be added
968 @param HiiHandle The package list in the HII database to insert the
971 @return The output string.
977 IN EFI_HII_HANDLE HiiHandle
980 EFI_STRING_ID StringId
;
982 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
983 ASSERT (StringId
!= 0);
990 Delete a string from HII Package List.
992 @param StringId Id of the string in HII database.
993 @param HiiHandle The HII package list handle.
995 @retval EFI_SUCCESS The string was deleted successfully.
1000 IN EFI_STRING_ID StringId
,
1001 IN EFI_HII_HANDLE HiiHandle
1006 NullChar
= CHAR_NULL
;
1007 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1013 Get the string based on the StringId and HII Package List Handle.
1015 @param Token The String's ID.
1016 @param HiiHandle The package list in the HII database to search for
1017 the specified string.
1019 @return The output string.
1024 IN EFI_STRING_ID Token
,
1025 IN EFI_HII_HANDLE HiiHandle
1030 if (HiiHandle
== NULL
) {
1034 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1035 if (String
== NULL
) {
1036 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1037 ASSERT (String
!= NULL
);
1039 return (CHAR16
*) String
;
1044 Allocate new memory and then copy the Unicode string Source to Destination.
1046 @param Dest Location to copy string
1047 @param Src String to copy
1052 IN OUT CHAR16
**Dest
,
1056 if (*Dest
!= NULL
) {
1059 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1060 ASSERT (*Dest
!= NULL
);
1065 Allocate new memory and concatinate Source on the end of Destination.
1067 @param Dest String to added to the end of.
1068 @param Src String to concatinate.
1073 IN OUT CHAR16
**Dest
,
1080 if (*Dest
== NULL
) {
1081 NewStringCpy (Dest
, Src
);
1085 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1086 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1087 ASSERT (NewString
!= NULL
);
1089 StrCpyS (NewString
, MaxLen
, *Dest
);
1090 StrCatS (NewString
, MaxLen
, Src
);
1097 Get Value for given Name from a NameValue Storage.
1099 @param Storage The NameValue Storage.
1100 @param Name The Name.
1101 @param Value The retured Value.
1102 @param GetValueFrom Where to get source value, from EditValue or Value.
1104 @retval EFI_SUCCESS Value found for given Name.
1105 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1110 IN BROWSER_STORAGE
*Storage
,
1112 IN OUT CHAR16
**Value
,
1113 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1117 NAME_VALUE_NODE
*Node
;
1119 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1120 return EFI_INVALID_PARAMETER
;
1125 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1126 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1127 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1129 if (StrCmp (Name
, Node
->Name
) == 0) {
1130 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1131 NewStringCpy (Value
, Node
->EditValue
);
1133 NewStringCpy (Value
, Node
->Value
);
1138 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1141 return EFI_NOT_FOUND
;
1146 Set Value of given Name in a NameValue Storage.
1148 @param Storage The NameValue Storage.
1149 @param Name The Name.
1150 @param Value The Value to set.
1151 @param SetValueTo Whether update editValue or Value.
1152 @param ReturnNode The node use the input name.
1154 @retval EFI_SUCCESS Value found for given Name.
1155 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1160 IN BROWSER_STORAGE
*Storage
,
1163 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1164 OUT NAME_VALUE_NODE
**ReturnNode
1168 NAME_VALUE_NODE
*Node
;
1171 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1172 return EFI_INVALID_PARAMETER
;
1175 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1176 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1177 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1179 if (StrCmp (Name
, Node
->Name
) == 0) {
1180 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1181 Buffer
= Node
->EditValue
;
1183 Buffer
= Node
->Value
;
1185 if (Buffer
!= NULL
) {
1188 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1189 ASSERT (Buffer
!= NULL
);
1190 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1191 Node
->EditValue
= Buffer
;
1193 Node
->Value
= Buffer
;
1196 if (ReturnNode
!= NULL
) {
1203 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1206 return EFI_NOT_FOUND
;
1211 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1213 @param Storage The Storage to be conveted.
1214 @param ConfigResp The returned <ConfigResp>.
1215 @param ConfigRequest The ConfigRequest string.
1216 @param GetEditBuf Get the data from editbuffer or buffer.
1218 @retval EFI_SUCCESS Convert success.
1219 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1223 StorageToConfigResp (
1224 IN BROWSER_STORAGE
*Storage
,
1225 IN CHAR16
**ConfigResp
,
1226 IN CHAR16
*ConfigRequest
,
1227 IN BOOLEAN GetEditBuf
1231 EFI_STRING Progress
;
1233 NAME_VALUE_NODE
*Node
;
1235 FORMSET_STORAGE
*FormsetStorage
;
1237 Status
= EFI_SUCCESS
;
1239 switch (Storage
->Type
) {
1240 case EFI_HII_VARSTORE_BUFFER
:
1241 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1242 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1243 Status
= mHiiConfigRouting
->BlockToConfig (
1253 case EFI_HII_VARSTORE_NAME_VALUE
:
1255 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1256 ASSERT (FormsetStorage
!= NULL
);
1257 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1259 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1260 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1261 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1263 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1264 NewStringCat (ConfigResp
, L
"&");
1265 NewStringCat (ConfigResp
, Node
->Name
);
1266 NewStringCat (ConfigResp
, L
"=");
1268 NewStringCat (ConfigResp
, Node
->EditValue
);
1270 NewStringCat (ConfigResp
, Node
->Value
);
1273 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1277 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1279 Status
= EFI_INVALID_PARAMETER
;
1288 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1290 @param Storage The Storage to receive the settings.
1291 @param ConfigResp The <ConfigResp> to be converted.
1293 @retval EFI_SUCCESS Convert success.
1294 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1298 ConfigRespToStorage (
1299 IN BROWSER_STORAGE
*Storage
,
1300 IN CHAR16
*ConfigResp
1304 EFI_STRING Progress
;
1310 Status
= EFI_SUCCESS
;
1312 switch (Storage
->Type
) {
1313 case EFI_HII_VARSTORE_BUFFER
:
1314 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1315 BufferSize
= Storage
->Size
;
1316 Status
= mHiiConfigRouting
->ConfigToBlock (
1319 Storage
->EditBuffer
,
1325 case EFI_HII_VARSTORE_NAME_VALUE
:
1326 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1327 if (StrPtr
== NULL
) {
1330 StrPtr
= StrStr (ConfigResp
, L
"&");
1331 while (StrPtr
!= NULL
) {
1335 StrPtr
= StrPtr
+ 1;
1337 StrPtr
= StrStr (StrPtr
, L
"=");
1338 if (StrPtr
== NULL
) {
1346 StrPtr
= StrPtr
+ 1;
1348 StrPtr
= StrStr (StrPtr
, L
"&");
1349 if (StrPtr
!= NULL
) {
1352 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1356 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1358 Status
= EFI_INVALID_PARAMETER
;
1366 Get bit field value from the buffer and then set the value for the question.
1367 Note: Data type UINT32 can cover all the bit field value.
1369 @param Question The question refer to bit field.
1370 @param Buffer Point to the buffer which the question value get from.
1374 GetBitsQuestionValue (
1375 IN FORM_BROWSER_STATEMENT
*Question
,
1384 StartBit
= Question
->BitVarOffset
% 8;
1385 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1387 CopyMem ((UINT8
*) &BufferValue
, Buffer
, Question
->StorageWidth
);
1389 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1392 // Set question value.
1393 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1394 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1396 CopyMem ((UINT8
*) &Question
->HiiValue
.Value
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1400 Set bit field value to the buffer.
1401 Note: Data type UINT32 can cover all the bit field value.
1403 @param Question The question refer to bit field.
1404 @param Buffer Point to the buffer which the question value set to.
1405 @param Value The bit field value need to set.
1409 SetBitsQuestionValue (
1410 IN FORM_BROWSER_STATEMENT
*Question
,
1411 IN OUT UINT8
*Buffer
,
1420 StartBit
= Question
->BitVarOffset
% 8;
1421 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1423 CopyMem ((UINT8
*) &Operand
, Buffer
, Question
->StorageWidth
);
1425 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1427 CopyMem (Buffer
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1431 Convert the buffer value to HiiValue.
1433 @param Question The question.
1434 @param Value Unicode buffer save the question value.
1436 @retval Status whether convert the value success.
1441 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1446 BOOLEAN IsBufferStorage
;
1461 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1462 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1463 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1464 IsBufferStorage
= TRUE
;
1466 IsBufferStorage
= FALSE
;
1470 // Question Value is provided by Buffer Storage or NameValue Storage
1472 if (Question
->BufferValue
!= NULL
) {
1474 // This Question is password or orderedlist
1476 Dst
= Question
->BufferValue
;
1479 // Other type of Questions
1481 if (Question
->QuestionReferToBitField
) {
1482 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1483 if (Buffer
== NULL
) {
1484 return EFI_OUT_OF_RESOURCES
;
1488 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1493 // Temp cut at the end of this section, end with '\0' or '&'.
1496 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1499 TempChar
= *StringPtr
;
1502 LengthStr
= StrLen (Value
);
1505 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1506 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1507 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1508 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1510 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1511 Length
= (UINTN
) Question
->StorageWidth
* 2;
1516 Status
= EFI_SUCCESS
;
1517 if (!IsBufferStorage
&& IsString
) {
1519 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1520 // Add string tail char L'\0' into Length
1522 DstBuf
= (CHAR16
*) Dst
;
1523 ZeroMem (TemStr
, sizeof (TemStr
));
1524 for (Index
= 0; Index
< Length
; Index
+= 4) {
1525 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1526 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1529 // Add tailing L'\0' character
1531 DstBuf
[Index
/4] = L
'\0';
1533 ZeroMem (TemStr
, sizeof (TemStr
));
1534 for (Index
= 0; Index
< Length
; Index
++) {
1535 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1536 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1537 if ((Index
& 1) == 0) {
1538 Dst
[Index
/2] = DigitUint8
;
1540 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1545 *StringPtr
= TempChar
;
1547 if (Buffer
!= NULL
&& Question
->QuestionReferToBitField
) {
1548 GetBitsQuestionValue (Question
, Buffer
);
1556 Get Question's current Value.
1558 @param FormSet FormSet data structure.
1559 @param Form Form data structure.
1560 @param Question Question to be initialized.
1561 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1563 @retval EFI_SUCCESS The function completed successfully.
1568 IN FORM_BROWSER_FORMSET
*FormSet
,
1569 IN FORM_BROWSER_FORM
*Form
,
1570 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1571 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1580 BROWSER_STORAGE
*Storage
;
1581 FORMSET_STORAGE
*FormsetStorage
;
1582 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1583 CHAR16
*ConfigRequest
;
1588 BOOLEAN IsBufferStorage
;
1591 Status
= EFI_SUCCESS
;
1595 if (GetValueFrom
>= GetSetValueWithMax
) {
1596 return EFI_INVALID_PARAMETER
;
1600 // Question value is provided by an Expression, evaluate it
1602 if (Question
->ValueExpression
!= NULL
) {
1603 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1604 if (!EFI_ERROR (Status
)) {
1605 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1606 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1607 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1608 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1609 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1611 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1612 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1614 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1616 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1617 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1623 // Get question value by read expression.
1625 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1626 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1627 if (!EFI_ERROR (Status
) &&
1628 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1630 // Only update question value to the valid result.
1632 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1633 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1634 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1635 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1636 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1638 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1639 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1641 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1643 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1644 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1650 // Question value is provided by RTC
1652 Storage
= Question
->Storage
;
1653 QuestionValue
= &Question
->HiiValue
.Value
;
1654 if (Storage
== NULL
) {
1656 // It's a Question without storage, or RTC date/time
1658 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1660 // Date and time define the same Flags bit
1662 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1663 case QF_DATE_STORAGE_TIME
:
1664 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1667 case QF_DATE_STORAGE_WAKEUP
:
1668 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1671 case QF_DATE_STORAGE_NORMAL
:
1674 // For date/time without storage
1679 if (EFI_ERROR (Status
)) {
1680 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1681 QuestionValue
->date
.Year
= 0xff;
1682 QuestionValue
->date
.Month
= 0xff;
1683 QuestionValue
->date
.Day
= 0xff;
1685 QuestionValue
->time
.Hour
= 0xff;
1686 QuestionValue
->time
.Minute
= 0xff;
1687 QuestionValue
->time
.Second
= 0xff;
1692 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1693 QuestionValue
->date
.Year
= EfiTime
.Year
;
1694 QuestionValue
->date
.Month
= EfiTime
.Month
;
1695 QuestionValue
->date
.Day
= EfiTime
.Day
;
1697 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1698 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1699 QuestionValue
->time
.Second
= EfiTime
.Second
;
1707 // Question value is provided by EFI variable
1709 StorageWidth
= Question
->StorageWidth
;
1710 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1711 if (Question
->BufferValue
!= NULL
) {
1712 Dst
= Question
->BufferValue
;
1714 Dst
= (UINT8
*) QuestionValue
;
1717 Status
= gRT
->GetVariable (
1718 Question
->VariableName
,
1725 // Always return success, even this EFI variable doesn't exist
1731 // Question Value is provided by Buffer Storage or NameValue Storage
1733 if (Question
->BufferValue
!= NULL
) {
1735 // This Question is password or orderedlist
1737 Dst
= Question
->BufferValue
;
1740 // Other type of Questions
1742 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1745 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1746 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1747 IsBufferStorage
= TRUE
;
1749 IsBufferStorage
= FALSE
;
1751 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1752 if (IsBufferStorage
) {
1753 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1755 // Copy from storage Edit buffer
1756 // If the Question refer to bit filed, get the value in the related bit filed.
1758 if (Question
->QuestionReferToBitField
) {
1759 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1761 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1765 // Copy from storage Edit buffer
1766 // If the Question refer to bit filed, get the value in the related bit filed.
1768 if (Question
->QuestionReferToBitField
) {
1769 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1771 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1776 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1777 if (EFI_ERROR (Status
)) {
1781 ASSERT (Value
!= NULL
);
1782 Status
= BufferToValue (Question
, Value
);
1786 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1787 ASSERT (FormsetStorage
!= NULL
);
1789 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1790 // <ConfigHdr> + "&" + <VariableName>
1792 if (IsBufferStorage
) {
1793 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1794 Length
+= StrLen (Question
->BlockName
);
1796 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1797 Length
+= StrLen (Question
->VariableName
) + 1;
1799 // Allocate buffer include '\0'
1800 MaxLen
= Length
+ 1;
1801 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1802 ASSERT (ConfigRequest
!= NULL
);
1804 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1805 if (IsBufferStorage
) {
1806 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1808 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1809 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1813 // Request current settings from Configuration Driver
1815 Status
= mHiiConfigRouting
->ExtractConfig (
1821 FreePool (ConfigRequest
);
1822 if (EFI_ERROR (Status
)) {
1827 // Skip <ConfigRequest>
1829 if (IsBufferStorage
) {
1830 Value
= StrStr (Result
, L
"&VALUE");
1831 if (Value
== NULL
) {
1833 return EFI_NOT_FOUND
;
1840 Value
= Result
+ Length
;
1842 if (*Value
!= '=') {
1844 return EFI_NOT_FOUND
;
1847 // Skip '=', point to value
1851 Status
= BufferToValue (Question
, Value
);
1852 if (EFI_ERROR (Status
)) {
1858 // Synchronize Edit Buffer
1860 if (IsBufferStorage
) {
1861 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1863 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1866 if (Result
!= NULL
) {
1876 Save Question Value to edit copy(cached) or Storage(uncached).
1878 @param FormSet FormSet data structure.
1879 @param Form Form data structure.
1880 @param Question Pointer to the Question.
1881 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1883 @retval EFI_SUCCESS The function completed successfully.
1888 IN FORM_BROWSER_FORMSET
*FormSet
,
1889 IN FORM_BROWSER_FORM
*Form
,
1890 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1891 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1901 BROWSER_STORAGE
*Storage
;
1902 FORMSET_STORAGE
*FormsetStorage
;
1903 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1908 BOOLEAN IsBufferStorage
;
1914 NAME_VALUE_NODE
*Node
;
1917 Status
= EFI_SUCCESS
;
1920 if (SetValueTo
>= GetSetValueWithMax
) {
1921 return EFI_INVALID_PARAMETER
;
1925 // If Question value is provided by an Expression, then it is read only
1927 if (Question
->ValueExpression
!= NULL
) {
1932 // Before set question value, evaluate its write expression.
1934 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1935 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1936 if (EFI_ERROR (Status
)) {
1942 // Question value is provided by RTC
1944 Storage
= Question
->Storage
;
1945 QuestionValue
= &Question
->HiiValue
.Value
;
1946 if (Storage
== NULL
) {
1948 // It's a Question without storage, or RTC date/time
1950 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1952 // Date and time define the same Flags bit
1954 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1955 case QF_DATE_STORAGE_TIME
:
1956 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1959 case QF_DATE_STORAGE_WAKEUP
:
1960 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1963 case QF_DATE_STORAGE_NORMAL
:
1966 // For date/time without storage
1971 if (EFI_ERROR (Status
)) {
1975 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1976 EfiTime
.Year
= QuestionValue
->date
.Year
;
1977 EfiTime
.Month
= QuestionValue
->date
.Month
;
1978 EfiTime
.Day
= QuestionValue
->date
.Day
;
1980 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1981 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1982 EfiTime
.Second
= QuestionValue
->time
.Second
;
1985 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1986 Status
= gRT
->SetTime (&EfiTime
);
1988 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1996 // Question value is provided by EFI variable
1998 StorageWidth
= Question
->StorageWidth
;
1999 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2000 if (Question
->BufferValue
!= NULL
) {
2001 Src
= Question
->BufferValue
;
2003 Src
= (UINT8
*) QuestionValue
;
2006 Status
= gRT
->SetVariable (
2007 Question
->VariableName
,
2009 Storage
->Attributes
,
2017 // Question Value is provided by Buffer Storage or NameValue Storage
2019 if (Question
->BufferValue
!= NULL
) {
2020 Src
= Question
->BufferValue
;
2022 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
2025 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2026 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2027 IsBufferStorage
= TRUE
;
2029 IsBufferStorage
= FALSE
;
2031 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2033 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
2034 if (IsBufferStorage
) {
2035 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2037 // Copy to storage edit buffer
2038 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2040 if (Question
->QuestionReferToBitField
) {
2041 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2043 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2045 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2047 // Copy to storage buffer
2048 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2050 if (Question
->QuestionReferToBitField
) {
2051 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2053 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2059 // Allocate enough string buffer.
2062 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
2063 Value
= AllocateZeroPool (BufferLen
);
2064 ASSERT (Value
!= NULL
);
2066 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2068 TemName
= (CHAR16
*) Src
;
2070 for (; *TemName
!= L
'\0'; TemName
++) {
2071 UnicodeValueToStringS (
2073 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2074 PREFIX_ZERO
| RADIX_HEX
,
2078 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2081 BufferLen
= StorageWidth
* 2 + 1;
2082 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2083 ASSERT (Value
!= NULL
);
2085 // Convert Buffer to Hex String
2087 TemBuffer
= Src
+ StorageWidth
- 1;
2089 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2090 UnicodeValueToStringS (
2092 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2093 PREFIX_ZERO
| RADIX_HEX
,
2097 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2101 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2103 if (EFI_ERROR (Status
)) {
2107 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2109 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2110 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2112 if (IsBufferStorage
) {
2113 Length
= StrLen (Question
->BlockName
) + 7;
2115 Length
= StrLen (Question
->VariableName
) + 2;
2117 if (!IsBufferStorage
&& IsString
) {
2118 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2120 Length
+= (StorageWidth
* 2);
2122 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2123 ASSERT (FormsetStorage
!= NULL
);
2124 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2125 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2126 ASSERT (ConfigResp
!= NULL
);
2128 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2129 if (IsBufferStorage
) {
2130 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2131 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2133 StrCatS (ConfigResp
, MaxLen
, L
"&");
2134 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2135 StrCatS (ConfigResp
, MaxLen
, L
"=");
2138 Value
= ConfigResp
+ StrLen (ConfigResp
);
2140 if (!IsBufferStorage
&& IsString
) {
2142 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2144 TemName
= (CHAR16
*) Src
;
2146 for (; *TemName
!= L
'\0'; TemName
++) {
2147 UnicodeValueToStringS (
2149 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2150 PREFIX_ZERO
| RADIX_HEX
,
2154 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2158 // Convert Buffer to Hex String
2160 TemBuffer
= Src
+ StorageWidth
- 1;
2162 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2163 UnicodeValueToStringS (
2165 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2166 PREFIX_ZERO
| RADIX_HEX
,
2170 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2175 // Convert to lower char.
2177 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2178 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2179 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2184 // Submit Question Value to Configuration Driver
2186 Status
= mHiiConfigRouting
->RouteConfig (
2191 if (EFI_ERROR (Status
)) {
2192 FreePool (ConfigResp
);
2195 FreePool (ConfigResp
);
2198 // Sync storage, from editbuffer to buffer.
2200 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2208 Perform nosubmitif check for a Form.
2210 @param FormSet FormSet data structure.
2211 @param Form Form data structure.
2212 @param Question The Question to be validated.
2213 @param Type Validation type: NoSubmit
2215 @retval EFI_SUCCESS Form validation pass.
2216 @retval other Form validation failed.
2221 IN FORM_BROWSER_FORMSET
*FormSet
,
2222 IN FORM_BROWSER_FORM
*Form
,
2223 IN FORM_BROWSER_STATEMENT
*Question
,
2229 LIST_ENTRY
*ListHead
;
2230 FORM_EXPRESSION
*Expression
;
2231 UINT32 BrowserStatus
;
2234 BrowserStatus
= BROWSER_SUCCESS
;
2238 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2239 ListHead
= &Question
->InconsistentListHead
;
2242 case EFI_HII_EXPRESSION_WARNING_IF
:
2243 ListHead
= &Question
->WarningListHead
;
2246 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2247 ListHead
= &Question
->NoSubmitListHead
;
2252 return EFI_UNSUPPORTED
;
2255 Link
= GetFirstNode (ListHead
);
2256 while (!IsNull (ListHead
, Link
)) {
2257 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2260 // Evaluate the expression
2262 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2263 if (EFI_ERROR (Status
)) {
2267 if (IsTrue (&Expression
->Result
)) {
2269 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2270 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2273 case EFI_HII_EXPRESSION_WARNING_IF
:
2274 BrowserStatus
= BROWSER_WARNING_IF
;
2277 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2278 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2280 // This code only used to compatible with old display engine,
2281 // New display engine will not use this field.
2283 if (Expression
->Error
!= 0) {
2284 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2293 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2295 // If in system submit process and for no_submit_if check, not popup this error message.
2296 // Will process this fail again later in not system submit process.
2298 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2301 if (ErrorStr
!= NULL
) {
2302 FreePool (ErrorStr
);
2305 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2308 return EFI_NOT_READY
;
2312 Link
= GetNextNode (ListHead
, Link
);
2319 Perform question check.
2321 If one question has more than one check, process form high priority to low.
2322 Only one error info will be popup.
2324 @param FormSet FormSet data structure.
2325 @param Form Form data structure.
2326 @param Question The Question to be validated.
2328 @retval EFI_SUCCESS Form validation pass.
2329 @retval other Form validation failed.
2333 ValueChangedValidation (
2334 IN FORM_BROWSER_FORMSET
*FormSet
,
2335 IN FORM_BROWSER_FORM
*Form
,
2336 IN FORM_BROWSER_STATEMENT
*Question
2341 Status
= EFI_SUCCESS
;
2344 // Do the inconsistentif check.
2346 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2347 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2348 if (EFI_ERROR (Status
)) {
2354 // Do the warningif check.
2356 if (!IsListEmpty (&Question
->WarningListHead
)) {
2357 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2364 Perform NoSubmit check for each Form in FormSet.
2366 @param FormSet FormSet data structure.
2367 @param CurrentForm Current input form data structure.
2368 @param Statement The statement for this check.
2370 @retval EFI_SUCCESS Form validation pass.
2371 @retval other Form validation failed.
2376 IN FORM_BROWSER_FORMSET
*FormSet
,
2377 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2378 OUT FORM_BROWSER_STATEMENT
**Statement
2383 FORM_BROWSER_STATEMENT
*Question
;
2384 FORM_BROWSER_FORM
*Form
;
2385 LIST_ENTRY
*LinkForm
;
2387 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2388 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2389 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2390 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2392 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2396 Link
= GetFirstNode (&Form
->StatementListHead
);
2397 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2398 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2399 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2400 if (EFI_ERROR (Status
)) {
2401 if (*CurrentForm
== NULL
) {
2402 *CurrentForm
= Form
;
2404 if (Statement
!= NULL
) {
2405 *Statement
= Question
;
2410 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2418 Fill storage's edit copy with settings requested from Configuration Driver.
2420 @param Storage The storage which need to sync.
2421 @param ConfigRequest The config request string which used to sync storage.
2422 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2423 editbuffer to buffer
2424 if TRUE, copy the editbuffer to the buffer.
2425 if FALSE, copy the buffer to the editbuffer.
2427 @retval EFI_SUCCESS The function completed successfully.
2431 SynchronizeStorage (
2432 OUT BROWSER_STORAGE
*Storage
,
2433 IN CHAR16
*ConfigRequest
,
2434 IN BOOLEAN SyncOrRestore
2438 EFI_STRING Progress
;
2442 NAME_VALUE_NODE
*Node
;
2446 Status
= EFI_SUCCESS
;
2449 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2450 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2451 BufferSize
= Storage
->Size
;
2453 if (SyncOrRestore
) {
2454 Src
= Storage
->EditBuffer
;
2455 Dst
= Storage
->Buffer
;
2457 Src
= Storage
->Buffer
;
2458 Dst
= Storage
->EditBuffer
;
2461 if (ConfigRequest
!= NULL
) {
2462 Status
= mHiiConfigRouting
->BlockToConfig(
2470 if (EFI_ERROR (Status
)) {
2474 Status
= mHiiConfigRouting
->ConfigToBlock (
2481 if (Result
!= NULL
) {
2485 CopyMem (Dst
, Src
, BufferSize
);
2487 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2488 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2489 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2490 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2492 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2493 (ConfigRequest
== NULL
)) {
2494 if (SyncOrRestore
) {
2495 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2497 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2501 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2509 When discard the question value, call the callback function with Changed type
2510 to inform the hii driver.
2512 @param FormSet FormSet data structure.
2513 @param Form Form data structure.
2517 SendDiscardInfoToDriver (
2518 IN FORM_BROWSER_FORMSET
*FormSet
,
2519 IN FORM_BROWSER_FORM
*Form
2523 FORM_BROWSER_STATEMENT
*Question
;
2524 EFI_IFR_TYPE_VALUE
*TypeValue
;
2525 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2527 if (FormSet
->ConfigAccess
== NULL
) {
2531 Link
= GetFirstNode (&Form
->StatementListHead
);
2532 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2533 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2534 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2536 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2540 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2544 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2548 if (!Question
->ValueChanged
) {
2553 // Restore the question value before call the CHANGED callback type.
2555 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2557 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2558 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2561 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2562 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2564 TypeValue
= &Question
->HiiValue
.Value
;
2567 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2568 FormSet
->ConfigAccess
->Callback (
2569 FormSet
->ConfigAccess
,
2570 EFI_BROWSER_ACTION_CHANGED
,
2571 Question
->QuestionId
,
2572 Question
->HiiValue
.Type
,
2580 When submit the question value, call the callback function with Submitted type
2581 to inform the hii driver.
2583 @param FormSet FormSet data structure.
2584 @param Form Form data structure.
2588 SubmitCallbackForForm (
2589 IN FORM_BROWSER_FORMSET
*FormSet
,
2590 IN FORM_BROWSER_FORM
*Form
2594 FORM_BROWSER_STATEMENT
*Question
;
2595 EFI_IFR_TYPE_VALUE
*TypeValue
;
2596 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2598 if (FormSet
->ConfigAccess
== NULL
) {
2602 Link
= GetFirstNode (&Form
->StatementListHead
);
2603 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2604 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2605 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2607 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2611 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2615 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2619 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2620 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2622 TypeValue
= &Question
->HiiValue
.Value
;
2625 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2626 FormSet
->ConfigAccess
->Callback (
2627 FormSet
->ConfigAccess
,
2628 EFI_BROWSER_ACTION_SUBMITTED
,
2629 Question
->QuestionId
,
2630 Question
->HiiValue
.Type
,
2638 When value set Success, call the submit callback function.
2640 @param FormSet FormSet data structure.
2641 @param Form Form data structure.
2646 IN FORM_BROWSER_FORMSET
*FormSet
,
2647 IN FORM_BROWSER_FORM
*Form
2650 FORM_BROWSER_FORM
*CurrentForm
;
2654 SubmitCallbackForForm(FormSet
, Form
);
2658 Link
= GetFirstNode (&FormSet
->FormListHead
);
2659 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2660 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2661 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2663 SubmitCallbackForForm(FormSet
, CurrentForm
);
2668 Validate the HiiHandle.
2670 @param HiiHandle The input HiiHandle which need to validate.
2672 @retval TRUE The handle is validate.
2673 @retval FALSE The handle is invalidate.
2678 EFI_HII_HANDLE HiiHandle
2681 EFI_HII_HANDLE
*HiiHandles
;
2685 if (HiiHandle
== NULL
) {
2691 HiiHandles
= HiiGetHiiHandles (NULL
);
2692 ASSERT (HiiHandles
!= NULL
);
2694 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2695 if (HiiHandles
[Index
] == HiiHandle
) {
2701 FreePool (HiiHandles
);
2707 Validate the FormSet. If the formset is not validate, remove it from the list.
2709 @param FormSet The input FormSet which need to validate.
2711 @retval TRUE The handle is validate.
2712 @retval FALSE The handle is invalidate.
2717 FORM_BROWSER_FORMSET
*FormSet
2722 ASSERT (FormSet
!= NULL
);
2724 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2726 // Should not remove the formset which is being used.
2728 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2729 CleanBrowserStorage(FormSet
);
2730 RemoveEntryList (&FormSet
->Link
);
2731 DestroyFormSet (FormSet
);
2737 Check whether need to enable the reset flag in form level.
2738 Also clean all ValueChanged flag in question.
2740 @param SetFlag Whether need to set the Reset Flag.
2741 @param FormSet FormSet data structure.
2742 @param Form Form data structure.
2748 IN FORM_BROWSER_FORMSET
*FormSet
,
2749 IN FORM_BROWSER_FORM
*Form
2753 FORM_BROWSER_STATEMENT
*Question
;
2756 Link
= GetFirstNode (&Form
->StatementListHead
);
2757 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2758 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2759 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2761 if (!Question
->ValueChanged
) {
2765 OldValue
= Question
->ValueChanged
;
2768 // Compare the buffer and editbuffer data to see whether the data has been saved.
2770 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2773 // Only the changed data has been saved, then need to set the reset flag.
2775 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2776 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2777 gResetRequiredFormLevel
= TRUE
;
2778 gResetRequiredSystemLevel
= TRUE
;
2781 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2782 gFlagReconnect
= TRUE
;
2789 Check whether need to enable the reset flag.
2790 Also clean ValueChanged flag for all statements.
2792 Form level or formset level, only one.
2794 @param SetFlag Whether need to set the Reset Flag.
2795 @param FormSet FormSet data structure.
2796 @param Form Form data structure.
2800 ValueChangeResetFlagUpdate (
2802 IN FORM_BROWSER_FORMSET
*FormSet
,
2803 IN FORM_BROWSER_FORM
*Form
2806 FORM_BROWSER_FORM
*CurrentForm
;
2810 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2814 Link
= GetFirstNode (&FormSet
->FormListHead
);
2815 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2816 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2817 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2819 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2824 Base on the return Progress string to find the form.
2826 Base on the first return Offset/Width (Name) string to find the form
2827 which keep this string.
2829 @param FormSet FormSet data structure.
2830 @param Storage Storage which has this Progress string.
2831 @param Progress The Progress string which has the first fail string.
2832 @param RetForm The return form for this progress string.
2833 @param RetQuestion The return question for the error progress string.
2835 @retval TRUE Find the error form and statement for this error progress string.
2836 @retval FALSE Not find the error form.
2840 FindQuestionFromProgress (
2841 IN FORM_BROWSER_FORMSET
*FormSet
,
2842 IN BROWSER_STORAGE
*Storage
,
2843 IN EFI_STRING Progress
,
2844 OUT FORM_BROWSER_FORM
**RetForm
,
2845 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2849 LIST_ENTRY
*LinkStorage
;
2850 LIST_ENTRY
*LinkStatement
;
2851 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2852 FORM_BROWSER_FORM
*Form
;
2854 FORM_BROWSER_STATEMENT
*Statement
;
2856 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2860 *RetQuestion
= NULL
;
2863 // Skip the first "&" or the ConfigHdr part.
2865 if (*Progress
== '&') {
2869 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2871 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2873 // For Name/Value type, Skip the ConfigHdr part.
2875 EndStr
= StrStr (Progress
, L
"PATH=");
2876 ASSERT (EndStr
!= NULL
);
2877 while (*EndStr
!= '&') {
2884 // For Buffer type, Skip the ConfigHdr part.
2886 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2887 ASSERT (EndStr
!= NULL
);
2891 Progress
= EndStr
+ 1;
2895 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2897 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2899 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2900 // here, just keep the "Fred" string.
2902 EndStr
= StrStr (Progress
, L
"=");
2903 ASSERT (EndStr
!= NULL
);
2907 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2908 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2910 EndStr
= StrStr (Progress
, L
"&VALUE=");
2911 ASSERT (EndStr
!= NULL
);
2916 // Search in the form list.
2918 Link
= GetFirstNode (&FormSet
->FormListHead
);
2919 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2920 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2921 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2924 // Search in the ConfigReqeust list in this form.
2926 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2927 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2928 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2929 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2931 if (Storage
!= ConfigInfo
->Storage
) {
2935 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2937 // Find the OffsetWidth string in this form.
2944 if (*RetForm
!= NULL
) {
2945 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2946 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2947 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2948 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2950 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2951 *RetQuestion
= Statement
;
2955 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2956 *RetQuestion
= Statement
;
2962 if (*RetForm
!= NULL
) {
2968 // restore the OffsetWidth string to the original format.
2970 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2976 return (BOOLEAN
) (*RetForm
!= NULL
);
2980 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2981 for form and formset.
2983 @param Storage Storage which has this Progress string.
2984 @param ConfigRequest The ConfigRequest string.
2985 @param Progress The Progress string which has the first fail string.
2986 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2987 @param SyncConfigRequest Return the SyncConfigRequest string.
2991 GetSyncRestoreConfigRequest(
2992 IN BROWSER_STORAGE
*Storage
,
2993 IN EFI_STRING ConfigRequest
,
2994 IN EFI_STRING Progress
,
2995 OUT EFI_STRING
*RestoreConfigRequest
,
2996 OUT EFI_STRING
*SyncConfigRequest
3000 EFI_STRING ConfigHdrEndStr
;
3001 EFI_STRING ElementStr
;
3003 UINTN RestoreEleSize
;
3006 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3008 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3009 // Need to restore all the fields in the ConfigRequest.
3011 if (*Progress
== L
'G') {
3012 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3013 ASSERT (*RestoreConfigRequest
!= NULL
);
3018 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3020 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3022 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3023 // here, just keep the "Fred" string.
3025 EndStr
= StrStr (Progress
, L
"=");
3026 ASSERT (EndStr
!= NULL
);
3029 // Find the ConfigHdr in ConfigRequest.
3031 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3032 ASSERT (ConfigHdrEndStr
!= NULL
);
3033 while (*ConfigHdrEndStr
!= L
'&') {
3038 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3039 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3041 EndStr
= StrStr (Progress
, L
"&VALUE=");
3042 ASSERT (EndStr
!= NULL
);
3045 // Find the ConfigHdr in ConfigRequest.
3047 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3050 // Find the first fail pair in the ConfigRequest.
3052 ElementStr
= StrStr (ConfigRequest
, Progress
);
3053 ASSERT (ElementStr
!= NULL
);
3055 // To get the RestoreConfigRequest.
3057 RestoreEleSize
= StrSize (ElementStr
);
3058 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3059 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3060 ASSERT (*RestoreConfigRequest
!= NULL
);
3061 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3062 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3064 // To get the SyncConfigRequest.
3066 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3067 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3068 ASSERT (*SyncConfigRequest
!= NULL
);
3069 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3072 // restore the Progress string to the original format.
3074 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3082 Popup an save error info and get user input.
3084 @param TitleId The form title id.
3085 @param HiiHandle The hii handle for this package.
3087 @retval UINT32 The user select option for the save fail.
3088 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3092 IN EFI_STRING_ID TitleId
,
3093 IN EFI_HII_HANDLE HiiHandle
3097 CHAR16
*StringBuffer
;
3100 FormTitle
= GetToken (TitleId
, HiiHandle
);
3102 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3103 ASSERT (StringBuffer
!= NULL
);
3107 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3108 L
"Submit Fail For Form: %s.",
3112 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3114 FreePool (StringBuffer
);
3115 FreePool (FormTitle
);
3121 Popup an NO_SUBMIT_IF error info and get user input.
3123 @param TitleId The form title id.
3124 @param HiiHandle The hii handle for this package.
3126 @retval UINT32 The user select option for the save fail.
3127 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3130 ConfirmNoSubmitFail (
3131 IN EFI_STRING_ID TitleId
,
3132 IN EFI_HII_HANDLE HiiHandle
3136 CHAR16
*StringBuffer
;
3139 FormTitle
= GetToken (TitleId
, HiiHandle
);
3141 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3142 ASSERT (StringBuffer
!= NULL
);
3146 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3147 L
"NO_SUBMIT_IF error For Form: %s.",
3151 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3153 FreePool (StringBuffer
);
3154 FreePool (FormTitle
);
3160 Discard data based on the input setting scope (Form, FormSet or System).
3162 @param FormSet FormSet data structure.
3163 @param Form Form data structure.
3164 @param SettingScope Setting Scope for Discard action.
3166 @retval EFI_SUCCESS The function completed successfully.
3167 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3172 IN FORM_BROWSER_FORMSET
*FormSet
,
3173 IN FORM_BROWSER_FORM
*Form
,
3174 IN BROWSER_SETTING_SCOPE SettingScope
3178 FORMSET_STORAGE
*Storage
;
3179 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3180 FORM_BROWSER_FORMSET
*LocalFormSet
;
3181 FORM_BROWSER_FORMSET
*OldFormSet
;
3184 // Check the supported setting level.
3186 if (SettingScope
>= MaxLevel
) {
3187 return EFI_UNSUPPORTED
;
3190 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3192 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3193 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3194 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3195 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3197 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3202 // Skip if there is no RequestElement
3204 if (ConfigInfo
->ElementCount
== 0) {
3209 // Prepare <ConfigResp>
3211 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3214 // Call callback with Changed type to inform the driver.
3216 SendDiscardInfoToDriver (FormSet
, Form
);
3219 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3220 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3223 // Discard Buffer storage or Name/Value storage
3225 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3226 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3227 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3228 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3230 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3235 // Skip if there is no RequestElement
3237 if (Storage
->ElementCount
== 0) {
3241 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3244 Link
= GetFirstNode (&FormSet
->FormListHead
);
3245 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3246 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3247 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3250 // Call callback with Changed type to inform the driver.
3252 SendDiscardInfoToDriver (FormSet
, Form
);
3255 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3256 } else if (SettingScope
== SystemLevel
) {
3258 // System Level Discard.
3260 OldFormSet
= mSystemLevelFormSet
;
3263 // Discard changed value for each FormSet in the maintain list.
3265 Link
= GetFirstNode (&gBrowserFormSetList
);
3266 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3267 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3268 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3269 if (!ValidateFormSet(LocalFormSet
)) {
3273 mSystemLevelFormSet
= LocalFormSet
;
3275 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3276 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3278 // Remove maintain backup list after discard except for the current using FormSet.
3280 CleanBrowserStorage(LocalFormSet
);
3281 RemoveEntryList (&LocalFormSet
->Link
);
3282 DestroyFormSet (LocalFormSet
);
3286 mSystemLevelFormSet
= OldFormSet
;
3293 Submit data for a form.
3295 @param FormSet FormSet data structure.
3296 @param Form Form data structure.
3298 @retval EFI_SUCCESS The function completed successfully.
3299 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3304 IN FORM_BROWSER_FORMSET
*FormSet
,
3305 IN FORM_BROWSER_FORM
*Form
3310 EFI_STRING ConfigResp
;
3311 EFI_STRING Progress
;
3312 BROWSER_STORAGE
*Storage
;
3313 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3314 BOOLEAN SubmitFormFail
;
3316 SubmitFormFail
= FALSE
;
3318 if (!IsNvUpdateRequiredForForm (Form
)) {
3322 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3323 if (EFI_ERROR (Status
)) {
3327 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3328 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3329 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3330 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3332 Storage
= ConfigInfo
->Storage
;
3333 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3338 // Skip if there is no RequestElement
3340 if (ConfigInfo
->ElementCount
== 0) {
3345 // 1. Prepare <ConfigResp>
3347 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3348 if (EFI_ERROR (Status
)) {
3353 // 2. Set value to hii config routine protocol.
3355 Status
= mHiiConfigRouting
->RouteConfig (
3361 if (EFI_ERROR (Status
)) {
3363 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3365 SubmitFormFail
= TRUE
;
3366 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3367 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3368 FreePool (ConfigResp
);
3372 FreePool (ConfigResp
);
3374 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3376 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3380 // 4. Process the save failed storage.
3382 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3383 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3384 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3385 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3386 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3387 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3389 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3390 // base on the SyncConfigRequest to Sync the buffer.
3392 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3393 FreePool (ConfigInfo
->RestoreConfigRequest
);
3394 ConfigInfo
->RestoreConfigRequest
= NULL
;
3395 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3396 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3397 FreePool (ConfigInfo
->SyncConfigRequest
);
3398 ConfigInfo
->SyncConfigRequest
= NULL
;
3401 Status
= EFI_SUCCESS
;
3403 SendDiscardInfoToDriver (FormSet
,Form
);
3405 Status
= EFI_UNSUPPORTED
;
3409 // Free Form save fail list.
3411 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3412 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3413 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3414 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3419 // 5. Update the NV flag.
3421 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3424 // 6 Call callback with Submitted type to inform the driver.
3426 if (!SubmitFormFail
) {
3427 SubmitCallback (FormSet
, Form
);
3434 Submit data for a formset.
3436 @param FormSet FormSet data structure.
3437 @param SkipProcessFail Whether skip to process the save failed storage.
3438 If submit formset is called when do system level save,
3439 set this value to true and process the failed formset
3441 if submit formset is called when do formset level save,
3442 set the value to false and process the failed storage
3443 right after process all storages for this formset.
3445 @retval EFI_SUCCESS The function completed successfully.
3446 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3451 IN FORM_BROWSER_FORMSET
*FormSet
,
3452 IN BOOLEAN SkipProcessFail
3457 EFI_STRING ConfigResp
;
3458 EFI_STRING Progress
;
3459 BROWSER_STORAGE
*Storage
;
3460 FORMSET_STORAGE
*FormSetStorage
;
3461 FORM_BROWSER_FORM
*Form
;
3462 BOOLEAN HasInserted
;
3463 FORM_BROWSER_STATEMENT
*Question
;
3464 BOOLEAN SubmitFormSetFail
;
3465 BOOLEAN DiscardChange
;
3467 HasInserted
= FALSE
;
3468 SubmitFormSetFail
= FALSE
;
3469 DiscardChange
= FALSE
;
3471 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3476 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3477 if (EFI_ERROR (Status
)) {
3478 if (SkipProcessFail
) {
3480 // Process NO_SUBMIT check first, so insert it at head.
3482 FormSet
->SaveFailForm
= Form
;
3483 FormSet
->SaveFailStatement
= Question
;
3484 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3493 // Submit Buffer storage or Name/Value storage
3495 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3496 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3497 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3498 Storage
= FormSetStorage
->BrowserStorage
;
3499 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3501 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3506 // Skip if there is no RequestElement
3508 if (FormSetStorage
->ElementCount
== 0) {
3513 // 1. Prepare <ConfigResp>
3515 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3516 if (EFI_ERROR (Status
)) {
3521 // 2. Send <ConfigResp> to Routine config Protocol.
3523 Status
= mHiiConfigRouting
->RouteConfig (
3528 if (EFI_ERROR (Status
)) {
3530 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3532 SubmitFormSetFail
= TRUE
;
3533 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3534 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3537 // Call submit formset for system level, save the formset info
3538 // and process later.
3540 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3541 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3542 FormSet
->SaveFailForm
= Form
;
3543 FormSet
->SaveFailStatement
= Question
;
3544 if (SkipProcessFail
) {
3545 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3550 FreePool (ConfigResp
);
3554 FreePool (ConfigResp
);
3556 // 3. Config success, update storage shadow Buffer
3558 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3562 // 4. Has save fail storage need to handle.
3565 if (!SkipProcessFail
) {
3567 // If not in system level, just handl the save failed storage here.
3569 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3570 DiscardChange
= TRUE
;
3571 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3572 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3573 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3574 Storage
= FormSetStorage
->BrowserStorage
;
3575 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3577 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3578 // base on the SyncConfigRequest to Sync the buffer.
3580 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3581 FreePool (FormSetStorage
->RestoreConfigRequest
);
3582 FormSetStorage
->RestoreConfigRequest
= NULL
;
3583 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3584 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3585 FreePool (FormSetStorage
->SyncConfigRequest
);
3586 FormSetStorage
->SyncConfigRequest
= NULL
;
3589 Status
= EFI_SUCCESS
;
3592 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3594 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3595 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3596 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3597 gCurrentSelection
->FormId
= Form
->FormId
;
3598 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3600 Status
= EFI_UNSUPPORTED
;
3604 // Free FormSet save fail list.
3606 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3607 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3608 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3609 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3613 // If in system level, just return error and handle the failed formset later.
3615 Status
= EFI_UNSUPPORTED
;
3620 // If user discard the change, send the discard info to driver.
3622 if (DiscardChange
) {
3623 Link
= GetFirstNode (&FormSet
->FormListHead
);
3624 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3625 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3626 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3628 // Call callback with Changed type to inform the driver.
3630 SendDiscardInfoToDriver (FormSet
, Form
);
3635 // 5. Update the NV flag.
3637 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3640 // 6. Call callback with Submitted type to inform the driver.
3642 if (!SubmitFormSetFail
) {
3643 SubmitCallback (FormSet
, NULL
);
3650 Submit data for all formsets.
3652 @retval EFI_SUCCESS The function completed successfully.
3653 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3663 LIST_ENTRY
*FormLink
;
3664 LIST_ENTRY
*StorageLink
;
3665 FORMSET_STORAGE
*FormSetStorage
;
3666 FORM_BROWSER_FORM
*Form
;
3667 FORM_BROWSER_FORMSET
*LocalFormSet
;
3668 UINT32 UserSelection
;
3669 FORM_BROWSER_STATEMENT
*Question
;
3671 mSystemSubmit
= TRUE
;
3672 Link
= GetFirstNode (&gBrowserFormSetList
);
3673 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3674 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3675 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3676 if (!ValidateFormSet(LocalFormSet
)) {
3680 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3681 if (EFI_ERROR (Status
)) {
3686 // Remove maintain backup list after save except for the current using FormSet.
3688 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3689 CleanBrowserStorage(LocalFormSet
);
3690 RemoveEntryList (&LocalFormSet
->Link
);
3691 DestroyFormSet (LocalFormSet
);
3694 mSystemSubmit
= FALSE
;
3696 Status
= EFI_SUCCESS
;
3699 // Process the save failed formsets.
3701 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3702 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3703 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3704 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3706 if (!ValidateFormSet(LocalFormSet
)) {
3710 Form
= LocalFormSet
->SaveFailForm
;
3711 Question
= LocalFormSet
->SaveFailStatement
;
3714 // Confirm with user, get user input.
3716 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3718 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3720 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3722 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3725 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3726 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3727 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3728 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3729 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3730 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3732 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3735 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3736 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3737 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3738 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3740 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3741 // base on the SyncConfigRequest to Sync the buffer.
3743 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3744 FreePool (FormSetStorage
->RestoreConfigRequest
);
3745 FormSetStorage
->RestoreConfigRequest
= NULL
;
3746 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3747 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3748 FreePool (FormSetStorage
->SyncConfigRequest
);
3749 FormSetStorage
->SyncConfigRequest
= NULL
;
3754 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3755 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3756 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3757 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3759 // Call callback with Changed type to inform the driver.
3761 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3764 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3765 CleanBrowserStorage(LocalFormSet
);
3766 RemoveEntryList (&LocalFormSet
->Link
);
3767 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3768 DestroyFormSet (LocalFormSet
);
3770 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3773 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3774 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3777 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3779 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3780 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3781 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3782 gCurrentSelection
->FormId
= Form
->FormId
;
3783 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3785 Status
= EFI_UNSUPPORTED
;
3791 // Clean the list which will not process.
3793 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3794 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3795 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3796 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3798 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3799 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3800 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3801 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3809 Submit data based on the input Setting level (Form, FormSet or System).
3811 @param FormSet FormSet data structure.
3812 @param Form Form data structure.
3813 @param SettingScope Setting Scope for Submit action.
3815 @retval EFI_SUCCESS The function completed successfully.
3816 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3821 IN FORM_BROWSER_FORMSET
*FormSet
,
3822 IN FORM_BROWSER_FORM
*Form
,
3823 IN BROWSER_SETTING_SCOPE SettingScope
3828 switch (SettingScope
) {
3830 Status
= SubmitForForm(FormSet
, Form
);
3834 Status
= SubmitForFormSet (FormSet
, FALSE
);
3838 Status
= SubmitForSystem ();
3842 Status
= EFI_UNSUPPORTED
;
3850 Converts the unicode character of the string from uppercase to lowercase.
3851 This is a internal function.
3853 @param ConfigString String to be converted
3859 IN EFI_STRING ConfigString
3865 ASSERT (ConfigString
!= NULL
);
3868 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3870 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3871 if (*String
== L
'=') {
3873 } else if (*String
== L
'&') {
3875 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3876 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3882 Find the point in the ConfigResp string for this question.
3884 @param Question The question.
3885 @param ConfigResp Get ConfigResp string.
3887 @retval point to the offset where is for this question.
3891 GetOffsetFromConfigResp (
3892 IN FORM_BROWSER_STATEMENT
*Question
,
3893 IN CHAR16
*ConfigResp
3896 CHAR16
*RequestElement
;
3900 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3902 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3903 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3904 if (RequestElement
!= NULL
) {
3906 // Skip the "VariableName=" field.
3908 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3911 return RequestElement
;
3915 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3919 // Convert all hex digits in ConfigResp to lower case before searching.
3921 HiiToLower (ConfigResp
);
3924 // 1. Directly use Question->BlockName to find.
3926 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3927 if (RequestElement
!= NULL
) {
3929 // Skip the "Question->BlockName&VALUE=" field.
3931 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3932 return RequestElement
;
3936 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3938 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3939 ASSERT (BlockData
!= NULL
);
3940 HiiToLower (BlockData
);
3941 RequestElement
= StrStr (ConfigResp
, BlockData
);
3942 FreePool (BlockData
);
3944 if (RequestElement
!= NULL
) {
3946 // Skip the "Question->BlockName&VALUE=" field.
3948 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3951 return RequestElement
;
3955 Get Question default value from AltCfg string.
3957 @param FormSet The form set.
3958 @param Form The form
3959 @param Question The question.
3961 @retval EFI_SUCCESS Question is reset to default value.
3965 GetDefaultValueFromAltCfg (
3966 IN FORM_BROWSER_FORMSET
*FormSet
,
3967 IN FORM_BROWSER_FORM
*Form
,
3968 IN OUT FORM_BROWSER_STATEMENT
*Question
3971 BROWSER_STORAGE
*Storage
;
3972 FORMSET_STORAGE
*FormSetStorage
;
3976 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3978 Storage
= Question
->Storage
;
3979 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3980 return EFI_NOT_FOUND
;
3984 // Try to get AltCfg string from form. If not found it, then
3985 // try to get it from formset.
3988 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3989 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3990 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3991 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3993 if (Storage
== ConfigInfo
->Storage
) {
3994 ConfigResp
= ConfigInfo
->ConfigAltResp
;
3999 if (ConfigResp
== NULL
) {
4000 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4001 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4002 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4003 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4005 if (Storage
== FormSetStorage
->BrowserStorage
) {
4006 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4012 if (ConfigResp
== NULL
) {
4013 return EFI_NOT_FOUND
;
4016 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4017 if (Value
== NULL
) {
4018 return EFI_NOT_FOUND
;
4021 return BufferToValue (Question
, Value
);
4025 Get default Id value used for browser.
4027 @param DefaultId The default id value used by hii.
4029 @retval Browser used default value.
4033 GetDefaultIdForCallBack (
4037 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4038 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4039 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4040 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4041 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4042 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4043 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
4044 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4045 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
4046 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4047 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
4048 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4057 Return data element in an Array by its Index.
4059 @param Array The data array.
4060 @param Type Type of the data in this array.
4061 @param Index Zero based index for data in this array.
4063 @retval Value The data to be returned
4075 ASSERT (Array
!= NULL
);
4079 case EFI_IFR_TYPE_NUM_SIZE_8
:
4080 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
4083 case EFI_IFR_TYPE_NUM_SIZE_16
:
4084 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
4087 case EFI_IFR_TYPE_NUM_SIZE_32
:
4088 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
4091 case EFI_IFR_TYPE_NUM_SIZE_64
:
4092 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4104 Set value of a data element in an Array by its Index.
4106 @param Array The data array.
4107 @param Type Type of the data in this array.
4108 @param Index Zero based index for data in this array.
4109 @param Value The value to be set.
4121 ASSERT (Array
!= NULL
);
4124 case EFI_IFR_TYPE_NUM_SIZE_8
:
4125 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4128 case EFI_IFR_TYPE_NUM_SIZE_16
:
4129 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4132 case EFI_IFR_TYPE_NUM_SIZE_32
:
4133 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4136 case EFI_IFR_TYPE_NUM_SIZE_64
:
4137 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4146 Search an Option of a Question by its value.
4148 @param Question The Question
4149 @param OptionValue Value for Option to be searched.
4151 @retval Pointer Pointer to the found Option.
4152 @retval NULL Option not found.
4157 IN FORM_BROWSER_STATEMENT
*Question
,
4158 IN EFI_HII_VALUE
*OptionValue
4162 QUESTION_OPTION
*Option
;
4165 Link
= GetFirstNode (&Question
->OptionListHead
);
4166 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4167 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4169 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4171 // Check the suppressif condition, only a valid option can be return.
4173 if ((Option
->SuppressExpression
== NULL
) ||
4174 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4179 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4187 Reset Question to its default value.
4189 @param FormSet The form set.
4190 @param Form The form.
4191 @param Question The question.
4192 @param DefaultId The Class of the default.
4194 @retval EFI_SUCCESS Question is reset to default value.
4198 GetQuestionDefault (
4199 IN FORM_BROWSER_FORMSET
*FormSet
,
4200 IN FORM_BROWSER_FORM
*Form
,
4201 IN FORM_BROWSER_STATEMENT
*Question
,
4207 QUESTION_DEFAULT
*Default
;
4208 QUESTION_OPTION
*Option
;
4209 EFI_HII_VALUE
*HiiValue
;
4211 EFI_STRING StrValue
;
4212 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4213 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4216 EFI_IFR_TYPE_VALUE
*TypeValue
;
4217 UINT16 OriginalDefaultId
;
4218 FORMSET_DEFAULTSTORE
*DefaultStore
;
4219 LIST_ENTRY
*DefaultLink
;
4221 Status
= EFI_NOT_FOUND
;
4223 OriginalDefaultId
= DefaultId
;
4224 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4227 // Statement don't have storage, skip them
4229 if (Question
->QuestionId
== 0) {
4234 // There are Five ways to specify default value for a Question:
4235 // 1, use call back function (highest priority)
4236 // 2, use ExtractConfig function
4237 // 3, use nested EFI_IFR_DEFAULT
4238 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4239 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4242 HiiValue
= &Question
->HiiValue
;
4243 TypeValue
= &HiiValue
->Value
;
4244 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4246 // For orderedlist, need to pass the BufferValue to Callback function.
4248 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4252 // Get Question defaut value from call back function.
4254 ConfigAccess
= FormSet
->ConfigAccess
;
4255 Action
= GetDefaultIdForCallBack (DefaultId
);
4256 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4257 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4258 Status
= ConfigAccess
->Callback (
4261 Question
->QuestionId
,
4266 if (!EFI_ERROR (Status
)) {
4267 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4268 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4269 ASSERT (NewString
!= NULL
);
4271 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4272 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4273 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4274 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4276 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4279 FreePool (NewString
);
4286 // Get default value from altcfg string.
4288 if (ConfigAccess
!= NULL
) {
4289 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4290 if (!EFI_ERROR (Status
)) {
4296 // EFI_IFR_DEFAULT has highest priority
4298 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4299 Link
= GetFirstNode (&Question
->DefaultListHead
);
4300 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4301 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4303 if (Default
->DefaultId
== DefaultId
) {
4304 if (Default
->ValueExpression
!= NULL
) {
4306 // Default is provided by an Expression, evaluate it
4308 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4309 if (EFI_ERROR (Status
)) {
4313 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4314 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4315 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4316 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4317 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4319 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4320 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4322 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4324 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4325 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4328 // Default value is embedded in EFI_IFR_DEFAULT
4330 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4331 ASSERT (HiiValue
->Buffer
!= NULL
);
4332 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4334 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4338 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4339 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4340 if (StrValue
== NULL
) {
4341 return EFI_NOT_FOUND
;
4343 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4344 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4345 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4347 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4354 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4359 // EFI_ONE_OF_OPTION
4361 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4362 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4364 // OneOfOption could only provide Standard and Manufacturing default
4366 Link
= GetFirstNode (&Question
->OptionListHead
);
4367 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4368 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4369 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4371 if ((Option
->SuppressExpression
!= NULL
) &&
4372 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4376 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4377 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4379 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4388 // EFI_IFR_CHECKBOX - lowest priority
4390 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4391 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4393 // Checkbox could only provide Standard and Manufacturing default
4395 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4396 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4398 HiiValue
->Value
.b
= TRUE
;
4406 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4407 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4408 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4410 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4411 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4412 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4413 DefaultId
= DefaultStore
->DefaultId
;
4414 if (DefaultId
== OriginalDefaultId
) {
4421 // For Questions without default value for all the default id in the DefaultStoreList.
4423 Status
= EFI_NOT_FOUND
;
4424 switch (Question
->Operand
) {
4425 case EFI_IFR_CHECKBOX_OP
:
4426 HiiValue
->Value
.b
= FALSE
;
4427 Status
= EFI_SUCCESS
;
4430 case EFI_IFR_NUMERIC_OP
:
4432 // Take minimum value as numeric default value
4434 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4436 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4438 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4439 case EFI_IFR_NUMERIC_SIZE_1
:
4440 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4441 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4442 Status
= EFI_SUCCESS
;
4445 case EFI_IFR_NUMERIC_SIZE_2
:
4446 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4447 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4448 Status
= EFI_SUCCESS
;
4451 case EFI_IFR_NUMERIC_SIZE_4
:
4452 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4453 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4454 Status
= EFI_SUCCESS
;
4457 case EFI_IFR_NUMERIC_SIZE_8
:
4458 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4459 HiiValue
->Value
.u64
= Question
->Minimum
;
4460 Status
= EFI_SUCCESS
;
4467 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4468 HiiValue
->Value
.u64
= Question
->Minimum
;
4469 Status
= EFI_SUCCESS
;
4474 case EFI_IFR_ONE_OF_OP
:
4476 // Take first oneof option as oneof's default value
4478 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4479 Link
= GetFirstNode (&Question
->OptionListHead
);
4480 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4481 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4482 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4484 if ((Option
->SuppressExpression
!= NULL
) &&
4485 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4489 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4490 Status
= EFI_SUCCESS
;
4496 case EFI_IFR_ORDERED_LIST_OP
:
4498 // Take option sequence in IFR as ordered list's default value
4501 Link
= GetFirstNode (&Question
->OptionListHead
);
4502 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4503 Status
= EFI_SUCCESS
;
4504 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4505 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4507 if ((Option
->SuppressExpression
!= NULL
) &&
4508 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4512 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4515 if (Index
>= Question
->MaxContainers
) {
4529 Get AltCfg string for current form.
4531 @param FormSet Form data structure.
4532 @param Form Form data structure.
4533 @param DefaultId The Class of the default.
4534 @param BrowserStorage The input request storage for the questions.
4538 ExtractAltCfgForForm (
4539 IN FORM_BROWSER_FORMSET
*FormSet
,
4540 IN FORM_BROWSER_FORM
*Form
,
4541 IN UINT16 DefaultId
,
4542 IN BROWSER_STORAGE
*BrowserStorage
4550 BROWSER_STORAGE
*Storage
;
4551 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4552 FORMSET_STORAGE
*FormSetStorage
;
4555 // Check whether has get AltCfg string for this formset.
4556 // If yes, no need to get AltCfg for form.
4558 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4559 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4560 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4561 Storage
= FormSetStorage
->BrowserStorage
;
4562 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4563 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4567 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4568 FormSetStorage
->ElementCount
!= 0 &&
4569 FormSetStorage
->HasCallAltCfg
) {
4575 // Get AltCfg string for each form.
4577 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4578 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4579 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4580 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4582 Storage
= ConfigInfo
->Storage
;
4583 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4587 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4592 // 1. Skip if there is no RequestElement
4594 if (ConfigInfo
->ElementCount
== 0) {
4599 // 2. Get value through hii config routine protocol.
4601 Status
= mHiiConfigRouting
->ExtractConfig (
4603 ConfigInfo
->ConfigRequest
,
4607 if (EFI_ERROR (Status
)) {
4612 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4613 // Get the default configuration string according to the default ID.
4615 Status
= mHiiConfigRouting
->GetAltConfig (
4621 &DefaultId
, // it can be NULL to get the current setting.
4625 if (EFI_ERROR (Status
)) {
4629 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4634 Clean AltCfg string for current form.
4636 @param Form Form data structure.
4640 CleanAltCfgForForm (
4641 IN FORM_BROWSER_FORM
*Form
4645 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4647 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4648 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4649 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4650 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4652 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4653 FreePool (ConfigInfo
->ConfigAltResp
);
4654 ConfigInfo
->ConfigAltResp
= NULL
;
4660 Get AltCfg string for current formset.
4662 @param FormSet Form data structure.
4663 @param DefaultId The Class of the default.
4664 @param BrowserStorage The input request storage for the questions.
4668 ExtractAltCfgForFormSet (
4669 IN FORM_BROWSER_FORMSET
*FormSet
,
4670 IN UINT16 DefaultId
,
4671 IN BROWSER_STORAGE
*BrowserStorage
4679 BROWSER_STORAGE
*Storage
;
4680 FORMSET_STORAGE
*FormSetStorage
;
4682 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4683 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4684 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4685 Storage
= FormSetStorage
->BrowserStorage
;
4686 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4688 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4692 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4697 // 1. Skip if there is no RequestElement
4699 if (FormSetStorage
->ElementCount
== 0) {
4703 FormSetStorage
->HasCallAltCfg
= TRUE
;
4706 // 2. Get value through hii config routine protocol.
4708 Status
= mHiiConfigRouting
->ExtractConfig (
4710 FormSetStorage
->ConfigRequest
,
4714 if (EFI_ERROR (Status
)) {
4719 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4720 // Get the default configuration string according to the default ID.
4722 Status
= mHiiConfigRouting
->GetAltConfig (
4728 &DefaultId
, // it can be NULL to get the current setting.
4733 if (EFI_ERROR (Status
)) {
4737 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4743 Clean AltCfg string for current formset.
4745 @param FormSet Form data structure.
4749 CleanAltCfgForFormSet (
4750 IN FORM_BROWSER_FORMSET
*FormSet
4754 FORMSET_STORAGE
*FormSetStorage
;
4756 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4757 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4758 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4759 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4761 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4762 FreePool (FormSetStorage
->ConfigAltResp
);
4763 FormSetStorage
->ConfigAltResp
= NULL
;
4766 FormSetStorage
->HasCallAltCfg
= FALSE
;
4771 Reset Questions to their initial value or default value in a Form, Formset or System.
4773 GetDefaultValueScope parameter decides which questions will reset
4774 to its default value.
4776 @param FormSet FormSet data structure.
4777 @param Form Form data structure.
4778 @param DefaultId The Class of the default.
4779 @param SettingScope Setting Scope for Default action.
4780 @param GetDefaultValueScope Get default value scope.
4781 @param Storage Get default value only for this storage.
4782 @param RetrieveValueFirst Whether call the retrieve call back to
4783 get the initial value before get default
4785 @param SkipGetAltCfg Whether skip the get altcfg string process.
4787 @retval EFI_SUCCESS The function completed successfully.
4788 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4793 IN FORM_BROWSER_FORMSET
*FormSet
,
4794 IN FORM_BROWSER_FORM
*Form
,
4795 IN UINT16 DefaultId
,
4796 IN BROWSER_SETTING_SCOPE SettingScope
,
4797 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4798 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4799 IN BOOLEAN RetrieveValueFirst
,
4800 IN BOOLEAN SkipGetAltCfg
4804 LIST_ENTRY
*FormLink
;
4806 FORM_BROWSER_STATEMENT
*Question
;
4807 FORM_BROWSER_FORMSET
*LocalFormSet
;
4808 FORM_BROWSER_FORMSET
*OldFormSet
;
4810 Status
= EFI_SUCCESS
;
4813 // Check the supported setting level.
4815 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4816 return EFI_UNSUPPORTED
;
4819 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4820 return EFI_UNSUPPORTED
;
4823 if (SettingScope
== FormLevel
) {
4825 // Prepare the AltCfg String for form.
4827 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4828 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4832 // Extract Form default
4834 Link
= GetFirstNode (&Form
->StatementListHead
);
4835 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4836 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4837 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4840 // If get default value only for this storage, check the storage first.
4842 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4847 // If get default value only for no storage question, just skip the question which has storage.
4849 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4854 // If Question is disabled, don't reset it to default
4856 if (Question
->Expression
!= NULL
) {
4857 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4862 if (RetrieveValueFirst
) {
4864 // Call the Retrieve call back to get the initial question value.
4866 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4870 // If not request to get the initial value or get initial value fail, then get default value.
4872 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4873 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4874 if (EFI_ERROR (Status
)) {
4880 // Synchronize Buffer storage's Edit buffer
4882 if ((Question
->Storage
!= NULL
) &&
4883 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4884 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4889 // Clean the AltCfg String.
4891 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4892 CleanAltCfgForForm(Form
);
4894 } else if (SettingScope
== FormSetLevel
) {
4896 // Prepare the AltCfg String for formset.
4898 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4899 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4902 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4903 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4904 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4905 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4906 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4910 // Clean the AltCfg String.
4912 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4913 CleanAltCfgForFormSet (FormSet
);
4915 } else if (SettingScope
== SystemLevel
) {
4917 // Preload all Hii formset.
4919 LoadAllHiiFormset();
4921 OldFormSet
= mSystemLevelFormSet
;
4924 // Set Default Value for each FormSet in the maintain list.
4926 Link
= GetFirstNode (&gBrowserFormSetList
);
4927 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4928 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4929 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4930 if (!ValidateFormSet(LocalFormSet
)) {
4934 mSystemLevelFormSet
= LocalFormSet
;
4936 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4939 mSystemLevelFormSet
= OldFormSet
;
4947 Validate whether this question's value has changed.
4949 @param FormSet FormSet data structure.
4950 @param Form Form data structure.
4951 @param Question Question to be initialized.
4952 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4954 @retval TRUE Question's value has changed.
4955 @retval FALSE Question's value has not changed
4959 IsQuestionValueChanged (
4960 IN FORM_BROWSER_FORMSET
*FormSet
,
4961 IN FORM_BROWSER_FORM
*Form
,
4962 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4963 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4966 EFI_HII_VALUE BackUpValue
;
4967 CHAR8
*BackUpBuffer
;
4968 EFI_HII_VALUE BackUpValue2
;
4969 CHAR8
*BackUpBuffer2
;
4971 BOOLEAN ValueChanged
;
4975 // For quetion without storage, always mark it as data not changed.
4977 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4981 BackUpBuffer
= NULL
;
4982 BackUpBuffer2
= NULL
;
4983 ValueChanged
= FALSE
;
4985 switch (Question
->Operand
) {
4986 case EFI_IFR_ORDERED_LIST_OP
:
4987 BufferWidth
= Question
->StorageWidth
;
4988 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4989 ASSERT (BackUpBuffer
!= NULL
);
4992 case EFI_IFR_STRING_OP
:
4993 case EFI_IFR_PASSWORD_OP
:
4994 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
4995 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4996 ASSERT (BackUpBuffer
!= NULL
);
5003 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5005 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5006 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5007 ASSERT_EFI_ERROR(Status
);
5009 switch (Question
->Operand
) {
5010 case EFI_IFR_ORDERED_LIST_OP
:
5011 BufferWidth
= Question
->StorageWidth
;
5012 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5013 ASSERT (BackUpBuffer2
!= NULL
);
5016 case EFI_IFR_STRING_OP
:
5017 case EFI_IFR_PASSWORD_OP
:
5018 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5019 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5020 ASSERT (BackUpBuffer2
!= NULL
);
5027 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5029 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5030 ASSERT_EFI_ERROR(Status
);
5032 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5033 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
5034 ValueChanged
= TRUE
;
5037 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5038 ASSERT_EFI_ERROR(Status
);
5040 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5041 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
5042 ValueChanged
= TRUE
;
5046 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5047 if (BackUpBuffer
!= NULL
) {
5048 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5049 FreePool (BackUpBuffer
);
5052 if (BackUpBuffer2
!= NULL
) {
5053 FreePool (BackUpBuffer2
);
5056 Question
->ValueChanged
= ValueChanged
;
5058 return ValueChanged
;
5062 Initialize Question's Edit copy from Storage.
5064 @param Selection Selection contains the information about
5065 the Selection, form and formset to be displayed.
5066 Selection action may be updated in retrieve callback.
5067 If Selection is NULL, only initialize Question value.
5068 @param FormSet FormSet data structure.
5069 @param Form Form data structure.
5071 @retval EFI_SUCCESS The function completed successfully.
5076 IN OUT UI_MENU_SELECTION
*Selection
,
5077 IN FORM_BROWSER_FORMSET
*FormSet
,
5078 IN FORM_BROWSER_FORM
*Form
5083 FORM_BROWSER_STATEMENT
*Question
;
5085 Link
= GetFirstNode (&Form
->StatementListHead
);
5086 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5087 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5090 // Initialize local copy of Value for each Question
5092 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
5093 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5095 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5097 if (EFI_ERROR (Status
)) {
5101 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5102 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5105 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5112 Initialize Question's Edit copy from Storage for the whole Formset.
5114 @param Selection Selection contains the information about
5115 the Selection, form and formset to be displayed.
5116 Selection action may be updated in retrieve callback.
5117 If Selection is NULL, only initialize Question value.
5118 @param FormSet FormSet data structure.
5120 @retval EFI_SUCCESS The function completed successfully.
5125 IN OUT UI_MENU_SELECTION
*Selection
,
5126 IN FORM_BROWSER_FORMSET
*FormSet
5131 FORM_BROWSER_FORM
*Form
;
5133 Link
= GetFirstNode (&FormSet
->FormListHead
);
5134 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5138 // Initialize local copy of Value for each Form
5140 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5141 if (EFI_ERROR (Status
)) {
5145 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5149 // Finished question initialization.
5151 FormSet
->QuestionInited
= TRUE
;
5157 Remove the Request element from the Config Request.
5159 @param Storage Pointer to the browser storage.
5160 @param RequestElement The pointer to the Request element.
5165 IN OUT BROWSER_STORAGE
*Storage
,
5166 IN CHAR16
*RequestElement
5172 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5174 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5176 if (NewStr
== NULL
) {
5181 // Remove this element from this ConfigRequest.
5184 NewStr
+= StrLen (RequestElement
);
5185 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5187 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5191 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5193 @param Storage Pointer to the formset storage.
5194 @param ConfigRequest The pointer to the Request element.
5198 RemoveConfigRequest (
5199 FORMSET_STORAGE
*Storage
,
5200 CHAR16
*ConfigRequest
5203 CHAR16
*RequestElement
;
5204 CHAR16
*NextRequestElement
;
5208 // No request element in it, just return.
5210 if (ConfigRequest
== NULL
) {
5214 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5216 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5221 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5223 SearchKey
= L
"&OFFSET";
5227 // Find SearchKey storage
5229 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5230 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5231 ASSERT (RequestElement
!= NULL
);
5232 RequestElement
= StrStr (RequestElement
, SearchKey
);
5234 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5237 while (RequestElement
!= NULL
) {
5239 // +1 to avoid find header itself.
5241 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5244 // The last Request element in configRequest string.
5246 if (NextRequestElement
!= NULL
) {
5248 // Replace "&" with '\0'.
5250 *NextRequestElement
= L
'\0';
5253 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5255 if (NextRequestElement
!= NULL
) {
5257 // Restore '&' with '\0' for later used.
5259 *NextRequestElement
= L
'&';
5262 RequestElement
= NextRequestElement
;
5266 // If no request element remain, just remove the ConfigRequest string.
5268 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5269 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5270 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5271 Storage
->BrowserStorage
->SpareStrLen
= 0;
5276 Base on the current formset info, clean the ConfigRequest string in browser storage.
5278 @param FormSet Pointer of the FormSet
5282 CleanBrowserStorage (
5283 IN OUT FORM_BROWSER_FORMSET
*FormSet
5287 FORMSET_STORAGE
*Storage
;
5289 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5290 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5291 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5292 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5294 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5295 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5299 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5300 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5301 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5302 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5303 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5304 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5306 Storage
->BrowserStorage
->Initialized
= FALSE
;
5312 Check whether current element in the ConfigReqeust string.
5314 @param BrowserStorage Storage which includes ConfigReqeust.
5315 @param RequestElement New element need to check.
5317 @retval TRUE The Element is in the ConfigReqeust string.
5318 @retval FALSE The Element not in the configReqeust String.
5323 BROWSER_STORAGE
*BrowserStorage
,
5324 CHAR16
*RequestElement
5327 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5331 Append the Request element to the Config Request.
5333 @param ConfigRequest Current ConfigRequest info.
5334 @param SpareStrLen Current remain free buffer for config reqeust.
5335 @param RequestElement New Request element.
5339 AppendConfigRequest (
5340 IN OUT CHAR16
**ConfigRequest
,
5341 IN OUT UINTN
*SpareStrLen
,
5342 IN CHAR16
*RequestElement
5350 StrLength
= StrLen (RequestElement
);
5351 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5352 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5355 // Append <RequestElement> to <ConfigRequest>
5357 if (StrLength
> *SpareStrLen
) {
5359 // Old String buffer is not sufficient for RequestElement, allocate a new one
5361 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5362 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5363 ASSERT (NewStr
!= NULL
);
5365 if (*ConfigRequest
!= NULL
) {
5366 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5367 FreePool (*ConfigRequest
);
5369 *ConfigRequest
= NewStr
;
5370 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5373 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5374 *SpareStrLen
-= StrLength
;
5378 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5380 @param Storage Form set Storage.
5381 @param Request The input request string.
5382 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5384 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5385 @retval FALSE All elements covered by current used elements.
5389 ConfigRequestAdjust (
5390 IN BROWSER_STORAGE
*Storage
,
5392 IN BOOLEAN RespString
5395 CHAR16
*RequestElement
;
5396 CHAR16
*NextRequestElement
;
5397 CHAR16
*NextElementBakup
;
5401 CHAR16
*ConfigRequest
;
5404 NextElementBakup
= NULL
;
5407 if (Request
!= NULL
) {
5408 ConfigRequest
= Request
;
5410 ConfigRequest
= Storage
->ConfigRequest
;
5413 if (Storage
->ConfigRequest
== NULL
) {
5414 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5418 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5420 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5425 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5427 SearchKey
= L
"&OFFSET";
5428 ValueKey
= L
"&VALUE";
5432 // Find SearchKey storage
5434 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5435 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5436 ASSERT (RequestElement
!= NULL
);
5437 RequestElement
= StrStr (RequestElement
, SearchKey
);
5439 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5442 while (RequestElement
!= NULL
) {
5445 // +1 to avoid find header itself.
5447 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5450 // The last Request element in configRequest string.
5452 if (NextRequestElement
!= NULL
) {
5453 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5454 NextElementBakup
= NextRequestElement
;
5455 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5456 ASSERT (NextRequestElement
!= NULL
);
5459 // Replace "&" with '\0'.
5461 *NextRequestElement
= L
'\0';
5463 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5464 NextElementBakup
= NextRequestElement
;
5465 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5466 ASSERT (NextRequestElement
!= NULL
);
5468 // Replace "&" with '\0'.
5470 *NextRequestElement
= L
'\0';
5474 if (!ElementValidation (Storage
, RequestElement
)) {
5476 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5478 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5482 if (NextRequestElement
!= NULL
) {
5484 // Restore '&' with '\0' for later used.
5486 *NextRequestElement
= L
'&';
5489 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5490 RequestElement
= NextElementBakup
;
5492 RequestElement
= NextRequestElement
;
5500 Fill storage's edit copy with settings requested from Configuration Driver.
5502 @param FormSet FormSet data structure.
5503 @param Storage Buffer Storage.
5508 IN FORM_BROWSER_FORMSET
*FormSet
,
5509 IN FORMSET_STORAGE
*Storage
5513 EFI_STRING Progress
;
5516 EFI_STRING ConfigRequest
;
5519 ConfigRequest
= NULL
;
5521 switch (Storage
->BrowserStorage
->Type
) {
5522 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5525 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5526 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5527 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5532 case EFI_HII_VARSTORE_BUFFER
:
5533 case EFI_HII_VARSTORE_NAME_VALUE
:
5535 // Skip if there is no RequestElement.
5537 if (Storage
->ElementCount
== 0) {
5542 // Just update the ConfigRequest, if storage already initialized.
5544 if (Storage
->BrowserStorage
->Initialized
) {
5545 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5549 Storage
->BrowserStorage
->Initialized
= TRUE
;
5556 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5558 // Create the config request string to get all fields for this storage.
5559 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5560 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5562 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5563 ConfigRequest
= AllocateZeroPool (StrLen
);
5564 ASSERT (ConfigRequest
!= NULL
);
5568 L
"%s&OFFSET=0&WIDTH=%04x",
5570 Storage
->BrowserStorage
->Size
);
5572 ConfigRequest
= Storage
->ConfigRequest
;
5576 // Request current settings from Configuration Driver
5578 Status
= mHiiConfigRouting
->ExtractConfig (
5586 // If get value fail, extract default from IFR binary
5588 if (EFI_ERROR (Status
)) {
5589 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5592 // Convert Result from <ConfigAltResp> to <ConfigResp>
5594 StrPtr
= StrStr (Result
, L
"&GUID=");
5595 if (StrPtr
!= NULL
) {
5599 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5603 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5606 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5608 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5610 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5611 if (ConfigRequest
!= NULL
) {
5612 FreePool (ConfigRequest
);
5618 Get Value changed status from old question.
5620 @param NewFormSet FormSet data structure.
5621 @param OldQuestion Old question which has value changed.
5625 SyncStatusForQuestion (
5626 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5627 IN FORM_BROWSER_STATEMENT
*OldQuestion
5631 LIST_ENTRY
*QuestionLink
;
5632 FORM_BROWSER_FORM
*Form
;
5633 FORM_BROWSER_STATEMENT
*Question
;
5636 // For each form in one formset.
5638 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5639 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5640 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5641 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5644 // for each question in one form.
5646 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5647 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5648 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5649 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5651 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5652 Question
->ValueChanged
= TRUE
;
5660 Get Value changed status from old formset.
5662 @param NewFormSet FormSet data structure.
5663 @param OldFormSet FormSet data structure.
5667 SyncStatusForFormSet (
5668 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5669 IN FORM_BROWSER_FORMSET
*OldFormSet
5673 LIST_ENTRY
*QuestionLink
;
5674 FORM_BROWSER_FORM
*Form
;
5675 FORM_BROWSER_STATEMENT
*Question
;
5678 // For each form in one formset.
5680 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5681 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5682 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5683 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5686 // for each question in one form.
5688 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5689 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5690 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5691 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5693 if (!Question
->ValueChanged
) {
5698 // Find the same question in new formset and update the value changed flag.
5700 SyncStatusForQuestion (NewFormSet
, Question
);
5706 Get current setting of Questions.
5708 @param FormSet FormSet data structure.
5712 InitializeCurrentSetting (
5713 IN OUT FORM_BROWSER_FORMSET
*FormSet
5717 FORMSET_STORAGE
*Storage
;
5718 FORM_BROWSER_FORMSET
*OldFormSet
;
5721 // Try to find pre FormSet in the maintain backup list.
5722 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5724 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5725 if (OldFormSet
!= NULL
) {
5726 SyncStatusForFormSet (FormSet
, OldFormSet
);
5727 RemoveEntryList (&OldFormSet
->Link
);
5728 DestroyFormSet (OldFormSet
);
5730 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5733 // Extract default from IFR binary for no storage questions.
5735 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5738 // Request current settings from Configuration Driver
5740 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5741 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5742 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5744 LoadStorage (FormSet
, Storage
);
5746 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5752 Fetch the Ifr binary data of a FormSet.
5754 @param Handle PackageList Handle
5755 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5756 specified (NULL or zero GUID), take the first
5757 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5758 found in package list.
5759 On output, GUID of the formset found(if not NULL).
5760 @param BinaryLength The length of the FormSet IFR binary.
5761 @param BinaryData The buffer designed to receive the FormSet.
5763 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5764 BufferLength was updated.
5765 @retval EFI_INVALID_PARAMETER The handle is unknown.
5766 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5767 be found with the requested FormId.
5772 IN EFI_HII_HANDLE Handle
,
5773 IN OUT EFI_GUID
*FormSetGuid
,
5774 OUT UINTN
*BinaryLength
,
5775 OUT UINT8
**BinaryData
5779 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5785 UINT32 PackageListLength
;
5786 EFI_HII_PACKAGE_HEADER PackageHeader
;
5788 UINT8 NumberOfClassGuid
;
5789 BOOLEAN ClassGuidMatch
;
5790 EFI_GUID
*ClassGuid
;
5791 EFI_GUID
*ComparingGuid
;
5795 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5798 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5800 if (FormSetGuid
== NULL
) {
5801 ComparingGuid
= &gZeroGuid
;
5803 ComparingGuid
= FormSetGuid
;
5807 // Get HII PackageList
5810 HiiPackageList
= NULL
;
5811 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5812 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5813 HiiPackageList
= AllocatePool (BufferSize
);
5814 ASSERT (HiiPackageList
!= NULL
);
5816 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5818 if (EFI_ERROR (Status
)) {
5821 ASSERT (HiiPackageList
!= NULL
);
5824 // Get Form package from this HII package List
5826 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5828 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5830 ClassGuidMatch
= FALSE
;
5831 while (Offset
< PackageListLength
) {
5832 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5833 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5835 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5837 // Search FormSet in this Form Package
5839 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5840 while (Offset2
< PackageHeader
.Length
) {
5841 OpCodeData
= Package
+ Offset2
;
5843 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5845 // Try to compare against formset GUID
5847 if (IsZeroGuid (FormSetGuid
) ||
5848 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5852 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5854 // Try to compare against formset class GUID
5856 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5857 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5858 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5859 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5860 ClassGuidMatch
= TRUE
;
5864 if (ClassGuidMatch
) {
5867 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5868 ClassGuidMatch
= TRUE
;
5873 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5876 if (Offset2
< PackageHeader
.Length
) {
5878 // Target formset found
5884 Offset
+= PackageHeader
.Length
;
5887 if (Offset
>= PackageListLength
) {
5889 // Form package not found in this Package List
5891 FreePool (HiiPackageList
);
5892 return EFI_NOT_FOUND
;
5895 if (FormSetGuid
!= NULL
) {
5897 // Return the FormSet GUID
5899 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5903 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5904 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5905 // of the Form Package.
5907 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5908 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5910 FreePool (HiiPackageList
);
5912 if (*BinaryData
== NULL
) {
5913 return EFI_OUT_OF_RESOURCES
;
5921 Initialize the internal data structure of a FormSet.
5923 @param Handle PackageList Handle
5924 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5925 specified (NULL or zero GUID), take the first
5926 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5927 found in package list.
5928 On output, GUID of the formset found(if not NULL).
5929 @param FormSet FormSet data structure.
5931 @retval EFI_SUCCESS The function completed successfully.
5932 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5937 IN EFI_HII_HANDLE Handle
,
5938 IN OUT EFI_GUID
*FormSetGuid
,
5939 OUT FORM_BROWSER_FORMSET
*FormSet
5943 EFI_HANDLE DriverHandle
;
5945 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5946 if (EFI_ERROR (Status
)) {
5950 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5951 FormSet
->HiiHandle
= Handle
;
5952 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5953 FormSet
->QuestionInited
= FALSE
;
5956 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5958 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5959 if (EFI_ERROR (Status
)) {
5962 FormSet
->DriverHandle
= DriverHandle
;
5963 Status
= gBS
->HandleProtocol (
5965 &gEfiHiiConfigAccessProtocolGuid
,
5966 (VOID
**) &FormSet
->ConfigAccess
5968 if (EFI_ERROR (Status
)) {
5970 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5971 // list, then there will be no configuration action required
5973 FormSet
->ConfigAccess
= NULL
;
5977 // Parse the IFR binary OpCodes
5979 Status
= ParseOpCodes (FormSet
);
5986 Save globals used by previous call to SendForm(). SendForm() may be called from
5987 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5988 So, save globals of previous call to SendForm() and restore them upon exit.
5992 SaveBrowserContext (
5996 BROWSER_CONTEXT
*Context
;
5997 FORM_ENTRY_INFO
*MenuList
;
5998 FORM_BROWSER_FORMSET
*FormSet
;
6000 gBrowserContextCount
++;
6001 if (gBrowserContextCount
== 1) {
6003 // This is not reentry of SendForm(), no context to save
6008 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6009 ASSERT (Context
!= NULL
);
6011 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6014 // Save FormBrowser context
6016 Context
->Selection
= gCurrentSelection
;
6017 Context
->ResetRequired
= gResetRequiredFormLevel
;
6018 Context
->FlagReconnect
= gFlagReconnect
;
6019 Context
->CallbackReconnect
= gCallbackReconnect
;
6020 Context
->ExitRequired
= gExitRequired
;
6021 Context
->HiiHandle
= mCurrentHiiHandle
;
6022 Context
->FormId
= mCurrentFormId
;
6023 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6024 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6025 Context
->CurFakeQestId
= mCurFakeQestId
;
6026 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6027 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6030 // Save the menu history data.
6032 InitializeListHead(&Context
->FormHistoryList
);
6033 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6034 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6035 RemoveEntryList (&MenuList
->Link
);
6037 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
6041 // Save formset list.
6043 InitializeListHead(&Context
->FormSetList
);
6044 while (!IsListEmpty (&gBrowserFormSetList
)) {
6045 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6046 RemoveEntryList (&FormSet
->Link
);
6048 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
6052 // Insert to FormBrowser context list
6054 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6059 Restore globals used by previous call to SendForm().
6063 RestoreBrowserContext (
6068 BROWSER_CONTEXT
*Context
;
6069 FORM_ENTRY_INFO
*MenuList
;
6070 FORM_BROWSER_FORMSET
*FormSet
;
6072 ASSERT (gBrowserContextCount
!= 0);
6073 gBrowserContextCount
--;
6074 if (gBrowserContextCount
== 0) {
6076 // This is not reentry of SendForm(), no context to restore
6081 ASSERT (!IsListEmpty (&gBrowserContextList
));
6083 Link
= GetFirstNode (&gBrowserContextList
);
6084 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6087 // Restore FormBrowser context
6089 gCurrentSelection
= Context
->Selection
;
6090 gResetRequiredFormLevel
= Context
->ResetRequired
;
6091 gFlagReconnect
= Context
->FlagReconnect
;
6092 gCallbackReconnect
= Context
->CallbackReconnect
;
6093 gExitRequired
= Context
->ExitRequired
;
6094 mCurrentHiiHandle
= Context
->HiiHandle
;
6095 mCurrentFormId
= Context
->FormId
;
6096 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6097 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6098 mCurFakeQestId
= Context
->CurFakeQestId
;
6099 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6100 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6103 // Restore the menu history data.
6105 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6106 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6107 RemoveEntryList (&MenuList
->Link
);
6109 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6113 // Restore the Formset data.
6115 while (!IsListEmpty (&Context
->FormSetList
)) {
6116 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6117 RemoveEntryList (&FormSet
->Link
);
6119 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6123 // Remove from FormBrowser context list
6125 RemoveEntryList (&Context
->Link
);
6126 gBS
->FreePool (Context
);
6130 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6132 @param Handle The Hii Handle.
6134 @return the found FormSet context. If no found, NULL will return.
6137 FORM_BROWSER_FORMSET
*
6138 GetFormSetFromHiiHandle (
6139 EFI_HII_HANDLE Handle
6143 FORM_BROWSER_FORMSET
*FormSet
;
6145 Link
= GetFirstNode (&gBrowserFormSetList
);
6146 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6147 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6148 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6149 if (!ValidateFormSet(FormSet
)) {
6152 if (FormSet
->HiiHandle
== Handle
) {
6161 Check whether the input HII handle is the FormSet that is being used.
6163 @param Handle The Hii Handle.
6165 @retval TRUE HII handle is being used.
6166 @retval FALSE HII handle is not being used.
6170 IsHiiHandleInBrowserContext (
6171 EFI_HII_HANDLE Handle
6175 BROWSER_CONTEXT
*Context
;
6178 // HiiHandle is Current FormSet.
6180 if (mCurrentHiiHandle
== Handle
) {
6185 // Check whether HiiHandle is in BrowserContext.
6187 Link
= GetFirstNode (&gBrowserContextList
);
6188 while (!IsNull (&gBrowserContextList
, Link
)) {
6189 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6190 if (Context
->HiiHandle
== Handle
) {
6192 // HiiHandle is in BrowserContext
6196 Link
= GetNextNode (&gBrowserContextList
, Link
);
6203 Perform Password check.
6204 Passwork may be encrypted by driver that requires the specific check.
6206 @param Form Form where Password Statement is in.
6207 @param Statement Password statement
6208 @param PasswordString Password string to be checked. It may be NULL.
6209 NULL means to restore password.
6210 "" string can be used to checked whether old password does exist.
6212 @return Status Status of Password check.
6217 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6218 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6219 IN EFI_STRING PasswordString OPTIONAL
6223 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6224 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6225 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6226 FORM_BROWSER_STATEMENT
*Question
;
6228 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6229 Question
= GetBrowserStatement(Statement
);
6230 ASSERT (Question
!= NULL
);
6232 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6233 if (ConfigAccess
== NULL
) {
6234 return EFI_UNSUPPORTED
;
6238 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6240 return EFI_UNSUPPORTED
;
6244 // Prepare password string in HII database
6246 if (PasswordString
!= NULL
) {
6247 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6249 IfrTypeValue
.string
= 0;
6253 // Send password to Configuration Driver for validation
6255 Status
= ConfigAccess
->Callback (
6257 EFI_BROWSER_ACTION_CHANGING
,
6258 Question
->QuestionId
,
6259 Question
->HiiValue
.Type
,
6265 // Remove password string from HII database
6267 if (PasswordString
!= NULL
) {
6268 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6275 Find the registered HotKey based on KeyData.
6277 @param[in] KeyData A pointer to a buffer that describes the keystroke
6278 information for the hot key.
6280 @return The registered HotKey context. If no found, NULL will return.
6283 GetHotKeyFromRegisterList (
6284 IN EFI_INPUT_KEY
*KeyData
6288 BROWSER_HOT_KEY
*HotKey
;
6290 Link
= GetFirstNode (&gBrowserHotKeyList
);
6291 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6292 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6293 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6296 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6303 Configure what scope the hot key will impact.
6304 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6305 If no scope is set, the default scope will be FormSet level.
6306 After all registered hot keys are removed, previous Scope can reset to another level.
6308 @param[in] Scope Scope level to be set.
6310 @retval EFI_SUCCESS Scope is set correctly.
6311 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6312 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6318 IN BROWSER_SETTING_SCOPE Scope
6321 if (Scope
>= MaxLevel
) {
6322 return EFI_INVALID_PARAMETER
;
6326 // When no hot key registered in system or on the first setting,
6327 // Scope can be set.
6329 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6330 gBrowserSettingScope
= Scope
;
6331 mBrowserScopeFirstSet
= FALSE
;
6332 } else if (Scope
!= gBrowserSettingScope
) {
6333 return EFI_UNSUPPORTED
;
6340 Register the hot key with its browser action, or unregistered the hot key.
6341 Only support hot key that is not printable character (control key, function key, etc.).
6342 If the action value is zero, the hot key will be unregistered if it has been registered.
6343 If the same hot key has been registered, the new action and help string will override the previous ones.
6345 @param[in] KeyData A pointer to a buffer that describes the keystroke
6346 information for the hot key. Its type is EFI_INPUT_KEY to
6347 be supported by all ConsoleIn devices.
6348 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6349 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6350 @param[in] HelpString Help string that describes the hot key information.
6351 Its value may be NULL for the unregistered hot key.
6353 @retval EFI_SUCCESS Hot key is registered or unregistered.
6354 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6355 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6356 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6357 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6362 IN EFI_INPUT_KEY
*KeyData
,
6364 IN UINT16 DefaultId
,
6365 IN EFI_STRING HelpString OPTIONAL
6368 BROWSER_HOT_KEY
*HotKey
;
6371 // Check input parameters.
6373 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6374 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6375 return EFI_INVALID_PARAMETER
;
6379 // Check whether the input KeyData is in BrowserHotKeyList.
6381 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6384 // Unregister HotKey
6386 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6387 if (HotKey
!= NULL
) {
6389 // The registered HotKey is found.
6390 // Remove it from List, and free its resource.
6392 RemoveEntryList (&HotKey
->Link
);
6393 FreePool (HotKey
->KeyData
);
6394 FreePool (HotKey
->HelpString
);
6398 // The registered HotKey is not found.
6400 return EFI_NOT_FOUND
;
6404 if (HotKey
!= NULL
) {
6405 return EFI_ALREADY_STARTED
;
6409 // Create new Key, and add it into List.
6411 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6412 ASSERT (HotKey
!= NULL
);
6413 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6414 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6415 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6418 // Fill HotKey information.
6420 HotKey
->Action
= Action
;
6421 HotKey
->DefaultId
= DefaultId
;
6422 if (HotKey
->HelpString
!= NULL
) {
6423 FreePool (HotKey
->HelpString
);
6425 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6431 Register Exit handler function.
6432 When more than one handler function is registered, the latter one will override the previous one.
6433 When NULL handler is specified, the previous Exit handler will be unregistered.
6435 @param[in] Handler Pointer to handler function.
6440 RegiserExitHandler (
6441 IN EXIT_HANDLER Handler
6444 ExitHandlerFunction
= Handler
;
6449 Check whether the browser data has been modified.
6451 @retval TRUE Browser data is modified.
6452 @retval FALSE No browser data is modified.
6457 IsBrowserDataModified (
6462 FORM_BROWSER_FORMSET
*FormSet
;
6464 switch (gBrowserSettingScope
) {
6466 if (gCurrentSelection
== NULL
) {
6469 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6472 if (gCurrentSelection
== NULL
) {
6475 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6478 Link
= GetFirstNode (&gBrowserFormSetList
);
6479 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6480 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6481 if (!ValidateFormSet(FormSet
)) {
6485 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6488 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6498 Execute the action requested by the Action parameter.
6500 @param[in] Action Execute the request action.
6501 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6503 @retval EFI_SUCCESS Execute the request action succss.
6504 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6515 FORM_BROWSER_FORMSET
*FormSet
;
6516 FORM_BROWSER_FORM
*Form
;
6518 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6519 return EFI_NOT_READY
;
6522 Status
= EFI_SUCCESS
;
6525 if (gBrowserSettingScope
< SystemLevel
) {
6526 FormSet
= gCurrentSelection
->FormSet
;
6527 Form
= gCurrentSelection
->Form
;
6531 // Executet the discard action.
6533 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6534 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6535 if (EFI_ERROR (Status
)) {
6541 // Executet the difault action.
6543 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6544 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6545 if (EFI_ERROR (Status
)) {
6548 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6552 // Executet the submit action.
6554 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6555 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6556 if (EFI_ERROR (Status
)) {
6562 // Executet the reset action.
6564 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6565 gResetRequiredFormLevel
= TRUE
;
6566 gResetRequiredSystemLevel
= TRUE
;
6570 // Executet the exit action.
6572 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6573 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6574 if (gBrowserSettingScope
== SystemLevel
) {
6575 if (ExitHandlerFunction
!= NULL
) {
6576 ExitHandlerFunction ();
6580 gExitRequired
= TRUE
;
6587 Create reminder to let user to choose save or discard the changed browser data.
6588 Caller can use it to actively check the changed browser data.
6590 @retval BROWSER_NO_CHANGES No browser data is changed.
6591 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6592 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6593 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6603 FORM_BROWSER_FORMSET
*FormSet
;
6604 BOOLEAN IsDataChanged
;
6605 UINT32 DataSavedAction
;
6608 DataSavedAction
= BROWSER_NO_CHANGES
;
6609 IsDataChanged
= FALSE
;
6610 Link
= GetFirstNode (&gBrowserFormSetList
);
6611 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6612 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6613 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6614 if (!ValidateFormSet(FormSet
)) {
6617 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6618 IsDataChanged
= TRUE
;
6624 // No data is changed. No save is required.
6626 if (!IsDataChanged
) {
6627 return DataSavedAction
;
6631 // If data is changed, prompt user to save or discard it.
6634 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6636 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6637 SubmitForm (NULL
, NULL
, SystemLevel
);
6638 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6640 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6641 DiscardForm (NULL
, NULL
, SystemLevel
);
6642 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6644 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6645 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6650 return DataSavedAction
;
6654 Check whether the Reset Required for the browser
6656 @retval TRUE Browser required to reset after exit.
6657 @retval FALSE Browser not need to reset after exit.
6666 return gResetRequiredSystemLevel
;