2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
13 SETUP_DRIVER_SIGNATURE
,
26 BROWSER_EXTENSION2_VERSION_1_1
,
30 IsBrowserDataModified
,
38 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
39 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
40 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
41 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
43 UINTN gBrowserContextCount
= 0;
44 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
45 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
46 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
47 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
48 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
50 BOOLEAN mSystemSubmit
= FALSE
;
51 BOOLEAN gResetRequiredFormLevel
;
52 BOOLEAN gResetRequiredSystemLevel
= FALSE
;
53 BOOLEAN gExitRequired
;
54 BOOLEAN gFlagReconnect
;
55 BOOLEAN gCallbackReconnect
;
56 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
57 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
58 EXIT_HANDLER ExitHandlerFunction
= NULL
;
59 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
62 // Browser Global Strings
65 CHAR16
*mUnknownString
= L
"!";
67 extern EFI_GUID mCurrentFormSetGuid
;
68 extern EFI_HII_HANDLE mCurrentHiiHandle
;
69 extern UINT16 mCurrentFormId
;
70 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
71 extern BOOLEAN mDynamicFormUpdated
;
74 Create a menu with specified formset GUID and form ID, and add it as a child
75 of the given parent menu.
77 @param HiiHandle Hii handle related to this formset.
78 @param FormSetGuid The Formset Guid of menu to be added.
79 @param FormId The Form ID of menu to be added.
80 @param QuestionId The question id of this menu to be added.
82 @return A pointer to the newly added menu or NULL if memory is insufficient.
87 IN EFI_HII_HANDLE HiiHandle
,
88 IN EFI_GUID
*FormSetGuid
,
93 FORM_ENTRY_INFO
*MenuList
;
95 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
96 if (MenuList
== NULL
) {
100 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
102 MenuList
->HiiHandle
= HiiHandle
;
103 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
104 MenuList
->FormId
= FormId
;
105 MenuList
->QuestionId
= QuestionId
;
108 // If parent is not specified, it is the root Form of a Formset
110 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
116 Return the form id for the input hiihandle and formset.
118 @param HiiHandle HiiHandle for FormSet.
119 @param FormSetGuid The Formset GUID of the menu to search.
121 @return First form's id for this form set.
126 IN EFI_HII_HANDLE HiiHandle
,
127 IN EFI_GUID
*FormSetGuid
131 FORM_BROWSER_FORM
*Form
;
133 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
134 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
140 Search Menu with given FormSetGuid and FormId in all cached menu list.
142 @param HiiHandle HiiHandle for FormSet.
143 @param FormSetGuid The Formset GUID of the menu to search.
144 @param FormId The Form ID of menu to search.
146 @return A pointer to menu found or NULL if not found.
151 IN EFI_HII_HANDLE HiiHandle
,
152 IN EFI_GUID
*FormSetGuid
,
157 FORM_ENTRY_INFO
*MenuList
;
158 FORM_ENTRY_INFO
*RetMenu
;
159 EFI_FORM_ID FirstFormId
;
163 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
164 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
165 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
166 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
169 // If already find the menu, free the menus behind it.
171 if (RetMenu
!= NULL
) {
172 RemoveEntryList (&MenuList
->Link
);
178 // Find the same FromSet.
180 if (MenuList
->HiiHandle
== HiiHandle
) {
181 if (IsZeroGuid (&MenuList
->FormSetGuid
)) {
183 // FormSetGuid is not specified.
186 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
187 if (MenuList
->FormId
== FormId
) {
189 } else if ((FormId
== 0) || (MenuList
->FormId
== 0)) {
190 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
191 if (((FormId
== 0) && (FirstFormId
== MenuList
->FormId
)) || ((MenuList
->FormId
== 0) && (FirstFormId
== FormId
))) {
203 Find parent menu for current menu.
205 @param CurrentMenu Current Menu
206 @param SettingLevel Whether find parent menu in Form Level or Formset level.
207 In form level, just find the parent menu;
208 In formset level, find the parent menu which has different
211 @retval The parent menu for current menu.
215 IN FORM_ENTRY_INFO
*CurrentMenu
,
216 IN BROWSER_SETTING_SCOPE SettingLevel
219 FORM_ENTRY_INFO
*ParentMenu
;
222 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
224 if (CurrentMenu
== NULL
) {
229 Link
= &CurrentMenu
->Link
;
231 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
232 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
234 if (SettingLevel
== FormLevel
) {
236 // For FormLevel, just find the parent menu, return.
241 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
243 // For SystemLevel, must find the menu which has different formset.
248 Link
= Link
->BackLink
;
252 // Not find the parent menu, just return NULL.
254 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
262 Free Menu list linked list.
264 @param MenuListHead One Menu list point in the menu list.
269 LIST_ENTRY
*MenuListHead
272 FORM_ENTRY_INFO
*MenuList
;
274 while (!IsListEmpty (MenuListHead
)) {
275 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
276 RemoveEntryList (&MenuList
->Link
);
283 Copy current Menu list to the new menu list.
285 @param NewMenuListHead New create Menu list.
286 @param CurrentMenuListHead Current Menu list.
291 OUT LIST_ENTRY
*NewMenuListHead
,
292 IN LIST_ENTRY
*CurrentMenuListHead
296 FORM_ENTRY_INFO
*MenuList
;
297 FORM_ENTRY_INFO
*NewMenuEntry
;
300 // If new menu list not empty, free it first.
302 UiFreeMenuList (NewMenuListHead
);
304 Link
= GetFirstNode (CurrentMenuListHead
);
305 while (!IsNull (CurrentMenuListHead
, Link
)) {
306 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
307 Link
= GetNextNode (CurrentMenuListHead
, Link
);
309 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
310 ASSERT (NewMenuEntry
!= NULL
);
311 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
312 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
313 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
314 NewMenuEntry
->FormId
= MenuList
->FormId
;
315 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
317 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
322 Load all hii formset to the browser.
330 FORM_BROWSER_FORMSET
*LocalFormSet
;
331 EFI_HII_HANDLE
*HiiHandles
;
335 FORM_BROWSER_FORMSET
*OldFormset
;
337 OldFormset
= mSystemLevelFormSet
;
340 // Get all the Hii handles
342 HiiHandles
= HiiGetHiiHandles (NULL
);
343 ASSERT (HiiHandles
!= NULL
);
346 // Search for formset of each class type
348 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
350 // Check HiiHandles[Index] does exist in global maintain list.
352 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
357 // Initilize FormSet Setting
359 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
360 ASSERT (LocalFormSet
!= NULL
);
361 mSystemLevelFormSet
= LocalFormSet
;
363 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
364 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
365 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
366 DestroyFormSet (LocalFormSet
);
370 InitializeCurrentSetting (LocalFormSet
);
373 // Initilize Questions' Value
375 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
376 if (EFI_ERROR (Status
)) {
377 DestroyFormSet (LocalFormSet
);
383 // Free resources, and restore gOldFormSet and gClassOfVfr
385 FreePool (HiiHandles
);
387 mSystemLevelFormSet
= OldFormset
;
391 Pop up the error info.
393 @param BrowserStatus The input browser status.
394 @param HiiHandle The Hiihandle for this opcode.
395 @param OpCode The opcode use to get the erro info and timeout value.
396 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
401 IN UINT32 BrowserStatus
,
402 IN EFI_HII_HANDLE HiiHandle
,
403 IN EFI_IFR_OP_HEADER
*OpCode OPTIONAL
,
404 IN CHAR16
*ErrorString
407 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
408 USER_INPUT UserInputData
;
412 if (OpCode
!= NULL
) {
413 Statement
= AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT
));
414 ASSERT (Statement
!= NULL
);
415 Statement
->OpCode
= OpCode
;
416 gDisplayFormData
.HighLightedStatement
= Statement
;
420 // Used to compatible with old display engine.
421 // New display engine not use this field.
423 gDisplayFormData
.ErrorString
= ErrorString
;
424 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
426 if (HiiHandle
!= NULL
) {
427 gDisplayFormData
.HiiHandle
= HiiHandle
;
430 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
432 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
433 gDisplayFormData
.ErrorString
= NULL
;
435 if (OpCode
!= NULL
) {
436 FreePool (Statement
);
439 return UserInputData
.Action
;
443 This is the routine which an external caller uses to direct the browser
444 where to obtain it's information.
447 @param This The Form Browser protocol instanse.
448 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
449 display a list of the formsets for the handles specified.
450 @param HandleCount The number of Handles specified in Handle.
451 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
452 field in the EFI_IFR_FORM_SET op-code for the specified
453 forms-based package. If FormSetGuid is NULL, then this
454 function will display the first found forms package.
455 @param FormId This field specifies which EFI_IFR_FORM to render as the first
456 displayable page. If this field has a value of 0x0000, then
457 the forms browser will render the specified forms in their encoded order.
458 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
460 @param ActionRequest Points to the action recommended by the form.
462 @retval EFI_SUCCESS The function completed successfully.
463 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
464 @retval EFI_NOT_FOUND No valid forms could be found to display.
470 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
471 IN EFI_HII_HANDLE
*Handles
,
472 IN UINTN HandleCount
,
473 IN EFI_GUID
*FormSetGuid OPTIONAL
,
474 IN UINT16 FormId OPTIONAL
,
475 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions OPTIONAL
,
476 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
480 UI_MENU_SELECTION
*Selection
;
482 FORM_BROWSER_FORMSET
*FormSet
;
483 FORM_ENTRY_INFO
*MenuList
;
487 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
489 if (mFormDisplay
== NULL
) {
490 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
491 return EFI_UNSUPPORTED
;
495 // Save globals used by SendForm()
497 SaveBrowserContext ();
499 gFlagReconnect
= FALSE
;
500 gResetRequiredFormLevel
= FALSE
;
501 gExitRequired
= FALSE
;
502 gCallbackReconnect
= FALSE
;
503 Status
= EFI_SUCCESS
;
505 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*)ScreenDimensions
;
507 for (Index
= 0; Index
< HandleCount
; Index
++) {
508 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
509 ASSERT (Selection
!= NULL
);
511 Selection
->Handle
= Handles
[Index
];
512 if (FormSetGuid
!= NULL
) {
513 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
514 Selection
->FormId
= FormId
;
516 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
520 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
521 ASSERT (FormSet
!= NULL
);
524 // Validate the HiiHandle
525 // if validate failed, find the first validate parent HiiHandle.
527 if (!ValidateHiiHandle (Selection
->Handle
)) {
528 FindNextMenu (Selection
, FormSetLevel
);
532 // Initialize internal data structures of FormSet
534 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
535 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
536 DestroyFormSet (FormSet
);
540 Selection
->FormSet
= FormSet
;
541 mSystemLevelFormSet
= FormSet
;
542 mDynamicFormUpdated
= FALSE
;
545 // Display this formset
547 gCurrentSelection
= Selection
;
549 Status
= SetupBrowser (Selection
);
551 gCurrentSelection
= NULL
;
552 mSystemLevelFormSet
= NULL
;
555 // If callback update form dynamically, it's not exiting of the formset for user so system do not reconnect driver hanlde
558 if (!mDynamicFormUpdated
&& (gFlagReconnect
|| gCallbackReconnect
)) {
559 RetVal
= ReconnectController (FormSet
->DriverHandle
);
561 PopupErrorMessage (BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
564 gFlagReconnect
= FALSE
;
565 gCallbackReconnect
= FALSE
;
569 // If no data is changed, don't need to save current FormSet into the maintain list.
571 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
572 CleanBrowserStorage (FormSet
);
573 RemoveEntryList (&FormSet
->Link
);
574 DestroyFormSet (FormSet
);
577 if (EFI_ERROR (Status
)) {
580 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
582 FreePool (Selection
);
585 if (ActionRequest
!= NULL
) {
586 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
587 if (gResetRequiredFormLevel
) {
588 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
592 mFormDisplay
->ExitDisplay ();
595 // Clear the menu history data.
597 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
598 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
599 RemoveEntryList (&MenuList
->Link
);
604 // Restore globals used by SendForm()
606 RestoreBrowserContext ();
612 Get or set data to the storage.
614 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
615 @param ResultsData A string returned from an IFR browser or
616 equivalent. The results string will have no
617 routing information in them.
618 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
619 (if RetrieveData = TRUE) data from the uncommitted
620 browser state information or set (if RetrieveData
621 = FALSE) data in the uncommitted browser state
623 @param Storage The pointer to the storage.
625 @retval EFI_SUCCESS The results have been distributed or are awaiting
631 IN OUT UINTN
*ResultsDataSize
,
632 IN OUT EFI_STRING
*ResultsData
,
633 IN BOOLEAN RetrieveData
,
634 IN BROWSER_STORAGE
*Storage
643 FORMSET_STORAGE
*BrowserStorage
;
647 // Generate <ConfigResp>
649 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
650 if (EFI_ERROR (Status
)) {
655 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
656 // Also need to consider add "\0" at first time.
658 StrPtr
= StrStr (ConfigResp
, L
"PATH");
659 ASSERT (StrPtr
!= NULL
);
660 StrPtr
= StrStr (StrPtr
, L
"&");
662 BufferSize
= StrSize (StrPtr
);
665 // Copy the data if the input buffer is bigger enough.
667 if (*ResultsDataSize
>= BufferSize
) {
668 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
671 *ResultsDataSize
= BufferSize
;
672 FreePool (ConfigResp
);
675 // Prepare <ConfigResp>
677 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
678 ASSERT (BrowserStorage
!= NULL
);
679 TmpSize
= StrLen (*ResultsData
);
680 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
681 MaxLen
= BufferSize
/ sizeof (CHAR16
);
682 ConfigResp
= AllocateZeroPool (BufferSize
);
683 ASSERT (ConfigResp
!= NULL
);
685 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
686 StrCatS (ConfigResp
, MaxLen
, L
"&");
687 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
690 // Update Browser uncommited data
692 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
693 FreePool (ConfigResp
);
694 if (EFI_ERROR (Status
)) {
703 This routine called this service in the browser to retrieve or set certain uncommitted
704 state information that resides in the open formsets.
706 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
708 @param ResultsDataSize A pointer to the size of the buffer associated
710 @param ResultsData A string returned from an IFR browser or
711 equivalent. The results string will have no
712 routing information in them.
713 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
714 (if RetrieveData = TRUE) data from the uncommitted
715 browser state information or set (if RetrieveData
716 = FALSE) data in the uncommitted browser state
718 @param VariableGuid An optional field to indicate the target variable
720 @param VariableName An optional field to indicate the target
721 human-readable variable name.
723 @retval EFI_SUCCESS The results have been distributed or are awaiting
725 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
726 contain the results data.
732 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
733 IN OUT UINTN
*ResultsDataSize
,
734 IN OUT EFI_STRING ResultsData
,
735 IN BOOLEAN RetrieveData
,
736 IN CONST EFI_GUID
*VariableGuid OPTIONAL
,
737 IN CONST CHAR16
*VariableName OPTIONAL
742 BROWSER_STORAGE
*Storage
;
743 FORMSET_STORAGE
*FormsetStorage
;
747 if ((ResultsDataSize
== NULL
) || (ResultsData
== NULL
)) {
748 return EFI_INVALID_PARAMETER
;
751 TotalSize
= *ResultsDataSize
;
754 Status
= EFI_SUCCESS
;
756 if (VariableGuid
!= NULL
) {
758 // Try to find target storage in the current formset.
760 Link
= GetFirstNode (&gBrowserStorageList
);
761 while (!IsNull (&gBrowserStorageList
, Link
)) {
762 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
763 Link
= GetNextNode (&gBrowserStorageList
, Link
);
765 // Check the current storage.
767 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*)VariableGuid
)) {
771 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
772 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
775 // Buffer storage require both GUID and Name
777 if (VariableName
== NULL
) {
778 return EFI_NOT_FOUND
;
781 if (StrCmp (Storage
->Name
, (CHAR16
*)VariableName
) != 0) {
786 if ((Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) ||
787 (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
))
789 if ((mSystemLevelFormSet
== NULL
) || (mSystemLevelFormSet
->HiiHandle
== NULL
)) {
790 return EFI_NOT_FOUND
;
793 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
798 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
799 if (EFI_ERROR (Status
)) {
803 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
804 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
808 // Different formsets may have same varstore, so here just set the flag
809 // not exit the circle.
816 return EFI_NOT_FOUND
;
820 // GUID/Name is not specified, take the first storage in FormSet
822 if (mSystemLevelFormSet
== NULL
) {
823 return EFI_NOT_READY
;
827 // Generate <ConfigResp>
829 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
830 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
831 return EFI_UNSUPPORTED
;
834 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
836 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
837 if (EFI_ERROR (Status
)) {
843 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
844 *ResultsDataSize
= TotalSize
;
851 Callback function for SimpleTextInEx protocol install events
853 @param Event the event that is signaled.
854 @param Context not used here.
859 FormDisplayCallback (
864 if (mFormDisplay
!= NULL
) {
868 gBS
->LocateProtocol (
869 &gEdkiiFormDisplayEngineProtocolGuid
,
871 (VOID
**)&mFormDisplay
876 Initialize Setup Browser driver.
878 @param ImageHandle The image handle.
879 @param SystemTable The system table.
881 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
882 @return Other value if failed to initialize the Setup Browser module.
888 IN EFI_HANDLE ImageHandle
,
889 IN EFI_SYSTEM_TABLE
*SystemTable
896 // Locate required Hii relative protocols
898 Status
= gBS
->LocateProtocol (
899 &gEfiHiiDatabaseProtocolGuid
,
901 (VOID
**)&mHiiDatabase
903 ASSERT_EFI_ERROR (Status
);
905 Status
= gBS
->LocateProtocol (
906 &gEfiHiiConfigRoutingProtocolGuid
,
908 (VOID
**)&mHiiConfigRouting
910 ASSERT_EFI_ERROR (Status
);
912 Status
= gBS
->LocateProtocol (
913 &gEfiDevicePathFromTextProtocolGuid
,
915 (VOID
**)&mPathFromText
919 // Install FormBrowser2 protocol
921 mPrivateData
.Handle
= NULL
;
922 Status
= gBS
->InstallProtocolInterface (
923 &mPrivateData
.Handle
,
924 &gEfiFormBrowser2ProtocolGuid
,
925 EFI_NATIVE_INTERFACE
,
926 &mPrivateData
.FormBrowser2
928 ASSERT_EFI_ERROR (Status
);
931 // Install FormBrowserEx2 protocol
933 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
934 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
935 mPrivateData
.Handle
= NULL
;
936 Status
= gBS
->InstallProtocolInterface (
937 &mPrivateData
.Handle
,
938 &gEdkiiFormBrowserEx2ProtocolGuid
,
939 EFI_NATIVE_INTERFACE
,
940 &mPrivateData
.FormBrowserEx2
942 ASSERT_EFI_ERROR (Status
);
944 Status
= gBS
->InstallProtocolInterface (
945 &mPrivateData
.Handle
,
946 &gEdkiiFormBrowserExProtocolGuid
,
947 EFI_NATIVE_INTERFACE
,
948 &mPrivateData
.FormBrowserEx
950 ASSERT_EFI_ERROR (Status
);
952 InitializeDisplayFormData ();
954 Status
= gBS
->LocateProtocol (
955 &gEdkiiFormDisplayEngineProtocolGuid
,
957 (VOID
**)&mFormDisplay
960 if (EFI_ERROR (Status
)) {
961 EfiCreateProtocolNotifyEvent (
962 &gEdkiiFormDisplayEngineProtocolGuid
,
974 Create a new string in HII Package List.
976 @param String The String to be added
977 @param HiiHandle The package list in the HII database to insert the
980 @return The output string.
986 IN EFI_HII_HANDLE HiiHandle
989 EFI_STRING_ID StringId
;
991 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
992 ASSERT (StringId
!= 0);
998 Delete a string from HII Package List.
1000 @param StringId Id of the string in HII database.
1001 @param HiiHandle The HII package list handle.
1003 @retval EFI_SUCCESS The string was deleted successfully.
1008 IN EFI_STRING_ID StringId
,
1009 IN EFI_HII_HANDLE HiiHandle
1014 NullChar
= CHAR_NULL
;
1015 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1020 Get the string based on the StringId and HII Package List Handle.
1022 @param Token The String's ID.
1023 @param HiiHandle The package list in the HII database to search for
1024 the specified string.
1026 @return The output string.
1031 IN EFI_STRING_ID Token
,
1032 IN EFI_HII_HANDLE HiiHandle
1037 if (HiiHandle
== NULL
) {
1041 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1042 if (String
== NULL
) {
1043 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1044 ASSERT (String
!= NULL
);
1047 return (CHAR16
*)String
;
1051 Allocate new memory and then copy the Unicode string Source to Destination.
1053 @param Dest Location to copy string
1054 @param Src String to copy
1059 IN OUT CHAR16
**Dest
,
1063 if (*Dest
!= NULL
) {
1067 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1068 ASSERT (*Dest
!= NULL
);
1072 Allocate new memory and concatinate Source on the end of Destination.
1074 @param Dest String to added to the end of.
1075 @param Src String to concatinate.
1080 IN OUT CHAR16
**Dest
,
1087 if (*Dest
== NULL
) {
1088 NewStringCpy (Dest
, Src
);
1092 MaxLen
= (StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1093 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1094 ASSERT (NewString
!= NULL
);
1096 StrCpyS (NewString
, MaxLen
, *Dest
);
1097 StrCatS (NewString
, MaxLen
, Src
);
1104 Get Value for given Name from a NameValue Storage.
1106 @param Storage The NameValue Storage.
1107 @param Name The Name.
1108 @param Value The retured Value.
1109 @param GetValueFrom Where to get source value, from EditValue or Value.
1111 @retval EFI_SUCCESS Value found for given Name.
1112 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1117 IN BROWSER_STORAGE
*Storage
,
1119 IN OUT CHAR16
**Value
,
1120 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1124 NAME_VALUE_NODE
*Node
;
1126 if ((GetValueFrom
!= GetSetValueWithEditBuffer
) && (GetValueFrom
!= GetSetValueWithBuffer
)) {
1127 return EFI_INVALID_PARAMETER
;
1132 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1133 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1134 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1136 if (StrCmp (Name
, Node
->Name
) == 0) {
1137 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1138 NewStringCpy (Value
, Node
->EditValue
);
1140 NewStringCpy (Value
, Node
->Value
);
1146 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1149 return EFI_NOT_FOUND
;
1153 Set Value of given Name in a NameValue Storage.
1155 @param Storage The NameValue Storage.
1156 @param Name The Name.
1157 @param Value The Value to set.
1158 @param SetValueTo Whether update editValue or Value.
1159 @param ReturnNode The node use the input name.
1161 @retval EFI_SUCCESS Value found for given Name.
1162 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1167 IN BROWSER_STORAGE
*Storage
,
1170 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1171 OUT NAME_VALUE_NODE
**ReturnNode
1175 NAME_VALUE_NODE
*Node
;
1178 if ((SetValueTo
!= GetSetValueWithEditBuffer
) && (SetValueTo
!= GetSetValueWithBuffer
)) {
1179 return EFI_INVALID_PARAMETER
;
1182 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1183 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1184 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1186 if (StrCmp (Name
, Node
->Name
) == 0) {
1187 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1188 Buffer
= Node
->EditValue
;
1190 Buffer
= Node
->Value
;
1193 if (Buffer
!= NULL
) {
1197 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1198 ASSERT (Buffer
!= NULL
);
1199 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1200 Node
->EditValue
= Buffer
;
1202 Node
->Value
= Buffer
;
1205 if (ReturnNode
!= NULL
) {
1212 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1215 return EFI_NOT_FOUND
;
1219 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1221 @param Storage The Storage to be conveted.
1222 @param ConfigResp The returned <ConfigResp>.
1223 @param ConfigRequest The ConfigRequest string.
1224 @param GetEditBuf Get the data from editbuffer or buffer.
1226 @retval EFI_SUCCESS Convert success.
1227 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1231 StorageToConfigResp (
1232 IN BROWSER_STORAGE
*Storage
,
1233 IN CHAR16
**ConfigResp
,
1234 IN CHAR16
*ConfigRequest
,
1235 IN BOOLEAN GetEditBuf
1239 EFI_STRING Progress
;
1241 NAME_VALUE_NODE
*Node
;
1243 FORMSET_STORAGE
*FormsetStorage
;
1245 Status
= EFI_SUCCESS
;
1247 switch (Storage
->Type
) {
1248 case EFI_HII_VARSTORE_BUFFER
:
1249 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1250 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1251 Status
= mHiiConfigRouting
->BlockToConfig (
1261 case EFI_HII_VARSTORE_NAME_VALUE
:
1263 FormsetStorage
= GetFstStgFromBrsStg (Storage
);
1264 ASSERT (FormsetStorage
!= NULL
);
1265 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1267 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1268 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1269 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1271 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1272 NewStringCat (ConfigResp
, L
"&");
1273 NewStringCat (ConfigResp
, Node
->Name
);
1274 NewStringCat (ConfigResp
, L
"=");
1276 NewStringCat (ConfigResp
, Node
->EditValue
);
1278 NewStringCat (ConfigResp
, Node
->Value
);
1282 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1287 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1289 Status
= EFI_INVALID_PARAMETER
;
1297 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1299 @param Storage The Storage to receive the settings.
1300 @param ConfigResp The <ConfigResp> to be converted.
1302 @retval EFI_SUCCESS Convert success.
1303 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1307 ConfigRespToStorage (
1308 IN BROWSER_STORAGE
*Storage
,
1309 IN CHAR16
*ConfigResp
1313 EFI_STRING Progress
;
1319 Status
= EFI_SUCCESS
;
1321 switch (Storage
->Type
) {
1322 case EFI_HII_VARSTORE_BUFFER
:
1323 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1324 BufferSize
= Storage
->Size
;
1325 Status
= mHiiConfigRouting
->ConfigToBlock (
1328 Storage
->EditBuffer
,
1334 case EFI_HII_VARSTORE_NAME_VALUE
:
1335 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1336 if (StrPtr
== NULL
) {
1340 StrPtr
= StrStr (ConfigResp
, L
"&");
1341 while (StrPtr
!= NULL
) {
1345 StrPtr
= StrPtr
+ 1;
1347 StrPtr
= StrStr (StrPtr
, L
"=");
1348 if (StrPtr
== NULL
) {
1357 StrPtr
= StrPtr
+ 1;
1359 StrPtr
= StrStr (StrPtr
, L
"&");
1360 if (StrPtr
!= NULL
) {
1364 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1369 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1371 Status
= EFI_INVALID_PARAMETER
;
1379 Get bit field value from the buffer and then set the value for the question.
1380 Note: Data type UINT32 can cover all the bit field value.
1382 @param Question The question refer to bit field.
1383 @param Buffer Point to the buffer which the question value get from.
1387 GetBitsQuestionValue (
1388 IN FORM_BROWSER_STATEMENT
*Question
,
1397 StartBit
= Question
->BitVarOffset
% 8;
1398 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1400 CopyMem ((UINT8
*)&BufferValue
, Buffer
, Question
->StorageWidth
);
1402 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1405 // Set question value.
1406 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1407 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1409 CopyMem ((UINT8
*)&Question
->HiiValue
.Value
, (UINT8
*)&RetVal
, Question
->StorageWidth
);
1413 Set bit field value to the buffer.
1414 Note: Data type UINT32 can cover all the bit field value.
1416 @param Question The question refer to bit field.
1417 @param Buffer Point to the buffer which the question value set to.
1418 @param Value The bit field value need to set.
1422 SetBitsQuestionValue (
1423 IN FORM_BROWSER_STATEMENT
*Question
,
1424 IN OUT UINT8
*Buffer
,
1433 StartBit
= Question
->BitVarOffset
% 8;
1434 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1436 CopyMem ((UINT8
*)&Operand
, Buffer
, Question
->StorageWidth
);
1438 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1440 CopyMem (Buffer
, (UINT8
*)&RetVal
, Question
->StorageWidth
);
1444 Convert the buffer value to HiiValue.
1446 @param Question The question.
1447 @param Value Unicode buffer save the question value.
1449 @retval Status whether convert the value success.
1454 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1459 BOOLEAN IsBufferStorage
;
1474 IsString
= (BOOLEAN
)((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1475 if ((Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
1476 (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
1478 IsBufferStorage
= TRUE
;
1480 IsBufferStorage
= FALSE
;
1484 // Question Value is provided by Buffer Storage or NameValue Storage
1486 if (Question
->BufferValue
!= NULL
) {
1488 // This Question is password or orderedlist
1490 Dst
= Question
->BufferValue
;
1493 // Other type of Questions
1495 if (Question
->QuestionReferToBitField
) {
1496 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1497 if (Buffer
== NULL
) {
1498 return EFI_OUT_OF_RESOURCES
;
1503 Dst
= (UINT8
*)&Question
->HiiValue
.Value
;
1508 // Temp cut at the end of this section, end with '\0' or '&'.
1511 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1515 TempChar
= *StringPtr
;
1518 LengthStr
= StrLen (Value
);
1521 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1522 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1523 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1524 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1526 if (LengthStr
> (UINTN
)Question
->StorageWidth
* 2) {
1527 Length
= (UINTN
)Question
->StorageWidth
* 2;
1532 Status
= EFI_SUCCESS
;
1533 if (!IsBufferStorage
&& IsString
) {
1535 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1536 // Add string tail char L'\0' into Length
1538 DstBuf
= (CHAR16
*)Dst
;
1539 ZeroMem (TemStr
, sizeof (TemStr
));
1540 for (Index
= 0; Index
< Length
; Index
+= 4) {
1541 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1542 DstBuf
[Index
/4] = (CHAR16
)StrHexToUint64 (TemStr
);
1546 // Add tailing L'\0' character
1548 DstBuf
[Index
/4] = L
'\0';
1550 ZeroMem (TemStr
, sizeof (TemStr
));
1551 for (Index
= 0; Index
< Length
; Index
++) {
1552 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1553 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
1554 if ((Index
& 1) == 0) {
1555 Dst
[Index
/2] = DigitUint8
;
1557 Dst
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + Dst
[Index
/2]);
1562 *StringPtr
= TempChar
;
1564 if ((Buffer
!= NULL
) && Question
->QuestionReferToBitField
) {
1565 GetBitsQuestionValue (Question
, Buffer
);
1573 Get Question's current Value.
1575 @param FormSet FormSet data structure.
1576 @param Form Form data structure.
1577 @param Question Question to be initialized.
1578 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1580 @retval EFI_SUCCESS The function completed successfully.
1585 IN FORM_BROWSER_FORMSET
*FormSet
,
1586 IN FORM_BROWSER_FORM
*Form
,
1587 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1588 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1597 BROWSER_STORAGE
*Storage
;
1598 FORMSET_STORAGE
*FormsetStorage
;
1599 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1600 CHAR16
*ConfigRequest
;
1605 BOOLEAN IsBufferStorage
;
1608 Status
= EFI_SUCCESS
;
1612 if (GetValueFrom
>= GetSetValueWithMax
) {
1613 return EFI_INVALID_PARAMETER
;
1617 // Question value is provided by an Expression, evaluate it
1619 if (Question
->ValueExpression
!= NULL
) {
1620 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1621 if (!EFI_ERROR (Status
)) {
1622 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1623 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1624 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1625 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1626 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1628 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1629 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1632 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1635 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1636 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1643 // Get question value by read expression.
1645 if ((Question
->ReadExpression
!= NULL
) && (Form
->FormType
== STANDARD_MAP_FORM_TYPE
)) {
1646 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1647 if (!EFI_ERROR (Status
) &&
1648 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
)))
1651 // Only update question value to the valid result.
1653 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1654 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1655 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1656 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1657 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1659 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1660 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1663 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1666 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1667 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1673 // Question value is provided by RTC
1675 Storage
= Question
->Storage
;
1676 QuestionValue
= &Question
->HiiValue
.Value
;
1677 if (Storage
== NULL
) {
1679 // It's a Question without storage, or RTC date/time
1681 if ((Question
->Operand
== EFI_IFR_DATE_OP
) || (Question
->Operand
== EFI_IFR_TIME_OP
)) {
1683 // Date and time define the same Flags bit
1685 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1686 case QF_DATE_STORAGE_TIME
:
1687 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1690 case QF_DATE_STORAGE_WAKEUP
:
1691 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1694 case QF_DATE_STORAGE_NORMAL
:
1697 // For date/time without storage
1702 if (EFI_ERROR (Status
)) {
1703 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1704 QuestionValue
->date
.Year
= 0xff;
1705 QuestionValue
->date
.Month
= 0xff;
1706 QuestionValue
->date
.Day
= 0xff;
1708 QuestionValue
->time
.Hour
= 0xff;
1709 QuestionValue
->time
.Minute
= 0xff;
1710 QuestionValue
->time
.Second
= 0xff;
1716 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1717 QuestionValue
->date
.Year
= EfiTime
.Year
;
1718 QuestionValue
->date
.Month
= EfiTime
.Month
;
1719 QuestionValue
->date
.Day
= EfiTime
.Day
;
1721 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1722 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1723 QuestionValue
->time
.Second
= EfiTime
.Second
;
1731 // Question value is provided by EFI variable
1733 StorageWidth
= Question
->StorageWidth
;
1734 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1735 if (Question
->BufferValue
!= NULL
) {
1736 Dst
= Question
->BufferValue
;
1738 Dst
= (UINT8
*)QuestionValue
;
1741 Status
= gRT
->GetVariable (
1742 Question
->VariableName
,
1749 // Always return success, even this EFI variable doesn't exist
1755 // Question Value is provided by Buffer Storage or NameValue Storage
1757 if (Question
->BufferValue
!= NULL
) {
1759 // This Question is password or orderedlist
1761 Dst
= Question
->BufferValue
;
1764 // Other type of Questions
1766 Dst
= (UINT8
*)&Question
->HiiValue
.Value
;
1769 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
1770 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
1772 IsBufferStorage
= TRUE
;
1774 IsBufferStorage
= FALSE
;
1777 if ((GetValueFrom
== GetSetValueWithEditBuffer
) || (GetValueFrom
== GetSetValueWithBuffer
)) {
1778 if (IsBufferStorage
) {
1779 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1781 // Copy from storage Edit buffer
1782 // If the Question refer to bit filed, get the value in the related bit filed.
1784 if (Question
->QuestionReferToBitField
) {
1785 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1787 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1791 // Copy from storage Edit buffer
1792 // If the Question refer to bit filed, get the value in the related bit filed.
1794 if (Question
->QuestionReferToBitField
) {
1795 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1797 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1802 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1803 if (EFI_ERROR (Status
)) {
1807 ASSERT (Value
!= NULL
);
1808 Status
= BufferToValue (Question
, Value
);
1812 FormsetStorage
= GetFstStgFromVarId (FormSet
, Question
->VarStoreId
);
1813 ASSERT (FormsetStorage
!= NULL
);
1815 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1816 // <ConfigHdr> + "&" + <VariableName>
1818 if (IsBufferStorage
) {
1819 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1820 Length
+= StrLen (Question
->BlockName
);
1822 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1823 Length
+= StrLen (Question
->VariableName
) + 1;
1826 // Allocate buffer include '\0'
1827 MaxLen
= Length
+ 1;
1828 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1829 ASSERT (ConfigRequest
!= NULL
);
1831 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1832 if (IsBufferStorage
) {
1833 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1835 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1836 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1840 // Request current settings from Configuration Driver
1842 Status
= mHiiConfigRouting
->ExtractConfig (
1848 FreePool (ConfigRequest
);
1849 if (EFI_ERROR (Status
)) {
1854 // Skip <ConfigRequest>
1856 if (IsBufferStorage
) {
1857 Value
= StrStr (Result
, L
"&VALUE");
1858 if (Value
== NULL
) {
1860 return EFI_NOT_FOUND
;
1868 Value
= Result
+ Length
;
1871 if (*Value
!= '=') {
1873 return EFI_NOT_FOUND
;
1877 // Skip '=', point to value
1881 Status
= BufferToValue (Question
, Value
);
1882 if (EFI_ERROR (Status
)) {
1888 // Synchronize Edit Buffer
1890 if (IsBufferStorage
) {
1891 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1893 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1896 if (Result
!= NULL
) {
1905 Save Question Value to edit copy(cached) or Storage(uncached).
1907 @param FormSet FormSet data structure.
1908 @param Form Form data structure.
1909 @param Question Pointer to the Question.
1910 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1912 @retval EFI_SUCCESS The function completed successfully.
1917 IN FORM_BROWSER_FORMSET
*FormSet
,
1918 IN FORM_BROWSER_FORM
*Form
,
1919 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1920 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1930 BROWSER_STORAGE
*Storage
;
1931 FORMSET_STORAGE
*FormsetStorage
;
1932 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1937 BOOLEAN IsBufferStorage
;
1943 NAME_VALUE_NODE
*Node
;
1946 Status
= EFI_SUCCESS
;
1949 if (SetValueTo
>= GetSetValueWithMax
) {
1950 return EFI_INVALID_PARAMETER
;
1954 // If Question value is provided by an Expression, then it is read only
1956 if (Question
->ValueExpression
!= NULL
) {
1961 // Before set question value, evaluate its write expression.
1963 if ((Question
->WriteExpression
!= NULL
) && (Form
->FormType
== STANDARD_MAP_FORM_TYPE
)) {
1964 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1965 if (EFI_ERROR (Status
)) {
1971 // Question value is provided by RTC
1973 Storage
= Question
->Storage
;
1974 QuestionValue
= &Question
->HiiValue
.Value
;
1975 if (Storage
== NULL
) {
1977 // It's a Question without storage, or RTC date/time
1979 if ((Question
->Operand
== EFI_IFR_DATE_OP
) || (Question
->Operand
== EFI_IFR_TIME_OP
)) {
1981 // Date and time define the same Flags bit
1983 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1984 case QF_DATE_STORAGE_TIME
:
1985 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1988 case QF_DATE_STORAGE_WAKEUP
:
1989 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1992 case QF_DATE_STORAGE_NORMAL
:
1995 // For date/time without storage
2000 if (EFI_ERROR (Status
)) {
2004 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
2005 EfiTime
.Year
= QuestionValue
->date
.Year
;
2006 EfiTime
.Month
= QuestionValue
->date
.Month
;
2007 EfiTime
.Day
= QuestionValue
->date
.Day
;
2009 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
2010 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
2011 EfiTime
.Second
= QuestionValue
->time
.Second
;
2014 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
2015 Status
= gRT
->SetTime (&EfiTime
);
2017 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
2025 // Question value is provided by EFI variable
2027 StorageWidth
= Question
->StorageWidth
;
2028 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2029 if (Question
->BufferValue
!= NULL
) {
2030 Src
= Question
->BufferValue
;
2032 Src
= (UINT8
*)QuestionValue
;
2035 Status
= gRT
->SetVariable (
2036 Question
->VariableName
,
2038 Storage
->Attributes
,
2046 // Question Value is provided by Buffer Storage or NameValue Storage
2048 if (Question
->BufferValue
!= NULL
) {
2049 Src
= Question
->BufferValue
;
2051 Src
= (UINT8
*)&Question
->HiiValue
.Value
;
2054 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
2055 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
2057 IsBufferStorage
= TRUE
;
2059 IsBufferStorage
= FALSE
;
2062 IsString
= (BOOLEAN
)((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2064 if ((SetValueTo
== GetSetValueWithEditBuffer
) || (SetValueTo
== GetSetValueWithBuffer
)) {
2065 if (IsBufferStorage
) {
2066 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2068 // Copy to storage edit buffer
2069 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2071 if (Question
->QuestionReferToBitField
) {
2072 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2074 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2076 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2078 // Copy to storage buffer
2079 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2081 if (Question
->QuestionReferToBitField
) {
2082 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2084 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2090 // Allocate enough string buffer.
2093 BufferLen
= ((StrLen ((CHAR16
*)Src
) * 4) + 1) * sizeof (CHAR16
);
2094 Value
= AllocateZeroPool (BufferLen
);
2095 ASSERT (Value
!= NULL
);
2097 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2099 TemName
= (CHAR16
*)Src
;
2101 for ( ; *TemName
!= L
'\0'; TemName
++) {
2102 UnicodeValueToStringS (
2104 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2105 PREFIX_ZERO
| RADIX_HEX
,
2109 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2112 BufferLen
= StorageWidth
* 2 + 1;
2113 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2114 ASSERT (Value
!= NULL
);
2116 // Convert Buffer to Hex String
2118 TemBuffer
= Src
+ StorageWidth
- 1;
2120 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2121 UnicodeValueToStringS (
2123 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2124 PREFIX_ZERO
| RADIX_HEX
,
2128 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2132 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2134 if (EFI_ERROR (Status
)) {
2138 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2140 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2141 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2143 if (IsBufferStorage
) {
2144 Length
= StrLen (Question
->BlockName
) + 7;
2146 Length
= StrLen (Question
->VariableName
) + 2;
2149 if (!IsBufferStorage
&& IsString
) {
2150 Length
+= (StrLen ((CHAR16
*)Src
) * 4);
2152 Length
+= (StorageWidth
* 2);
2155 FormsetStorage
= GetFstStgFromVarId (FormSet
, Question
->VarStoreId
);
2156 ASSERT (FormsetStorage
!= NULL
);
2157 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2158 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2159 ASSERT (ConfigResp
!= NULL
);
2161 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2162 if (IsBufferStorage
) {
2163 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2164 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2166 StrCatS (ConfigResp
, MaxLen
, L
"&");
2167 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2168 StrCatS (ConfigResp
, MaxLen
, L
"=");
2171 Value
= ConfigResp
+ StrLen (ConfigResp
);
2173 if (!IsBufferStorage
&& IsString
) {
2175 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2177 TemName
= (CHAR16
*)Src
;
2179 for ( ; *TemName
!= L
'\0'; TemName
++) {
2180 UnicodeValueToStringS (
2182 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2183 PREFIX_ZERO
| RADIX_HEX
,
2187 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2191 // Convert Buffer to Hex String
2193 TemBuffer
= Src
+ StorageWidth
- 1;
2195 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2196 UnicodeValueToStringS (
2198 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2199 PREFIX_ZERO
| RADIX_HEX
,
2203 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2208 // Convert to lower char.
2210 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2211 if ((*Value
>= L
'A') && (*Value
<= L
'Z')) {
2212 *Value
= (CHAR16
)(*Value
- L
'A' + L
'a');
2217 // Submit Question Value to Configuration Driver
2219 Status
= mHiiConfigRouting
->RouteConfig (
2224 if (EFI_ERROR (Status
)) {
2225 FreePool (ConfigResp
);
2229 FreePool (ConfigResp
);
2232 // Sync storage, from editbuffer to buffer.
2234 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2241 Perform nosubmitif check for a Form.
2243 @param FormSet FormSet data structure.
2244 @param Form Form data structure.
2245 @param Question The Question to be validated.
2246 @param Type Validation type: NoSubmit
2248 @retval EFI_SUCCESS Form validation pass.
2249 @retval other Form validation failed.
2254 IN FORM_BROWSER_FORMSET
*FormSet
,
2255 IN FORM_BROWSER_FORM
*Form
,
2256 IN FORM_BROWSER_STATEMENT
*Question
,
2262 LIST_ENTRY
*ListHead
;
2263 FORM_EXPRESSION
*Expression
;
2264 UINT32 BrowserStatus
;
2267 BrowserStatus
= BROWSER_SUCCESS
;
2271 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2272 ListHead
= &Question
->InconsistentListHead
;
2275 case EFI_HII_EXPRESSION_WARNING_IF
:
2276 ListHead
= &Question
->WarningListHead
;
2279 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2280 ListHead
= &Question
->NoSubmitListHead
;
2285 return EFI_UNSUPPORTED
;
2288 Link
= GetFirstNode (ListHead
);
2289 while (!IsNull (ListHead
, Link
)) {
2290 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2293 // Evaluate the expression
2295 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2296 if (EFI_ERROR (Status
)) {
2300 if (IsTrue (&Expression
->Result
)) {
2302 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2303 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2306 case EFI_HII_EXPRESSION_WARNING_IF
:
2307 BrowserStatus
= BROWSER_WARNING_IF
;
2310 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2311 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2313 // This code only used to compatible with old display engine,
2314 // New display engine will not use this field.
2316 if (Expression
->Error
!= 0) {
2317 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2327 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2329 // If in system submit process and for no_submit_if check, not popup this error message.
2330 // Will process this fail again later in not system submit process.
2332 PopupErrorMessage (BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2335 if (ErrorStr
!= NULL
) {
2336 FreePool (ErrorStr
);
2339 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2342 return EFI_NOT_READY
;
2346 Link
= GetNextNode (ListHead
, Link
);
2353 Perform question check.
2355 If one question has more than one check, process form high priority to low.
2356 Only one error info will be popup.
2358 @param FormSet FormSet data structure.
2359 @param Form Form data structure.
2360 @param Question The Question to be validated.
2362 @retval EFI_SUCCESS Form validation pass.
2363 @retval other Form validation failed.
2367 ValueChangedValidation (
2368 IN FORM_BROWSER_FORMSET
*FormSet
,
2369 IN FORM_BROWSER_FORM
*Form
,
2370 IN FORM_BROWSER_STATEMENT
*Question
2375 Status
= EFI_SUCCESS
;
2378 // Do the inconsistentif check.
2380 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2381 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2382 if (EFI_ERROR (Status
)) {
2388 // Do the warningif check.
2390 if (!IsListEmpty (&Question
->WarningListHead
)) {
2391 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2398 Perform NoSubmit check for each Form in FormSet.
2400 @param FormSet FormSet data structure.
2401 @param CurrentForm Current input form data structure.
2402 @param Statement The statement for this check.
2404 @retval EFI_SUCCESS Form validation pass.
2405 @retval other Form validation failed.
2410 IN FORM_BROWSER_FORMSET
*FormSet
,
2411 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2412 OUT FORM_BROWSER_STATEMENT
**Statement
2417 FORM_BROWSER_STATEMENT
*Question
;
2418 FORM_BROWSER_FORM
*Form
;
2419 LIST_ENTRY
*LinkForm
;
2421 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2422 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2423 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2424 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2426 if ((*CurrentForm
!= NULL
) && (*CurrentForm
!= Form
)) {
2430 Link
= GetFirstNode (&Form
->StatementListHead
);
2431 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2432 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2433 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2434 if (EFI_ERROR (Status
)) {
2435 if (*CurrentForm
== NULL
) {
2436 *CurrentForm
= Form
;
2439 if (Statement
!= NULL
) {
2440 *Statement
= Question
;
2446 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2454 Fill storage's edit copy with settings requested from Configuration Driver.
2456 @param Storage The storage which need to sync.
2457 @param ConfigRequest The config request string which used to sync storage.
2458 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2459 editbuffer to buffer
2460 if TRUE, copy the editbuffer to the buffer.
2461 if FALSE, copy the buffer to the editbuffer.
2463 @retval EFI_SUCCESS The function completed successfully.
2467 SynchronizeStorage (
2468 OUT BROWSER_STORAGE
*Storage
,
2469 IN CHAR16
*ConfigRequest
,
2470 IN BOOLEAN SyncOrRestore
2474 EFI_STRING Progress
;
2478 NAME_VALUE_NODE
*Node
;
2482 Status
= EFI_SUCCESS
;
2485 if ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
2486 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
))
2488 BufferSize
= Storage
->Size
;
2490 if (SyncOrRestore
) {
2491 Src
= Storage
->EditBuffer
;
2492 Dst
= Storage
->Buffer
;
2494 Src
= Storage
->Buffer
;
2495 Dst
= Storage
->EditBuffer
;
2498 if (ConfigRequest
!= NULL
) {
2499 Status
= mHiiConfigRouting
->BlockToConfig (
2507 if (EFI_ERROR (Status
)) {
2511 Status
= mHiiConfigRouting
->ConfigToBlock (
2518 if (Result
!= NULL
) {
2522 CopyMem (Dst
, Src
, BufferSize
);
2524 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2525 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2526 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2527 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2529 if (((ConfigRequest
!= NULL
) && (StrStr (ConfigRequest
, Node
->Name
) != NULL
)) ||
2530 (ConfigRequest
== NULL
))
2532 if (SyncOrRestore
) {
2533 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2535 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2539 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2547 When discard the question value, call the callback function with Changed type
2548 to inform the hii driver.
2550 @param FormSet FormSet data structure.
2551 @param Form Form data structure.
2555 SendDiscardInfoToDriver (
2556 IN FORM_BROWSER_FORMSET
*FormSet
,
2557 IN FORM_BROWSER_FORM
*Form
2561 FORM_BROWSER_STATEMENT
*Question
;
2562 EFI_IFR_TYPE_VALUE
*TypeValue
;
2563 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2565 if (FormSet
->ConfigAccess
== NULL
) {
2569 Link
= GetFirstNode (&Form
->StatementListHead
);
2570 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2571 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2572 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2574 if ((Question
->Storage
== NULL
) || (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2578 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2582 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2586 if (!Question
->ValueChanged
) {
2591 // Restore the question value before call the CHANGED callback type.
2593 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2595 if (Question
->Operand
== EFI_IFR_STRING_OP
) {
2596 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2599 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2600 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
2602 TypeValue
= &Question
->HiiValue
.Value
;
2605 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2606 FormSet
->ConfigAccess
->Callback (
2607 FormSet
->ConfigAccess
,
2608 EFI_BROWSER_ACTION_CHANGED
,
2609 Question
->QuestionId
,
2610 Question
->HiiValue
.Type
,
2618 When submit the question value, call the callback function with Submitted type
2619 to inform the hii driver.
2621 @param FormSet FormSet data structure.
2622 @param Form Form data structure.
2626 SubmitCallbackForForm (
2627 IN FORM_BROWSER_FORMSET
*FormSet
,
2628 IN FORM_BROWSER_FORM
*Form
2632 FORM_BROWSER_STATEMENT
*Question
;
2633 EFI_IFR_TYPE_VALUE
*TypeValue
;
2634 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2636 if (FormSet
->ConfigAccess
== NULL
) {
2640 Link
= GetFirstNode (&Form
->StatementListHead
);
2641 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2642 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2643 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2645 if ((Question
->Storage
== NULL
) || (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2649 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2653 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2657 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2658 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
2660 TypeValue
= &Question
->HiiValue
.Value
;
2663 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2664 FormSet
->ConfigAccess
->Callback (
2665 FormSet
->ConfigAccess
,
2666 EFI_BROWSER_ACTION_SUBMITTED
,
2667 Question
->QuestionId
,
2668 Question
->HiiValue
.Type
,
2676 When value set Success, call the submit callback function.
2678 @param FormSet FormSet data structure.
2679 @param Form Form data structure.
2684 IN FORM_BROWSER_FORMSET
*FormSet
,
2685 IN FORM_BROWSER_FORM
*Form
2688 FORM_BROWSER_FORM
*CurrentForm
;
2692 SubmitCallbackForForm (FormSet
, Form
);
2696 Link
= GetFirstNode (&FormSet
->FormListHead
);
2697 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2698 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2699 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2701 SubmitCallbackForForm (FormSet
, CurrentForm
);
2706 Validate the HiiHandle.
2708 @param HiiHandle The input HiiHandle which need to validate.
2710 @retval TRUE The handle is validate.
2711 @retval FALSE The handle is invalidate.
2716 EFI_HII_HANDLE HiiHandle
2719 EFI_HII_HANDLE
*HiiHandles
;
2723 if (HiiHandle
== NULL
) {
2729 HiiHandles
= HiiGetHiiHandles (NULL
);
2730 ASSERT (HiiHandles
!= NULL
);
2732 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2733 if (HiiHandles
[Index
] == HiiHandle
) {
2739 FreePool (HiiHandles
);
2745 Validate the FormSet. If the formset is not validate, remove it from the list.
2747 @param FormSet The input FormSet which need to validate.
2749 @retval TRUE The handle is validate.
2750 @retval FALSE The handle is invalidate.
2755 FORM_BROWSER_FORMSET
*FormSet
2760 ASSERT (FormSet
!= NULL
);
2762 Find
= ValidateHiiHandle (FormSet
->HiiHandle
);
2764 // Should not remove the formset which is being used.
2766 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2767 CleanBrowserStorage (FormSet
);
2768 RemoveEntryList (&FormSet
->Link
);
2769 DestroyFormSet (FormSet
);
2776 Check whether need to enable the reset flag in form level.
2777 Also clean all ValueChanged flag in question.
2779 @param SetFlag Whether need to set the Reset Flag.
2780 @param FormSet FormSet data structure.
2781 @param Form Form data structure.
2787 IN FORM_BROWSER_FORMSET
*FormSet
,
2788 IN FORM_BROWSER_FORM
*Form
2792 FORM_BROWSER_STATEMENT
*Question
;
2795 Link
= GetFirstNode (&Form
->StatementListHead
);
2796 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2797 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2798 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2800 if (!Question
->ValueChanged
) {
2804 OldValue
= Question
->ValueChanged
;
2807 // Compare the buffer and editbuffer data to see whether the data has been saved.
2809 Question
->ValueChanged
= IsQuestionValueChanged (FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2812 // Only the changed data has been saved, then need to set the reset flag.
2814 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2815 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2816 gResetRequiredFormLevel
= TRUE
;
2817 gResetRequiredSystemLevel
= TRUE
;
2820 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2821 gFlagReconnect
= TRUE
;
2828 Check whether need to enable the reset flag.
2829 Also clean ValueChanged flag for all statements.
2831 Form level or formset level, only one.
2833 @param SetFlag Whether need to set the Reset Flag.
2834 @param FormSet FormSet data structure.
2835 @param Form Form data structure.
2839 ValueChangeResetFlagUpdate (
2841 IN FORM_BROWSER_FORMSET
*FormSet
,
2842 IN FORM_BROWSER_FORM
*Form
2845 FORM_BROWSER_FORM
*CurrentForm
;
2849 UpdateFlagForForm (SetFlag
, FormSet
, Form
);
2853 Link
= GetFirstNode (&FormSet
->FormListHead
);
2854 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2855 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2856 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2858 UpdateFlagForForm (SetFlag
, FormSet
, CurrentForm
);
2863 Base on the return Progress string to find the form.
2865 Base on the first return Offset/Width (Name) string to find the form
2866 which keep this string.
2868 @param FormSet FormSet data structure.
2869 @param Storage Storage which has this Progress string.
2870 @param Progress The Progress string which has the first fail string.
2871 @param RetForm The return form for this progress string.
2872 @param RetQuestion The return question for the error progress string.
2874 @retval TRUE Find the error form and statement for this error progress string.
2875 @retval FALSE Not find the error form.
2879 FindQuestionFromProgress (
2880 IN FORM_BROWSER_FORMSET
*FormSet
,
2881 IN BROWSER_STORAGE
*Storage
,
2882 IN EFI_STRING Progress
,
2883 OUT FORM_BROWSER_FORM
**RetForm
,
2884 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2888 LIST_ENTRY
*LinkStorage
;
2889 LIST_ENTRY
*LinkStatement
;
2890 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2891 FORM_BROWSER_FORM
*Form
;
2893 FORM_BROWSER_STATEMENT
*Statement
;
2895 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2899 *RetQuestion
= NULL
;
2902 // Skip the first "&" or the ConfigHdr part.
2904 if (*Progress
== '&') {
2908 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2910 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2912 // For Name/Value type, Skip the ConfigHdr part.
2914 EndStr
= StrStr (Progress
, L
"PATH=");
2915 ASSERT (EndStr
!= NULL
);
2916 while (*EndStr
!= '&') {
2923 // For Buffer type, Skip the ConfigHdr part.
2925 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2926 ASSERT (EndStr
!= NULL
);
2930 Progress
= EndStr
+ 1;
2934 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2936 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2938 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2939 // here, just keep the "Fred" string.
2941 EndStr
= StrStr (Progress
, L
"=");
2942 ASSERT (EndStr
!= NULL
);
2946 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2947 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2949 EndStr
= StrStr (Progress
, L
"&VALUE=");
2950 ASSERT (EndStr
!= NULL
);
2955 // Search in the form list.
2957 Link
= GetFirstNode (&FormSet
->FormListHead
);
2958 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2959 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2960 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2963 // Search in the ConfigReqeust list in this form.
2965 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2966 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2967 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2968 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2970 if (Storage
!= ConfigInfo
->Storage
) {
2974 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2976 // Find the OffsetWidth string in this form.
2983 if (*RetForm
!= NULL
) {
2984 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2985 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2986 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2987 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2989 if ((Statement
->BlockName
!= NULL
) && (StrStr (Statement
->BlockName
, Progress
) != NULL
)) {
2990 *RetQuestion
= Statement
;
2994 if ((Statement
->VariableName
!= NULL
) && (StrStr (Statement
->VariableName
, Progress
) != NULL
)) {
2995 *RetQuestion
= Statement
;
3001 if (*RetForm
!= NULL
) {
3007 // restore the OffsetWidth string to the original format.
3009 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3015 return (BOOLEAN
)(*RetForm
!= NULL
);
3019 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
3020 for form and formset.
3022 @param Storage Storage which has this Progress string.
3023 @param ConfigRequest The ConfigRequest string.
3024 @param Progress The Progress string which has the first fail string.
3025 @param RestoreConfigRequest Return the RestoreConfigRequest string.
3026 @param SyncConfigRequest Return the SyncConfigRequest string.
3030 GetSyncRestoreConfigRequest (
3031 IN BROWSER_STORAGE
*Storage
,
3032 IN EFI_STRING ConfigRequest
,
3033 IN EFI_STRING Progress
,
3034 OUT EFI_STRING
*RestoreConfigRequest
,
3035 OUT EFI_STRING
*SyncConfigRequest
3039 EFI_STRING ConfigHdrEndStr
;
3040 EFI_STRING ElementStr
;
3042 UINTN RestoreEleSize
;
3045 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3047 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3048 // Need to restore all the fields in the ConfigRequest.
3050 if (*Progress
== L
'G') {
3051 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3052 ASSERT (*RestoreConfigRequest
!= NULL
);
3057 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3059 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3061 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3062 // here, just keep the "Fred" string.
3064 EndStr
= StrStr (Progress
, L
"=");
3065 ASSERT (EndStr
!= NULL
);
3068 // Find the ConfigHdr in ConfigRequest.
3070 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3071 ASSERT (ConfigHdrEndStr
!= NULL
);
3072 while (*ConfigHdrEndStr
!= L
'&') {
3077 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3078 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3080 EndStr
= StrStr (Progress
, L
"&VALUE=");
3081 ASSERT (EndStr
!= NULL
);
3084 // Find the ConfigHdr in ConfigRequest.
3086 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3090 // Find the first fail pair in the ConfigRequest.
3092 ElementStr
= StrStr (ConfigRequest
, Progress
);
3093 ASSERT (ElementStr
!= NULL
);
3095 // To get the RestoreConfigRequest.
3097 RestoreEleSize
= StrSize (ElementStr
);
3098 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3099 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3100 ASSERT (*RestoreConfigRequest
!= NULL
);
3101 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3102 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3104 // To get the SyncConfigRequest.
3106 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3107 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3108 ASSERT (*SyncConfigRequest
!= NULL
);
3109 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3112 // restore the Progress string to the original format.
3114 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3122 Popup an save error info and get user input.
3124 @param TitleId The form title id.
3125 @param HiiHandle The hii handle for this package.
3127 @retval UINT32 The user select option for the save fail.
3128 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3132 IN EFI_STRING_ID TitleId
,
3133 IN EFI_HII_HANDLE HiiHandle
3137 CHAR16
*StringBuffer
;
3140 FormTitle
= GetToken (TitleId
, HiiHandle
);
3142 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3143 ASSERT (StringBuffer
!= NULL
);
3147 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3148 L
"Submit Fail For Form: %s.",
3152 RetVal
= PopupErrorMessage (BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3154 FreePool (StringBuffer
);
3155 FreePool (FormTitle
);
3161 Popup an NO_SUBMIT_IF error info and get user input.
3163 @param TitleId The form title id.
3164 @param HiiHandle The hii handle for this package.
3166 @retval UINT32 The user select option for the save fail.
3167 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3170 ConfirmNoSubmitFail (
3171 IN EFI_STRING_ID TitleId
,
3172 IN EFI_HII_HANDLE HiiHandle
3176 CHAR16
*StringBuffer
;
3179 FormTitle
= GetToken (TitleId
, HiiHandle
);
3181 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3182 ASSERT (StringBuffer
!= NULL
);
3186 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3187 L
"NO_SUBMIT_IF error For Form: %s.",
3191 RetVal
= PopupErrorMessage (BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3193 FreePool (StringBuffer
);
3194 FreePool (FormTitle
);
3200 Discard data based on the input setting scope (Form, FormSet or System).
3202 @param FormSet FormSet data structure.
3203 @param Form Form data structure.
3204 @param SettingScope Setting Scope for Discard action.
3206 @retval EFI_SUCCESS The function completed successfully.
3207 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3212 IN FORM_BROWSER_FORMSET
*FormSet
,
3213 IN FORM_BROWSER_FORM
*Form
,
3214 IN BROWSER_SETTING_SCOPE SettingScope
3218 FORMSET_STORAGE
*Storage
;
3219 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3220 FORM_BROWSER_FORMSET
*LocalFormSet
;
3221 FORM_BROWSER_FORMSET
*OldFormSet
;
3224 // Check the supported setting level.
3226 if (SettingScope
>= MaxLevel
) {
3227 return EFI_UNSUPPORTED
;
3230 if ((SettingScope
== FormLevel
) && IsNvUpdateRequiredForForm (Form
)) {
3232 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3233 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3234 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3235 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3237 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3242 // Skip if there is no RequestElement
3244 if (ConfigInfo
->ElementCount
== 0) {
3249 // Prepare <ConfigResp>
3251 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3254 // Call callback with Changed type to inform the driver.
3256 SendDiscardInfoToDriver (FormSet
, Form
);
3259 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3260 } else if ((SettingScope
== FormSetLevel
) && IsNvUpdateRequiredForFormSet (FormSet
)) {
3262 // Discard Buffer storage or Name/Value storage
3264 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3265 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3266 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3267 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3269 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3274 // Skip if there is no RequestElement
3276 if (Storage
->ElementCount
== 0) {
3280 SynchronizeStorage (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3283 Link
= GetFirstNode (&FormSet
->FormListHead
);
3284 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3285 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3286 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3289 // Call callback with Changed type to inform the driver.
3291 SendDiscardInfoToDriver (FormSet
, Form
);
3294 ValueChangeResetFlagUpdate (FALSE
, FormSet
, NULL
);
3295 } else if (SettingScope
== SystemLevel
) {
3297 // System Level Discard.
3299 OldFormSet
= mSystemLevelFormSet
;
3302 // Discard changed value for each FormSet in the maintain list.
3304 Link
= GetFirstNode (&gBrowserFormSetList
);
3305 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3306 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3307 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3308 if (!ValidateFormSet (LocalFormSet
)) {
3312 mSystemLevelFormSet
= LocalFormSet
;
3314 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3315 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3317 // Remove maintain backup list after discard except for the current using FormSet.
3319 CleanBrowserStorage (LocalFormSet
);
3320 RemoveEntryList (&LocalFormSet
->Link
);
3321 DestroyFormSet (LocalFormSet
);
3325 mSystemLevelFormSet
= OldFormSet
;
3332 Submit data for a form.
3334 @param FormSet FormSet data structure.
3335 @param Form Form data structure.
3337 @retval EFI_SUCCESS The function completed successfully.
3338 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3343 IN FORM_BROWSER_FORMSET
*FormSet
,
3344 IN FORM_BROWSER_FORM
*Form
3349 EFI_STRING ConfigResp
;
3350 EFI_STRING Progress
;
3351 BROWSER_STORAGE
*Storage
;
3352 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3353 BOOLEAN SubmitFormFail
;
3355 SubmitFormFail
= FALSE
;
3357 if (!IsNvUpdateRequiredForForm (Form
)) {
3361 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3362 if (EFI_ERROR (Status
)) {
3366 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3367 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3368 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3369 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3371 Storage
= ConfigInfo
->Storage
;
3372 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3377 // Skip if there is no RequestElement
3379 if (ConfigInfo
->ElementCount
== 0) {
3384 // 1. Prepare <ConfigResp>
3386 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3387 if (EFI_ERROR (Status
)) {
3392 // 2. Set value to hii config routine protocol.
3394 Status
= mHiiConfigRouting
->RouteConfig (
3400 if (EFI_ERROR (Status
)) {
3402 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3404 SubmitFormFail
= TRUE
;
3405 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3406 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3407 FreePool (ConfigResp
);
3411 FreePool (ConfigResp
);
3413 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3415 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3419 // 4. Process the save failed storage.
3421 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3422 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3423 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3424 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3425 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3426 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3428 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3429 // base on the SyncConfigRequest to Sync the buffer.
3431 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3432 FreePool (ConfigInfo
->RestoreConfigRequest
);
3433 ConfigInfo
->RestoreConfigRequest
= NULL
;
3434 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3435 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3436 FreePool (ConfigInfo
->SyncConfigRequest
);
3437 ConfigInfo
->SyncConfigRequest
= NULL
;
3440 Status
= EFI_SUCCESS
;
3443 SendDiscardInfoToDriver (FormSet
, Form
);
3445 Status
= EFI_UNSUPPORTED
;
3449 // Free Form save fail list.
3451 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3452 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3453 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3454 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3459 // 5. Update the NV flag.
3461 ValueChangeResetFlagUpdate (TRUE
, FormSet
, Form
);
3464 // 6 Call callback with Submitted type to inform the driver.
3466 if (!SubmitFormFail
) {
3467 SubmitCallback (FormSet
, Form
);
3474 Submit data for a formset.
3476 @param FormSet FormSet data structure.
3477 @param SkipProcessFail Whether skip to process the save failed storage.
3478 If submit formset is called when do system level save,
3479 set this value to true and process the failed formset
3481 if submit formset is called when do formset level save,
3482 set the value to false and process the failed storage
3483 right after process all storages for this formset.
3485 @retval EFI_SUCCESS The function completed successfully.
3486 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3491 IN FORM_BROWSER_FORMSET
*FormSet
,
3492 IN BOOLEAN SkipProcessFail
3497 EFI_STRING ConfigResp
;
3498 EFI_STRING Progress
;
3499 BROWSER_STORAGE
*Storage
;
3500 FORMSET_STORAGE
*FormSetStorage
;
3501 FORM_BROWSER_FORM
*Form
;
3502 BOOLEAN HasInserted
;
3503 FORM_BROWSER_STATEMENT
*Question
;
3504 BOOLEAN SubmitFormSetFail
;
3505 BOOLEAN DiscardChange
;
3507 HasInserted
= FALSE
;
3508 SubmitFormSetFail
= FALSE
;
3509 DiscardChange
= FALSE
;
3511 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3516 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3517 if (EFI_ERROR (Status
)) {
3518 if (SkipProcessFail
) {
3520 // Process NO_SUBMIT check first, so insert it at head.
3522 FormSet
->SaveFailForm
= Form
;
3523 FormSet
->SaveFailStatement
= Question
;
3524 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3533 // Submit Buffer storage or Name/Value storage
3535 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3536 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3537 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3538 Storage
= FormSetStorage
->BrowserStorage
;
3539 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3541 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3546 // Skip if there is no RequestElement
3548 if (FormSetStorage
->ElementCount
== 0) {
3553 // 1. Prepare <ConfigResp>
3555 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3556 if (EFI_ERROR (Status
)) {
3561 // 2. Send <ConfigResp> to Routine config Protocol.
3563 Status
= mHiiConfigRouting
->RouteConfig (
3568 if (EFI_ERROR (Status
)) {
3570 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3572 SubmitFormSetFail
= TRUE
;
3573 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3574 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3577 // Call submit formset for system level, save the formset info
3578 // and process later.
3580 FindQuestionFromProgress (FormSet
, Storage
, Progress
, &Form
, &Question
);
3581 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3582 FormSet
->SaveFailForm
= Form
;
3583 FormSet
->SaveFailStatement
= Question
;
3584 if (SkipProcessFail
) {
3585 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3591 FreePool (ConfigResp
);
3595 FreePool (ConfigResp
);
3597 // 3. Config success, update storage shadow Buffer
3599 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3603 // 4. Has save fail storage need to handle.
3606 if (!SkipProcessFail
) {
3608 // If not in system level, just handl the save failed storage here.
3610 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3611 DiscardChange
= TRUE
;
3612 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3613 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3614 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3615 Storage
= FormSetStorage
->BrowserStorage
;
3616 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3618 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3619 // base on the SyncConfigRequest to Sync the buffer.
3621 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3622 FreePool (FormSetStorage
->RestoreConfigRequest
);
3623 FormSetStorage
->RestoreConfigRequest
= NULL
;
3624 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3625 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3626 FreePool (FormSetStorage
->SyncConfigRequest
);
3627 FormSetStorage
->SyncConfigRequest
= NULL
;
3630 Status
= EFI_SUCCESS
;
3633 UiCopyMenuList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3635 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3636 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3637 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3638 gCurrentSelection
->FormId
= Form
->FormId
;
3639 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3641 Status
= EFI_UNSUPPORTED
;
3645 // Free FormSet save fail list.
3647 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3648 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3649 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3650 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3654 // If in system level, just return error and handle the failed formset later.
3656 Status
= EFI_UNSUPPORTED
;
3661 // If user discard the change, send the discard info to driver.
3663 if (DiscardChange
) {
3664 Link
= GetFirstNode (&FormSet
->FormListHead
);
3665 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3666 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3667 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3669 // Call callback with Changed type to inform the driver.
3671 SendDiscardInfoToDriver (FormSet
, Form
);
3676 // 5. Update the NV flag.
3678 ValueChangeResetFlagUpdate (TRUE
, FormSet
, NULL
);
3681 // 6. Call callback with Submitted type to inform the driver.
3683 if (!SubmitFormSetFail
) {
3684 SubmitCallback (FormSet
, NULL
);
3691 Submit data for all formsets.
3693 @retval EFI_SUCCESS The function completed successfully.
3694 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3704 LIST_ENTRY
*FormLink
;
3705 LIST_ENTRY
*StorageLink
;
3706 FORMSET_STORAGE
*FormSetStorage
;
3707 FORM_BROWSER_FORM
*Form
;
3708 FORM_BROWSER_FORMSET
*LocalFormSet
;
3709 UINT32 UserSelection
;
3710 FORM_BROWSER_STATEMENT
*Question
;
3712 mSystemSubmit
= TRUE
;
3713 Link
= GetFirstNode (&gBrowserFormSetList
);
3714 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3715 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3716 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3717 if (!ValidateFormSet (LocalFormSet
)) {
3721 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3722 if (EFI_ERROR (Status
)) {
3727 // Remove maintain backup list after save except for the current using FormSet.
3729 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3730 CleanBrowserStorage (LocalFormSet
);
3731 RemoveEntryList (&LocalFormSet
->Link
);
3732 DestroyFormSet (LocalFormSet
);
3736 mSystemSubmit
= FALSE
;
3738 Status
= EFI_SUCCESS
;
3741 // Process the save failed formsets.
3743 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3744 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3745 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3746 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3748 if (!ValidateFormSet (LocalFormSet
)) {
3752 Form
= LocalFormSet
->SaveFailForm
;
3753 Question
= LocalFormSet
->SaveFailStatement
;
3756 // Confirm with user, get user input.
3758 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3760 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3762 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3764 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3767 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3768 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3769 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3770 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3771 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3772 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3774 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3777 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3778 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3779 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3780 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3782 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3783 // base on the SyncConfigRequest to Sync the buffer.
3785 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3786 FreePool (FormSetStorage
->RestoreConfigRequest
);
3787 FormSetStorage
->RestoreConfigRequest
= NULL
;
3788 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3789 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3790 FreePool (FormSetStorage
->SyncConfigRequest
);
3791 FormSetStorage
->SyncConfigRequest
= NULL
;
3796 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3797 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3798 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3799 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3801 // Call callback with Changed type to inform the driver.
3803 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3806 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3807 CleanBrowserStorage (LocalFormSet
);
3808 RemoveEntryList (&LocalFormSet
->Link
);
3809 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3810 DestroyFormSet (LocalFormSet
);
3812 ValueChangeResetFlagUpdate (FALSE
, LocalFormSet
, NULL
);
3815 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3816 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3819 UiCopyMenuList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3821 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3822 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3823 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3824 gCurrentSelection
->FormId
= Form
->FormId
;
3825 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3827 Status
= EFI_UNSUPPORTED
;
3833 // Clean the list which will not process.
3835 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3836 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3837 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3838 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3840 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3841 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3842 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3843 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3851 Submit data based on the input Setting level (Form, FormSet or System).
3853 @param FormSet FormSet data structure.
3854 @param Form Form data structure.
3855 @param SettingScope Setting Scope for Submit action.
3857 @retval EFI_SUCCESS The function completed successfully.
3858 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3863 IN FORM_BROWSER_FORMSET
*FormSet
,
3864 IN FORM_BROWSER_FORM
*Form
,
3865 IN BROWSER_SETTING_SCOPE SettingScope
3870 switch (SettingScope
) {
3872 Status
= SubmitForForm (FormSet
, Form
);
3876 Status
= SubmitForFormSet (FormSet
, FALSE
);
3880 Status
= SubmitForSystem ();
3884 Status
= EFI_UNSUPPORTED
;
3892 Converts the unicode character of the string from uppercase to lowercase.
3893 This is a internal function.
3895 @param ConfigString String to be converted
3901 IN EFI_STRING ConfigString
3907 ASSERT (ConfigString
!= NULL
);
3910 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3912 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3913 if (*String
== L
'=') {
3915 } else if (*String
== L
'&') {
3917 } else if (Lower
&& (*String
>= L
'A') && (*String
<= L
'F')) {
3918 *String
= (CHAR16
)(*String
- L
'A' + L
'a');
3924 Find the point in the ConfigResp string for this question.
3926 @param Question The question.
3927 @param ConfigResp Get ConfigResp string.
3929 @retval point to the offset where is for this question.
3933 GetOffsetFromConfigResp (
3934 IN FORM_BROWSER_STATEMENT
*Question
,
3935 IN CHAR16
*ConfigResp
3938 CHAR16
*RequestElement
;
3942 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3944 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3945 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3946 if (RequestElement
!= NULL
) {
3948 // Skip the "VariableName=" field.
3950 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3953 return RequestElement
;
3957 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3961 // Convert all hex digits in ConfigResp to lower case before searching.
3963 HiiToLower (ConfigResp
);
3966 // 1. Directly use Question->BlockName to find.
3968 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3969 if (RequestElement
!= NULL
) {
3971 // Skip the "Question->BlockName&VALUE=" field.
3973 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3974 return RequestElement
;
3978 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3980 BlockData
= AllocateCopyPool (StrSize (Question
->BlockName
), Question
->BlockName
);
3981 ASSERT (BlockData
!= NULL
);
3982 HiiToLower (BlockData
);
3983 RequestElement
= StrStr (ConfigResp
, BlockData
);
3984 FreePool (BlockData
);
3986 if (RequestElement
!= NULL
) {
3988 // Skip the "Question->BlockName&VALUE=" field.
3990 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3993 return RequestElement
;
3997 Get Question default value from AltCfg string.
3999 @param FormSet The form set.
4000 @param Form The form
4001 @param Question The question.
4003 @retval EFI_SUCCESS Question is reset to default value.
4007 GetDefaultValueFromAltCfg (
4008 IN FORM_BROWSER_FORMSET
*FormSet
,
4009 IN FORM_BROWSER_FORM
*Form
,
4010 IN OUT FORM_BROWSER_STATEMENT
*Question
4013 BROWSER_STORAGE
*Storage
;
4014 FORMSET_STORAGE
*FormSetStorage
;
4018 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4020 Storage
= Question
->Storage
;
4021 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4022 return EFI_NOT_FOUND
;
4026 // Try to get AltCfg string from form. If not found it, then
4027 // try to get it from formset.
4030 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4031 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4032 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4033 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4035 if (Storage
== ConfigInfo
->Storage
) {
4036 ConfigResp
= ConfigInfo
->ConfigAltResp
;
4041 if (ConfigResp
== NULL
) {
4042 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4043 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4044 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4045 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4047 if (Storage
== FormSetStorage
->BrowserStorage
) {
4048 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4054 if (ConfigResp
== NULL
) {
4055 return EFI_NOT_FOUND
;
4058 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4059 if (Value
== NULL
) {
4060 return EFI_NOT_FOUND
;
4063 return BufferToValue (Question
, Value
);
4067 Get default Id value used for browser.
4069 @param DefaultId The default id value used by hii.
4071 @retval Browser used default value.
4075 GetDefaultIdForCallBack (
4079 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4080 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4081 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4082 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4083 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4084 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4085 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000)) {
4086 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4087 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000)) {
4088 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4089 } else if ((DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
) && (DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000)) {
4090 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4097 Return data element in an Array by its Index.
4099 @param Array The data array.
4100 @param Type Type of the data in this array.
4101 @param Index Zero based index for data in this array.
4103 @retval Value The data to be returned
4115 ASSERT (Array
!= NULL
);
4119 case EFI_IFR_TYPE_NUM_SIZE_8
:
4120 Data
= (UINT64
)*(((UINT8
*)Array
) + Index
);
4123 case EFI_IFR_TYPE_NUM_SIZE_16
:
4124 Data
= (UINT64
)*(((UINT16
*)Array
) + Index
);
4127 case EFI_IFR_TYPE_NUM_SIZE_32
:
4128 Data
= (UINT64
)*(((UINT32
*)Array
) + Index
);
4131 case EFI_IFR_TYPE_NUM_SIZE_64
:
4132 Data
= (UINT64
)*(((UINT64
*)Array
) + Index
);
4143 Set value of a data element in an Array by its Index.
4145 @param Array The data array.
4146 @param Type Type of the data in this array.
4147 @param Index Zero based index for data in this array.
4148 @param Value The value to be set.
4159 ASSERT (Array
!= NULL
);
4162 case EFI_IFR_TYPE_NUM_SIZE_8
:
4163 *(((UINT8
*)Array
) + Index
) = (UINT8
)Value
;
4166 case EFI_IFR_TYPE_NUM_SIZE_16
:
4167 *(((UINT16
*)Array
) + Index
) = (UINT16
)Value
;
4170 case EFI_IFR_TYPE_NUM_SIZE_32
:
4171 *(((UINT32
*)Array
) + Index
) = (UINT32
)Value
;
4174 case EFI_IFR_TYPE_NUM_SIZE_64
:
4175 *(((UINT64
*)Array
) + Index
) = (UINT64
)Value
;
4184 Search an Option of a Question by its value.
4186 @param Question The Question
4187 @param OptionValue Value for Option to be searched.
4189 @retval Pointer Pointer to the found Option.
4190 @retval NULL Option not found.
4195 IN FORM_BROWSER_STATEMENT
*Question
,
4196 IN EFI_HII_VALUE
*OptionValue
4200 QUESTION_OPTION
*Option
;
4203 Link
= GetFirstNode (&Question
->OptionListHead
);
4204 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4205 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4207 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4209 // Check the suppressif condition, only a valid option can be return.
4211 if ((Option
->SuppressExpression
== NULL
) ||
4212 ((EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
)))
4218 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4225 Reset Question to its default value.
4227 @param FormSet The form set.
4228 @param Form The form.
4229 @param Question The question.
4230 @param DefaultId The Class of the default.
4232 @retval EFI_SUCCESS Question is reset to default value.
4236 GetQuestionDefault (
4237 IN FORM_BROWSER_FORMSET
*FormSet
,
4238 IN FORM_BROWSER_FORM
*Form
,
4239 IN FORM_BROWSER_STATEMENT
*Question
,
4245 QUESTION_DEFAULT
*Default
;
4246 QUESTION_OPTION
*Option
;
4247 EFI_HII_VALUE
*HiiValue
;
4249 EFI_STRING StrValue
;
4250 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4251 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4254 EFI_IFR_TYPE_VALUE
*TypeValue
;
4255 UINT16 OriginalDefaultId
;
4256 FORMSET_DEFAULTSTORE
*DefaultStore
;
4257 LIST_ENTRY
*DefaultLink
;
4259 Status
= EFI_NOT_FOUND
;
4261 OriginalDefaultId
= DefaultId
;
4262 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4265 // Statement don't have storage, skip them
4267 if (Question
->QuestionId
== 0) {
4272 // There are Five ways to specify default value for a Question:
4273 // 1, use call back function (highest priority)
4274 // 2, use ExtractConfig function
4275 // 3, use nested EFI_IFR_DEFAULT
4276 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4277 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4280 HiiValue
= &Question
->HiiValue
;
4281 TypeValue
= &HiiValue
->Value
;
4282 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4284 // For orderedlist, need to pass the BufferValue to Callback function.
4286 TypeValue
= (EFI_IFR_TYPE_VALUE
*)Question
->BufferValue
;
4290 // Get Question defaut value from call back function.
4292 ConfigAccess
= FormSet
->ConfigAccess
;
4293 Action
= GetDefaultIdForCallBack (DefaultId
);
4294 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4295 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4296 Status
= ConfigAccess
->Callback (
4299 Question
->QuestionId
,
4304 if (!EFI_ERROR (Status
)) {
4305 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4306 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4307 ASSERT (NewString
!= NULL
);
4309 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4310 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4311 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4312 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4314 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4317 FreePool (NewString
);
4325 // Get default value from altcfg string.
4327 if (ConfigAccess
!= NULL
) {
4328 Status
= GetDefaultValueFromAltCfg (FormSet
, Form
, Question
);
4329 if (!EFI_ERROR (Status
)) {
4335 // EFI_IFR_DEFAULT has highest priority
4337 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4338 Link
= GetFirstNode (&Question
->DefaultListHead
);
4339 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4340 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4342 if (Default
->DefaultId
== DefaultId
) {
4343 if (Default
->ValueExpression
!= NULL
) {
4345 // Default is provided by an Expression, evaluate it
4347 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4348 if (EFI_ERROR (Status
)) {
4352 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4353 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4354 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4355 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4356 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4358 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4359 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4362 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4365 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4366 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4369 // Default value is embedded in EFI_IFR_DEFAULT
4371 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4372 ASSERT (HiiValue
->Buffer
!= NULL
);
4373 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4375 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4379 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4380 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4381 if (StrValue
== NULL
) {
4382 return EFI_NOT_FOUND
;
4385 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4386 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4387 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4389 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4396 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4401 // EFI_ONE_OF_OPTION
4403 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4404 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4406 // OneOfOption could only provide Standard and Manufacturing default
4408 Link
= GetFirstNode (&Question
->OptionListHead
);
4409 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4410 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4411 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4413 if ((Option
->SuppressExpression
!= NULL
) &&
4414 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4419 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4420 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4423 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4432 // EFI_IFR_CHECKBOX - lowest priority
4434 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4435 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4437 // Checkbox could only provide Standard and Manufacturing default
4439 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4440 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4443 HiiValue
->Value
.b
= TRUE
;
4451 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4452 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4453 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4455 while (!IsNull (&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4456 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink
);
4457 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
, DefaultLink
);
4458 DefaultId
= DefaultStore
->DefaultId
;
4459 if (DefaultId
== OriginalDefaultId
) {
4467 // For Questions without default value for all the default id in the DefaultStoreList.
4469 Status
= EFI_NOT_FOUND
;
4470 switch (Question
->Operand
) {
4471 case EFI_IFR_CHECKBOX_OP
:
4472 HiiValue
->Value
.b
= FALSE
;
4473 Status
= EFI_SUCCESS
;
4476 case EFI_IFR_NUMERIC_OP
:
4478 // Take minimum value as numeric default value
4480 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4482 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4484 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4485 case EFI_IFR_NUMERIC_SIZE_1
:
4486 if (((INT8
)HiiValue
->Value
.u8
< (INT8
)Question
->Minimum
) || ((INT8
)HiiValue
->Value
.u8
> (INT8
)Question
->Maximum
)) {
4487 HiiValue
->Value
.u8
= (UINT8
)Question
->Minimum
;
4488 Status
= EFI_SUCCESS
;
4492 case EFI_IFR_NUMERIC_SIZE_2
:
4493 if (((INT16
)HiiValue
->Value
.u16
< (INT16
)Question
->Minimum
) || ((INT16
)HiiValue
->Value
.u16
> (INT16
)Question
->Maximum
)) {
4494 HiiValue
->Value
.u16
= (UINT16
)Question
->Minimum
;
4495 Status
= EFI_SUCCESS
;
4499 case EFI_IFR_NUMERIC_SIZE_4
:
4500 if (((INT32
)HiiValue
->Value
.u32
< (INT32
)Question
->Minimum
) || ((INT32
)HiiValue
->Value
.u32
> (INT32
)Question
->Maximum
)) {
4501 HiiValue
->Value
.u32
= (UINT32
)Question
->Minimum
;
4502 Status
= EFI_SUCCESS
;
4506 case EFI_IFR_NUMERIC_SIZE_8
:
4507 if (((INT64
)HiiValue
->Value
.u64
< (INT64
)Question
->Minimum
) || ((INT64
)HiiValue
->Value
.u64
> (INT64
)Question
->Maximum
)) {
4508 HiiValue
->Value
.u64
= Question
->Minimum
;
4509 Status
= EFI_SUCCESS
;
4517 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4518 HiiValue
->Value
.u64
= Question
->Minimum
;
4519 Status
= EFI_SUCCESS
;
4525 case EFI_IFR_ONE_OF_OP
:
4527 // Take first oneof option as oneof's default value
4529 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4530 Link
= GetFirstNode (&Question
->OptionListHead
);
4531 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4532 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4533 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4535 if ((Option
->SuppressExpression
!= NULL
) &&
4536 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4541 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4542 Status
= EFI_SUCCESS
;
4549 case EFI_IFR_ORDERED_LIST_OP
:
4551 // Take option sequence in IFR as ordered list's default value
4554 Link
= GetFirstNode (&Question
->OptionListHead
);
4555 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4556 Status
= EFI_SUCCESS
;
4557 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4558 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4560 if ((Option
->SuppressExpression
!= NULL
) &&
4561 (EvaluateExpressionList (Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
))
4566 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4569 if (Index
>= Question
->MaxContainers
) {
4584 Get AltCfg string for current form.
4586 @param FormSet Form data structure.
4587 @param Form Form data structure.
4588 @param DefaultId The Class of the default.
4589 @param BrowserStorage The input request storage for the questions.
4593 ExtractAltCfgForForm (
4594 IN FORM_BROWSER_FORMSET
*FormSet
,
4595 IN FORM_BROWSER_FORM
*Form
,
4596 IN UINT16 DefaultId
,
4597 IN BROWSER_STORAGE
*BrowserStorage
4605 BROWSER_STORAGE
*Storage
;
4606 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4607 FORMSET_STORAGE
*FormSetStorage
;
4610 // Check whether has get AltCfg string for this formset.
4611 // If yes, no need to get AltCfg for form.
4613 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4614 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4615 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4616 Storage
= FormSetStorage
->BrowserStorage
;
4617 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4618 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4622 if ((Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
) &&
4623 (FormSetStorage
->ElementCount
!= 0) &&
4624 FormSetStorage
->HasCallAltCfg
)
4631 // Get AltCfg string for each form.
4633 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4634 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4635 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4636 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4638 Storage
= ConfigInfo
->Storage
;
4639 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4643 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4648 // 1. Skip if there is no RequestElement
4650 if (ConfigInfo
->ElementCount
== 0) {
4655 // 2. Get value through hii config routine protocol.
4657 Status
= mHiiConfigRouting
->ExtractConfig (
4659 ConfigInfo
->ConfigRequest
,
4663 if (EFI_ERROR (Status
)) {
4668 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4669 // Get the default configuration string according to the default ID.
4671 Status
= mHiiConfigRouting
->GetAltConfig (
4677 &DefaultId
, // it can be NULL to get the current setting.
4681 if (EFI_ERROR (Status
)) {
4685 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4690 Clean AltCfg string for current form.
4692 @param Form Form data structure.
4696 CleanAltCfgForForm (
4697 IN FORM_BROWSER_FORM
*Form
4701 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4703 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4704 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4705 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4706 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4708 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4709 FreePool (ConfigInfo
->ConfigAltResp
);
4710 ConfigInfo
->ConfigAltResp
= NULL
;
4716 Get AltCfg string for current formset.
4718 @param FormSet Form data structure.
4719 @param DefaultId The Class of the default.
4720 @param BrowserStorage The input request storage for the questions.
4724 ExtractAltCfgForFormSet (
4725 IN FORM_BROWSER_FORMSET
*FormSet
,
4726 IN UINT16 DefaultId
,
4727 IN BROWSER_STORAGE
*BrowserStorage
4735 BROWSER_STORAGE
*Storage
;
4736 FORMSET_STORAGE
*FormSetStorage
;
4738 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4739 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4740 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4741 Storage
= FormSetStorage
->BrowserStorage
;
4742 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4744 if ((BrowserStorage
!= NULL
) && (BrowserStorage
!= Storage
)) {
4748 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4753 // 1. Skip if there is no RequestElement
4755 if (FormSetStorage
->ElementCount
== 0) {
4759 FormSetStorage
->HasCallAltCfg
= TRUE
;
4762 // 2. Get value through hii config routine protocol.
4764 Status
= mHiiConfigRouting
->ExtractConfig (
4766 FormSetStorage
->ConfigRequest
,
4770 if (EFI_ERROR (Status
)) {
4775 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4776 // Get the default configuration string according to the default ID.
4778 Status
= mHiiConfigRouting
->GetAltConfig (
4784 &DefaultId
, // it can be NULL to get the current setting.
4789 if (EFI_ERROR (Status
)) {
4793 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4798 Clean AltCfg string for current formset.
4800 @param FormSet Form data structure.
4804 CleanAltCfgForFormSet (
4805 IN FORM_BROWSER_FORMSET
*FormSet
4809 FORMSET_STORAGE
*FormSetStorage
;
4811 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4812 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4813 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4814 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4816 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4817 FreePool (FormSetStorage
->ConfigAltResp
);
4818 FormSetStorage
->ConfigAltResp
= NULL
;
4821 FormSetStorage
->HasCallAltCfg
= FALSE
;
4826 Reset Questions to their initial value or default value in a Form, Formset or System.
4828 GetDefaultValueScope parameter decides which questions will reset
4829 to its default value.
4831 @param FormSet FormSet data structure.
4832 @param Form Form data structure.
4833 @param DefaultId The Class of the default.
4834 @param SettingScope Setting Scope for Default action.
4835 @param GetDefaultValueScope Get default value scope.
4836 @param Storage Get default value only for this storage.
4837 @param RetrieveValueFirst Whether call the retrieve call back to
4838 get the initial value before get default
4840 @param SkipGetAltCfg Whether skip the get altcfg string process.
4842 @retval EFI_SUCCESS The function completed successfully.
4843 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4848 IN FORM_BROWSER_FORMSET
*FormSet
,
4849 IN FORM_BROWSER_FORM
*Form
,
4850 IN UINT16 DefaultId
,
4851 IN BROWSER_SETTING_SCOPE SettingScope
,
4852 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4853 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4854 IN BOOLEAN RetrieveValueFirst
,
4855 IN BOOLEAN SkipGetAltCfg
4859 LIST_ENTRY
*FormLink
;
4861 FORM_BROWSER_STATEMENT
*Question
;
4862 FORM_BROWSER_FORMSET
*LocalFormSet
;
4863 FORM_BROWSER_FORMSET
*OldFormSet
;
4865 Status
= EFI_SUCCESS
;
4868 // Check the supported setting level.
4870 if ((SettingScope
>= MaxLevel
) || (GetDefaultValueScope
>= GetDefaultForMax
)) {
4871 return EFI_UNSUPPORTED
;
4874 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Storage
== NULL
)) {
4875 return EFI_UNSUPPORTED
;
4878 if (SettingScope
== FormLevel
) {
4880 // Prepare the AltCfg String for form.
4882 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4883 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4887 // Extract Form default
4889 Link
= GetFirstNode (&Form
->StatementListHead
);
4890 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4891 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4892 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4895 // If get default value only for this storage, check the storage first.
4897 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4902 // If get default value only for no storage question, just skip the question which has storage.
4904 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4909 // If Question is disabled, don't reset it to default
4911 if (Question
->Expression
!= NULL
) {
4912 if (EvaluateExpressionList (Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4917 if (RetrieveValueFirst
) {
4919 // Call the Retrieve call back to get the initial question value.
4921 Status
= ProcessRetrieveForQuestion (FormSet
->ConfigAccess
, Question
, FormSet
);
4925 // If not request to get the initial value or get initial value fail, then get default value.
4927 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4928 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4929 if (EFI_ERROR (Status
)) {
4935 // Synchronize Buffer storage's Edit buffer
4937 if ((Question
->Storage
!= NULL
) &&
4938 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
))
4940 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4945 // Clean the AltCfg String.
4947 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4948 CleanAltCfgForForm (Form
);
4950 } else if (SettingScope
== FormSetLevel
) {
4952 // Prepare the AltCfg String for formset.
4954 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4955 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4958 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4959 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4960 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4961 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4962 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4966 // Clean the AltCfg String.
4968 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4969 CleanAltCfgForFormSet (FormSet
);
4971 } else if (SettingScope
== SystemLevel
) {
4973 // Preload all Hii formset.
4975 LoadAllHiiFormset ();
4977 OldFormSet
= mSystemLevelFormSet
;
4980 // Set Default Value for each FormSet in the maintain list.
4982 Link
= GetFirstNode (&gBrowserFormSetList
);
4983 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4984 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4985 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4986 if (!ValidateFormSet (LocalFormSet
)) {
4990 mSystemLevelFormSet
= LocalFormSet
;
4992 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4995 mSystemLevelFormSet
= OldFormSet
;
5002 Validate whether this question's value has changed.
5004 @param FormSet FormSet data structure.
5005 @param Form Form data structure.
5006 @param Question Question to be initialized.
5007 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
5009 @retval TRUE Question's value has changed.
5010 @retval FALSE Question's value has not changed
5014 IsQuestionValueChanged (
5015 IN FORM_BROWSER_FORMSET
*FormSet
,
5016 IN FORM_BROWSER_FORM
*Form
,
5017 IN OUT FORM_BROWSER_STATEMENT
*Question
,
5018 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
5021 EFI_HII_VALUE BackUpValue
;
5022 CHAR8
*BackUpBuffer
;
5023 EFI_HII_VALUE BackUpValue2
;
5024 CHAR8
*BackUpBuffer2
;
5026 BOOLEAN ValueChanged
;
5030 // For quetion without storage, always mark it as data not changed.
5032 if ((Question
->Storage
== NULL
) && (Question
->Operand
!= EFI_IFR_TIME_OP
) && (Question
->Operand
!= EFI_IFR_DATE_OP
)) {
5036 BackUpBuffer
= NULL
;
5037 BackUpBuffer2
= NULL
;
5038 ValueChanged
= FALSE
;
5040 switch (Question
->Operand
) {
5041 case EFI_IFR_ORDERED_LIST_OP
:
5042 BufferWidth
= Question
->StorageWidth
;
5043 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5044 ASSERT (BackUpBuffer
!= NULL
);
5047 case EFI_IFR_STRING_OP
:
5048 case EFI_IFR_PASSWORD_OP
:
5049 BufferWidth
= (UINTN
)Question
->Maximum
* sizeof (CHAR16
);
5050 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5051 ASSERT (BackUpBuffer
!= NULL
);
5059 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5061 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5062 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5063 ASSERT_EFI_ERROR (Status
);
5065 switch (Question
->Operand
) {
5066 case EFI_IFR_ORDERED_LIST_OP
:
5067 BufferWidth
= Question
->StorageWidth
;
5068 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5069 ASSERT (BackUpBuffer2
!= NULL
);
5072 case EFI_IFR_STRING_OP
:
5073 case EFI_IFR_PASSWORD_OP
:
5074 BufferWidth
= (UINTN
)Question
->Maximum
* sizeof (CHAR16
);
5075 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5076 ASSERT (BackUpBuffer2
!= NULL
);
5084 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5086 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5087 ASSERT_EFI_ERROR (Status
);
5089 if ((CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0) ||
5090 (CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0))
5092 ValueChanged
= TRUE
;
5095 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5096 ASSERT_EFI_ERROR (Status
);
5098 if ((CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0) ||
5099 (CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0))
5101 ValueChanged
= TRUE
;
5105 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5106 if (BackUpBuffer
!= NULL
) {
5107 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5108 FreePool (BackUpBuffer
);
5111 if (BackUpBuffer2
!= NULL
) {
5112 FreePool (BackUpBuffer2
);
5115 Question
->ValueChanged
= ValueChanged
;
5117 return ValueChanged
;
5121 Initialize Question's Edit copy from Storage.
5123 @param Selection Selection contains the information about
5124 the Selection, form and formset to be displayed.
5125 Selection action may be updated in retrieve callback.
5126 If Selection is NULL, only initialize Question value.
5127 @param FormSet FormSet data structure.
5128 @param Form Form data structure.
5130 @retval EFI_SUCCESS The function completed successfully.
5135 IN OUT UI_MENU_SELECTION
*Selection
,
5136 IN FORM_BROWSER_FORMSET
*FormSet
,
5137 IN FORM_BROWSER_FORM
*Form
5142 FORM_BROWSER_STATEMENT
*Question
;
5144 Link
= GetFirstNode (&Form
->StatementListHead
);
5145 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5146 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5149 // Initialize local copy of Value for each Question
5151 if ((Question
->Operand
== EFI_IFR_PASSWORD_OP
) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == 0)) {
5152 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5154 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5157 if (EFI_ERROR (Status
)) {
5161 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5162 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5165 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5172 Initialize Question's Edit copy from Storage for the whole Formset.
5174 @param Selection Selection contains the information about
5175 the Selection, form and formset to be displayed.
5176 Selection action may be updated in retrieve callback.
5177 If Selection is NULL, only initialize Question value.
5178 @param FormSet FormSet data structure.
5180 @retval EFI_SUCCESS The function completed successfully.
5185 IN OUT UI_MENU_SELECTION
*Selection
,
5186 IN FORM_BROWSER_FORMSET
*FormSet
5191 FORM_BROWSER_FORM
*Form
;
5193 Link
= GetFirstNode (&FormSet
->FormListHead
);
5194 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5195 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5198 // Initialize local copy of Value for each Form
5200 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5201 if (EFI_ERROR (Status
)) {
5205 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5209 // Finished question initialization.
5211 FormSet
->QuestionInited
= TRUE
;
5217 Remove the Request element from the Config Request.
5219 @param Storage Pointer to the browser storage.
5220 @param RequestElement The pointer to the Request element.
5225 IN OUT BROWSER_STORAGE
*Storage
,
5226 IN CHAR16
*RequestElement
5232 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5234 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5236 if (NewStr
== NULL
) {
5241 // Remove this element from this ConfigRequest.
5244 NewStr
+= StrLen (RequestElement
);
5245 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5247 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5251 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5253 @param Storage Pointer to the formset storage.
5254 @param ConfigRequest The pointer to the Request element.
5258 RemoveConfigRequest (
5259 FORMSET_STORAGE
*Storage
,
5260 CHAR16
*ConfigRequest
5263 CHAR16
*RequestElement
;
5264 CHAR16
*NextRequestElement
;
5268 // No request element in it, just return.
5270 if (ConfigRequest
== NULL
) {
5274 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5276 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5281 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5283 SearchKey
= L
"&OFFSET";
5287 // Find SearchKey storage
5289 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5290 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5291 ASSERT (RequestElement
!= NULL
);
5292 RequestElement
= StrStr (RequestElement
, SearchKey
);
5294 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5297 while (RequestElement
!= NULL
) {
5299 // +1 to avoid find header itself.
5301 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5304 // The last Request element in configRequest string.
5306 if (NextRequestElement
!= NULL
) {
5308 // Replace "&" with '\0'.
5310 *NextRequestElement
= L
'\0';
5313 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5315 if (NextRequestElement
!= NULL
) {
5317 // Restore '&' with '\0' for later used.
5319 *NextRequestElement
= L
'&';
5322 RequestElement
= NextRequestElement
;
5326 // If no request element remain, just remove the ConfigRequest string.
5328 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5329 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5330 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5331 Storage
->BrowserStorage
->SpareStrLen
= 0;
5336 Base on the current formset info, clean the ConfigRequest string in browser storage.
5338 @param FormSet Pointer of the FormSet
5342 CleanBrowserStorage (
5343 IN OUT FORM_BROWSER_FORMSET
*FormSet
5347 FORMSET_STORAGE
*Storage
;
5349 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5350 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5351 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5352 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5354 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5355 if ((Storage
->ConfigRequest
== NULL
) || (Storage
->BrowserStorage
->ConfigRequest
== NULL
)) {
5359 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5360 } else if ((Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
) ||
5361 (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
))
5363 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5364 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5365 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5368 Storage
->BrowserStorage
->Initialized
= FALSE
;
5374 Check whether current element in the ConfigReqeust string.
5376 @param BrowserStorage Storage which includes ConfigReqeust.
5377 @param RequestElement New element need to check.
5379 @retval TRUE The Element is in the ConfigReqeust string.
5380 @retval FALSE The Element not in the configReqeust String.
5385 BROWSER_STORAGE
*BrowserStorage
,
5386 CHAR16
*RequestElement
5389 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5393 Append the Request element to the Config Request.
5395 @param ConfigRequest Current ConfigRequest info.
5396 @param SpareStrLen Current remain free buffer for config reqeust.
5397 @param RequestElement New Request element.
5401 AppendConfigRequest (
5402 IN OUT CHAR16
**ConfigRequest
,
5403 IN OUT UINTN
*SpareStrLen
,
5404 IN CHAR16
*RequestElement
5412 StrLength
= StrLen (RequestElement
);
5413 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5414 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5417 // Append <RequestElement> to <ConfigRequest>
5419 if (StrLength
> *SpareStrLen
) {
5421 // Old String buffer is not sufficient for RequestElement, allocate a new one
5423 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5424 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5425 ASSERT (NewStr
!= NULL
);
5427 if (*ConfigRequest
!= NULL
) {
5428 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5429 FreePool (*ConfigRequest
);
5432 *ConfigRequest
= NewStr
;
5433 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5436 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5437 *SpareStrLen
-= StrLength
;
5441 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5443 @param Storage Form set Storage.
5444 @param Request The input request string.
5445 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5447 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5448 @retval FALSE All elements covered by current used elements.
5452 ConfigRequestAdjust (
5453 IN BROWSER_STORAGE
*Storage
,
5455 IN BOOLEAN RespString
5458 CHAR16
*RequestElement
;
5459 CHAR16
*NextRequestElement
;
5460 CHAR16
*NextElementBakup
;
5464 CHAR16
*ConfigRequest
;
5467 NextElementBakup
= NULL
;
5470 if (Request
!= NULL
) {
5471 ConfigRequest
= Request
;
5473 ConfigRequest
= Storage
->ConfigRequest
;
5476 if (Storage
->ConfigRequest
== NULL
) {
5477 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5481 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5483 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5488 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5490 SearchKey
= L
"&OFFSET";
5491 ValueKey
= L
"&VALUE";
5495 // Find SearchKey storage
5497 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5498 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5499 ASSERT (RequestElement
!= NULL
);
5500 RequestElement
= StrStr (RequestElement
, SearchKey
);
5502 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5505 while (RequestElement
!= NULL
) {
5507 // +1 to avoid find header itself.
5509 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5512 // The last Request element in configRequest string.
5514 if (NextRequestElement
!= NULL
) {
5515 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5516 NextElementBakup
= NextRequestElement
;
5517 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5518 ASSERT (NextRequestElement
!= NULL
);
5522 // Replace "&" with '\0'.
5524 *NextRequestElement
= L
'\0';
5526 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5527 NextElementBakup
= NextRequestElement
;
5528 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5529 ASSERT (NextRequestElement
!= NULL
);
5531 // Replace "&" with '\0'.
5533 *NextRequestElement
= L
'\0';
5537 if (!ElementValidation (Storage
, RequestElement
)) {
5539 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5541 AppendConfigRequest (&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5545 if (NextRequestElement
!= NULL
) {
5547 // Restore '&' with '\0' for later used.
5549 *NextRequestElement
= L
'&';
5552 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5553 RequestElement
= NextElementBakup
;
5555 RequestElement
= NextRequestElement
;
5563 Fill storage's edit copy with settings requested from Configuration Driver.
5565 @param FormSet FormSet data structure.
5566 @param Storage Buffer Storage.
5571 IN FORM_BROWSER_FORMSET
*FormSet
,
5572 IN FORMSET_STORAGE
*Storage
5576 EFI_STRING Progress
;
5579 EFI_STRING ConfigRequest
;
5582 ConfigRequest
= NULL
;
5584 switch (Storage
->BrowserStorage
->Type
) {
5585 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5588 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5589 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5590 ConfigRequestAdjust (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5596 case EFI_HII_VARSTORE_BUFFER
:
5597 case EFI_HII_VARSTORE_NAME_VALUE
:
5599 // Skip if there is no RequestElement.
5601 if (Storage
->ElementCount
== 0) {
5606 // Just update the ConfigRequest, if storage already initialized.
5608 if (Storage
->BrowserStorage
->Initialized
) {
5609 ConfigRequestAdjust (Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5613 Storage
->BrowserStorage
->Initialized
= TRUE
;
5620 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5622 // Create the config request string to get all fields for this storage.
5623 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5624 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5626 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5627 ConfigRequest
= AllocateZeroPool (StrLen
);
5628 ASSERT (ConfigRequest
!= NULL
);
5632 L
"%s&OFFSET=0&WIDTH=%04x",
5634 Storage
->BrowserStorage
->Size
5637 ConfigRequest
= Storage
->ConfigRequest
;
5641 // Request current settings from Configuration Driver
5643 Status
= mHiiConfigRouting
->ExtractConfig (
5651 // If get value fail, extract default from IFR binary
5653 if (EFI_ERROR (Status
)) {
5654 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5657 // Convert Result from <ConfigAltResp> to <ConfigResp>
5659 StrPtr
= StrStr (Result
, L
"&GUID=");
5660 if (StrPtr
!= NULL
) {
5664 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5668 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5671 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5673 SynchronizeStorage (Storage
->BrowserStorage
, NULL
, TRUE
);
5675 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5676 if (ConfigRequest
!= NULL
) {
5677 FreePool (ConfigRequest
);
5683 Get Value changed status from old question.
5685 @param NewFormSet FormSet data structure.
5686 @param OldQuestion Old question which has value changed.
5690 SyncStatusForQuestion (
5691 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5692 IN FORM_BROWSER_STATEMENT
*OldQuestion
5696 LIST_ENTRY
*QuestionLink
;
5697 FORM_BROWSER_FORM
*Form
;
5698 FORM_BROWSER_STATEMENT
*Question
;
5701 // For each form in one formset.
5703 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5704 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5705 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5706 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5709 // for each question in one form.
5711 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5712 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5713 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5714 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5716 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5717 Question
->ValueChanged
= TRUE
;
5725 Get Value changed status from old formset.
5727 @param NewFormSet FormSet data structure.
5728 @param OldFormSet FormSet data structure.
5732 SyncStatusForFormSet (
5733 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5734 IN FORM_BROWSER_FORMSET
*OldFormSet
5738 LIST_ENTRY
*QuestionLink
;
5739 FORM_BROWSER_FORM
*Form
;
5740 FORM_BROWSER_STATEMENT
*Question
;
5743 // For each form in one formset.
5745 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5746 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5747 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5748 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5751 // for each question in one form.
5753 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5754 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5755 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5756 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5758 if (!Question
->ValueChanged
) {
5763 // Find the same question in new formset and update the value changed flag.
5765 SyncStatusForQuestion (NewFormSet
, Question
);
5771 Get current setting of Questions.
5773 @param FormSet FormSet data structure.
5777 InitializeCurrentSetting (
5778 IN OUT FORM_BROWSER_FORMSET
*FormSet
5782 FORMSET_STORAGE
*Storage
;
5783 FORM_BROWSER_FORMSET
*OldFormSet
;
5786 // Try to find pre FormSet in the maintain backup list.
5787 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5789 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5790 if (OldFormSet
!= NULL
) {
5791 SyncStatusForFormSet (FormSet
, OldFormSet
);
5792 RemoveEntryList (&OldFormSet
->Link
);
5793 DestroyFormSet (OldFormSet
);
5796 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5799 // Extract default from IFR binary for no storage questions.
5801 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5804 // Request current settings from Configuration Driver
5806 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5807 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5808 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5810 LoadStorage (FormSet
, Storage
);
5812 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5817 Fetch the Ifr binary data of a FormSet.
5819 @param Handle PackageList Handle
5820 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5821 specified (NULL or zero GUID), take the first
5822 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5823 found in package list.
5824 On output, GUID of the formset found(if not NULL).
5825 @param BinaryLength The length of the FormSet IFR binary.
5826 @param BinaryData The buffer designed to receive the FormSet.
5828 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5829 BufferLength was updated.
5830 @retval EFI_INVALID_PARAMETER The handle is unknown.
5831 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5832 be found with the requested FormId.
5837 IN EFI_HII_HANDLE Handle
,
5838 IN OUT EFI_GUID
*FormSetGuid
,
5839 OUT UINTN
*BinaryLength
,
5840 OUT UINT8
**BinaryData
5844 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5850 UINT32 PackageListLength
;
5851 EFI_HII_PACKAGE_HEADER PackageHeader
;
5853 UINT8 NumberOfClassGuid
;
5854 BOOLEAN ClassGuidMatch
;
5855 EFI_GUID
*ClassGuid
;
5856 EFI_GUID
*ComparingGuid
;
5860 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5863 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5865 if (FormSetGuid
== NULL
) {
5866 ComparingGuid
= &gZeroGuid
;
5868 ComparingGuid
= FormSetGuid
;
5872 // Get HII PackageList
5875 HiiPackageList
= NULL
;
5876 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5877 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5878 HiiPackageList
= AllocatePool (BufferSize
);
5879 ASSERT (HiiPackageList
!= NULL
);
5881 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5884 if (EFI_ERROR (Status
)) {
5888 ASSERT (HiiPackageList
!= NULL
);
5891 // Get Form package from this HII package List
5893 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5895 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5897 ClassGuidMatch
= FALSE
;
5898 while (Offset
< PackageListLength
) {
5899 Package
= ((UINT8
*)HiiPackageList
) + Offset
;
5900 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5902 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5904 // Search FormSet in this Form Package
5906 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5907 while (Offset2
< PackageHeader
.Length
) {
5908 OpCodeData
= Package
+ Offset2
;
5910 if (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5912 // Try to compare against formset GUID
5914 if (IsZeroGuid (ComparingGuid
) ||
5915 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
))))
5920 if (((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5922 // Try to compare against formset class GUID
5924 NumberOfClassGuid
= (UINT8
)(((EFI_IFR_FORM_SET
*)OpCodeData
)->Flags
& 0x3);
5925 ClassGuid
= (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5926 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5927 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5928 ClassGuidMatch
= TRUE
;
5933 if (ClassGuidMatch
) {
5936 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5937 ClassGuidMatch
= TRUE
;
5942 Offset2
+= ((EFI_IFR_OP_HEADER
*)OpCodeData
)->Length
;
5945 if (Offset2
< PackageHeader
.Length
) {
5947 // Target formset found
5953 Offset
+= PackageHeader
.Length
;
5956 if (Offset
>= PackageListLength
) {
5958 // Form package not found in this Package List
5960 FreePool (HiiPackageList
);
5961 return EFI_NOT_FOUND
;
5964 if (FormSetGuid
!= NULL
) {
5966 // Return the FormSet GUID
5968 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*)OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5972 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5973 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5974 // of the Form Package.
5976 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5977 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5979 FreePool (HiiPackageList
);
5981 if (*BinaryData
== NULL
) {
5982 return EFI_OUT_OF_RESOURCES
;
5989 Initialize the internal data structure of a FormSet.
5991 @param Handle PackageList Handle
5992 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5993 specified (NULL or zero GUID), take the first
5994 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5995 found in package list.
5996 On output, GUID of the formset found(if not NULL).
5997 @param FormSet FormSet data structure.
5999 @retval EFI_SUCCESS The function completed successfully.
6000 @retval EFI_NOT_FOUND The specified FormSet could not be found.
6005 IN EFI_HII_HANDLE Handle
,
6006 IN OUT EFI_GUID
*FormSetGuid
,
6007 OUT FORM_BROWSER_FORMSET
*FormSet
6011 EFI_HANDLE DriverHandle
;
6013 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
6014 if (EFI_ERROR (Status
)) {
6018 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
6019 FormSet
->HiiHandle
= Handle
;
6020 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
6021 FormSet
->QuestionInited
= FALSE
;
6024 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
6026 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
6027 if (EFI_ERROR (Status
)) {
6031 FormSet
->DriverHandle
= DriverHandle
;
6032 Status
= gBS
->HandleProtocol (
6034 &gEfiHiiConfigAccessProtocolGuid
,
6035 (VOID
**)&FormSet
->ConfigAccess
6037 if (EFI_ERROR (Status
)) {
6039 // Configuration Driver don't attach ConfigAccess protocol to its HII package
6040 // list, then there will be no configuration action required
6042 FormSet
->ConfigAccess
= NULL
;
6046 // Parse the IFR binary OpCodes
6048 Status
= ParseOpCodes (FormSet
);
6054 Save globals used by previous call to SendForm(). SendForm() may be called from
6055 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
6056 So, save globals of previous call to SendForm() and restore them upon exit.
6060 SaveBrowserContext (
6064 BROWSER_CONTEXT
*Context
;
6065 FORM_ENTRY_INFO
*MenuList
;
6066 FORM_BROWSER_FORMSET
*FormSet
;
6068 gBrowserContextCount
++;
6069 if (gBrowserContextCount
== 1) {
6071 // This is not reentry of SendForm(), no context to save
6076 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6077 ASSERT (Context
!= NULL
);
6079 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6082 // Save FormBrowser context
6084 Context
->Selection
= gCurrentSelection
;
6085 Context
->ResetRequired
= gResetRequiredFormLevel
;
6086 Context
->FlagReconnect
= gFlagReconnect
;
6087 Context
->CallbackReconnect
= gCallbackReconnect
;
6088 Context
->ExitRequired
= gExitRequired
;
6089 Context
->HiiHandle
= mCurrentHiiHandle
;
6090 Context
->FormId
= mCurrentFormId
;
6091 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6092 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6093 Context
->CurFakeQestId
= mCurFakeQestId
;
6094 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6095 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6098 // Save the menu history data.
6100 InitializeListHead (&Context
->FormHistoryList
);
6101 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6102 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6103 RemoveEntryList (&MenuList
->Link
);
6105 InsertTailList (&Context
->FormHistoryList
, &MenuList
->Link
);
6109 // Save formset list.
6111 InitializeListHead (&Context
->FormSetList
);
6112 while (!IsListEmpty (&gBrowserFormSetList
)) {
6113 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6114 RemoveEntryList (&FormSet
->Link
);
6116 InsertTailList (&Context
->FormSetList
, &FormSet
->Link
);
6120 // Insert to FormBrowser context list
6122 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6126 Restore globals used by previous call to SendForm().
6130 RestoreBrowserContext (
6135 BROWSER_CONTEXT
*Context
;
6136 FORM_ENTRY_INFO
*MenuList
;
6137 FORM_BROWSER_FORMSET
*FormSet
;
6139 ASSERT (gBrowserContextCount
!= 0);
6140 gBrowserContextCount
--;
6141 if (gBrowserContextCount
== 0) {
6143 // This is not reentry of SendForm(), no context to restore
6148 ASSERT (!IsListEmpty (&gBrowserContextList
));
6150 Link
= GetFirstNode (&gBrowserContextList
);
6151 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6154 // Restore FormBrowser context
6156 gCurrentSelection
= Context
->Selection
;
6157 gResetRequiredFormLevel
= Context
->ResetRequired
;
6158 gFlagReconnect
= Context
->FlagReconnect
;
6159 gCallbackReconnect
= Context
->CallbackReconnect
;
6160 gExitRequired
= Context
->ExitRequired
;
6161 mCurrentHiiHandle
= Context
->HiiHandle
;
6162 mCurrentFormId
= Context
->FormId
;
6163 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6164 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6165 mCurFakeQestId
= Context
->CurFakeQestId
;
6166 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6167 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6170 // Restore the menu history data.
6172 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6173 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6174 RemoveEntryList (&MenuList
->Link
);
6176 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6180 // Restore the Formset data.
6182 while (!IsListEmpty (&Context
->FormSetList
)) {
6183 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6184 RemoveEntryList (&FormSet
->Link
);
6186 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
6190 // Remove from FormBrowser context list
6192 RemoveEntryList (&Context
->Link
);
6193 gBS
->FreePool (Context
);
6197 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6199 @param Handle The Hii Handle.
6201 @return the found FormSet context. If no found, NULL will return.
6204 FORM_BROWSER_FORMSET
*
6205 GetFormSetFromHiiHandle (
6206 EFI_HII_HANDLE Handle
6210 FORM_BROWSER_FORMSET
*FormSet
;
6212 Link
= GetFirstNode (&gBrowserFormSetList
);
6213 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6214 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6215 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6216 if (!ValidateFormSet (FormSet
)) {
6220 if (FormSet
->HiiHandle
== Handle
) {
6229 Check whether the input HII handle is the FormSet that is being used.
6231 @param Handle The Hii Handle.
6233 @retval TRUE HII handle is being used.
6234 @retval FALSE HII handle is not being used.
6238 IsHiiHandleInBrowserContext (
6239 EFI_HII_HANDLE Handle
6243 BROWSER_CONTEXT
*Context
;
6246 // HiiHandle is Current FormSet.
6248 if (mCurrentHiiHandle
== Handle
) {
6253 // Check whether HiiHandle is in BrowserContext.
6255 Link
= GetFirstNode (&gBrowserContextList
);
6256 while (!IsNull (&gBrowserContextList
, Link
)) {
6257 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6258 if (Context
->HiiHandle
== Handle
) {
6260 // HiiHandle is in BrowserContext
6265 Link
= GetNextNode (&gBrowserContextList
, Link
);
6272 Perform Password check.
6273 Passwork may be encrypted by driver that requires the specific check.
6275 @param Form Form where Password Statement is in.
6276 @param Statement Password statement
6277 @param PasswordString Password string to be checked. It may be NULL.
6278 NULL means to restore password.
6279 "" string can be used to checked whether old password does exist.
6281 @return Status Status of Password check.
6286 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6287 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6288 IN EFI_STRING PasswordString OPTIONAL
6292 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6293 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6294 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6295 FORM_BROWSER_STATEMENT
*Question
;
6297 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6298 Question
= GetBrowserStatement (Statement
);
6299 ASSERT (Question
!= NULL
);
6301 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6302 if (ConfigAccess
== NULL
) {
6303 return EFI_UNSUPPORTED
;
6307 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6309 return EFI_UNSUPPORTED
;
6313 // Prepare password string in HII database
6315 if (PasswordString
!= NULL
) {
6316 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6318 IfrTypeValue
.string
= 0;
6322 // Send password to Configuration Driver for validation
6324 Status
= ConfigAccess
->Callback (
6326 EFI_BROWSER_ACTION_CHANGING
,
6327 Question
->QuestionId
,
6328 Question
->HiiValue
.Type
,
6334 // Remove password string from HII database
6336 if (PasswordString
!= NULL
) {
6337 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6344 Find the registered HotKey based on KeyData.
6346 @param[in] KeyData A pointer to a buffer that describes the keystroke
6347 information for the hot key.
6349 @return The registered HotKey context. If no found, NULL will return.
6352 GetHotKeyFromRegisterList (
6353 IN EFI_INPUT_KEY
*KeyData
6357 BROWSER_HOT_KEY
*HotKey
;
6359 Link
= GetFirstNode (&gBrowserHotKeyList
);
6360 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6361 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6362 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6366 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6373 Configure what scope the hot key will impact.
6374 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6375 If no scope is set, the default scope will be FormSet level.
6376 After all registered hot keys are removed, previous Scope can reset to another level.
6378 @param[in] Scope Scope level to be set.
6380 @retval EFI_SUCCESS Scope is set correctly.
6381 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6382 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6388 IN BROWSER_SETTING_SCOPE Scope
6391 if (Scope
>= MaxLevel
) {
6392 return EFI_INVALID_PARAMETER
;
6396 // When no hot key registered in system or on the first setting,
6397 // Scope can be set.
6399 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6400 gBrowserSettingScope
= Scope
;
6401 mBrowserScopeFirstSet
= FALSE
;
6402 } else if (Scope
!= gBrowserSettingScope
) {
6403 return EFI_UNSUPPORTED
;
6410 Register the hot key with its browser action, or unregistered the hot key.
6411 Only support hot key that is not printable character (control key, function key, etc.).
6412 If the action value is zero, the hot key will be unregistered if it has been registered.
6413 If the same hot key has been registered, the new action and help string will override the previous ones.
6415 @param[in] KeyData A pointer to a buffer that describes the keystroke
6416 information for the hot key. Its type is EFI_INPUT_KEY to
6417 be supported by all ConsoleIn devices.
6418 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6419 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6420 @param[in] HelpString Help string that describes the hot key information.
6421 Its value may be NULL for the unregistered hot key.
6423 @retval EFI_SUCCESS Hot key is registered or unregistered.
6424 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6425 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6426 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6427 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6432 IN EFI_INPUT_KEY
*KeyData
,
6434 IN UINT16 DefaultId
,
6435 IN EFI_STRING HelpString OPTIONAL
6438 BROWSER_HOT_KEY
*HotKey
;
6441 // Check input parameters.
6443 if ((KeyData
== NULL
) || (KeyData
->UnicodeChar
!= CHAR_NULL
) ||
6444 ((Action
!= BROWSER_ACTION_UNREGISTER
) && (HelpString
== NULL
)))
6446 return EFI_INVALID_PARAMETER
;
6450 // Check whether the input KeyData is in BrowserHotKeyList.
6452 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6455 // Unregister HotKey
6457 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6458 if (HotKey
!= NULL
) {
6460 // The registered HotKey is found.
6461 // Remove it from List, and free its resource.
6463 RemoveEntryList (&HotKey
->Link
);
6464 FreePool (HotKey
->KeyData
);
6465 FreePool (HotKey
->HelpString
);
6469 // The registered HotKey is not found.
6471 return EFI_NOT_FOUND
;
6475 if (HotKey
!= NULL
) {
6476 return EFI_ALREADY_STARTED
;
6480 // Create new Key, and add it into List.
6482 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6483 ASSERT (HotKey
!= NULL
);
6484 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6485 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6486 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6489 // Fill HotKey information.
6491 HotKey
->Action
= Action
;
6492 HotKey
->DefaultId
= DefaultId
;
6493 if (HotKey
->HelpString
!= NULL
) {
6494 FreePool (HotKey
->HelpString
);
6497 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6503 Register Exit handler function.
6504 When more than one handler function is registered, the latter one will override the previous one.
6505 When NULL handler is specified, the previous Exit handler will be unregistered.
6507 @param[in] Handler Pointer to handler function.
6512 RegiserExitHandler (
6513 IN EXIT_HANDLER Handler
6516 ExitHandlerFunction
= Handler
;
6521 Check whether the browser data has been modified.
6523 @retval TRUE Browser data is modified.
6524 @retval FALSE No browser data is modified.
6529 IsBrowserDataModified (
6534 FORM_BROWSER_FORMSET
*FormSet
;
6536 switch (gBrowserSettingScope
) {
6538 if (gCurrentSelection
== NULL
) {
6542 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6545 if (gCurrentSelection
== NULL
) {
6549 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6552 Link
= GetFirstNode (&gBrowserFormSetList
);
6553 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6554 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6555 if (!ValidateFormSet (FormSet
)) {
6559 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6563 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6574 Execute the action requested by the Action parameter.
6576 @param[in] Action Execute the request action.
6577 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6579 @retval EFI_SUCCESS Execute the request action succss.
6580 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6591 FORM_BROWSER_FORMSET
*FormSet
;
6592 FORM_BROWSER_FORM
*Form
;
6594 if ((gBrowserSettingScope
< SystemLevel
) && (gCurrentSelection
== NULL
)) {
6595 return EFI_NOT_READY
;
6598 Status
= EFI_SUCCESS
;
6601 if (gBrowserSettingScope
< SystemLevel
) {
6602 FormSet
= gCurrentSelection
->FormSet
;
6603 Form
= gCurrentSelection
->Form
;
6607 // Executet the discard action.
6609 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6610 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6611 if (EFI_ERROR (Status
)) {
6617 // Executet the difault action.
6619 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6620 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6621 if (EFI_ERROR (Status
)) {
6625 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6629 // Executet the submit action.
6631 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6632 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6633 if (EFI_ERROR (Status
)) {
6639 // Executet the reset action.
6641 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6642 gResetRequiredFormLevel
= TRUE
;
6643 gResetRequiredSystemLevel
= TRUE
;
6647 // Executet the exit action.
6649 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6650 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6651 if (gBrowserSettingScope
== SystemLevel
) {
6652 if (ExitHandlerFunction
!= NULL
) {
6653 ExitHandlerFunction ();
6657 gExitRequired
= TRUE
;
6664 Create reminder to let user to choose save or discard the changed browser data.
6665 Caller can use it to actively check the changed browser data.
6667 @retval BROWSER_NO_CHANGES No browser data is changed.
6668 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6669 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6670 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6680 FORM_BROWSER_FORMSET
*FormSet
;
6681 BOOLEAN IsDataChanged
;
6682 UINT32 DataSavedAction
;
6685 DataSavedAction
= BROWSER_NO_CHANGES
;
6686 IsDataChanged
= FALSE
;
6687 Link
= GetFirstNode (&gBrowserFormSetList
);
6688 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6689 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6690 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6691 if (!ValidateFormSet (FormSet
)) {
6695 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6696 IsDataChanged
= TRUE
;
6702 // No data is changed. No save is required.
6704 if (!IsDataChanged
) {
6705 return DataSavedAction
;
6709 // If data is changed, prompt user to save or discard it.
6712 ConfirmRet
= (UINT32
)mFormDisplay
->ConfirmDataChange ();
6714 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6715 SubmitForm (NULL
, NULL
, SystemLevel
);
6716 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6718 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6719 DiscardForm (NULL
, NULL
, SystemLevel
);
6720 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6722 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6723 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6728 return DataSavedAction
;
6732 Check whether the Reset Required for the browser
6734 @retval TRUE Browser required to reset after exit.
6735 @retval FALSE Browser not need to reset after exit.
6744 return gResetRequiredSystemLevel
;