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
);
369 InitializeCurrentSetting (LocalFormSet
);
372 // Initilize Questions' Value
374 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
375 if (EFI_ERROR (Status
)) {
376 DestroyFormSet (LocalFormSet
);
382 // Free resources, and restore gOldFormSet and gClassOfVfr
384 FreePool (HiiHandles
);
386 mSystemLevelFormSet
= OldFormset
;
390 Pop up the error info.
392 @param BrowserStatus The input browser status.
393 @param HiiHandle The Hiihandle for this opcode.
394 @param OpCode The opcode use to get the erro info and timeout value.
395 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
400 IN UINT32 BrowserStatus
,
401 IN EFI_HII_HANDLE HiiHandle
,
402 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
403 IN CHAR16
*ErrorString
406 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
407 USER_INPUT UserInputData
;
411 if (OpCode
!= NULL
) {
412 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
413 ASSERT (Statement
!= NULL
);
414 Statement
->OpCode
= OpCode
;
415 gDisplayFormData
.HighLightedStatement
= Statement
;
419 // Used to compatible with old display engine.
420 // New display engine not use this field.
422 gDisplayFormData
.ErrorString
= ErrorString
;
423 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
425 if (HiiHandle
!= NULL
) {
426 gDisplayFormData
.HiiHandle
= HiiHandle
;
429 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
431 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
432 gDisplayFormData
.ErrorString
= NULL
;
434 if (OpCode
!= NULL
) {
435 FreePool (Statement
);
438 return UserInputData
.Action
;
442 This is the routine which an external caller uses to direct the browser
443 where to obtain it's information.
446 @param This The Form Browser protocol instanse.
447 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
448 display a list of the formsets for the handles specified.
449 @param HandleCount The number of Handles specified in Handle.
450 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
451 field in the EFI_IFR_FORM_SET op-code for the specified
452 forms-based package. If FormSetGuid is NULL, then this
453 function will display the first found forms package.
454 @param FormId This field specifies which EFI_IFR_FORM to render as the first
455 displayable page. If this field has a value of 0x0000, then
456 the forms browser will render the specified forms in their encoded order.
457 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
459 @param ActionRequest Points to the action recommended by the form.
461 @retval EFI_SUCCESS The function completed successfully.
462 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
463 @retval EFI_NOT_FOUND No valid forms could be found to display.
469 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
470 IN EFI_HII_HANDLE
*Handles
,
471 IN UINTN HandleCount
,
472 IN EFI_GUID
*FormSetGuid
, OPTIONAL
473 IN UINT16 FormId
, OPTIONAL
474 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
475 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
479 UI_MENU_SELECTION
*Selection
;
481 FORM_BROWSER_FORMSET
*FormSet
;
482 FORM_ENTRY_INFO
*MenuList
;
486 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
488 if (mFormDisplay
== NULL
) {
489 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
490 return EFI_UNSUPPORTED
;
494 // Save globals used by SendForm()
496 SaveBrowserContext ();
498 gFlagReconnect
= FALSE
;
499 gResetRequiredFormLevel
= FALSE
;
500 gExitRequired
= FALSE
;
501 gCallbackReconnect
= FALSE
;
502 Status
= EFI_SUCCESS
;
504 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
506 for (Index
= 0; Index
< HandleCount
; Index
++) {
507 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
508 ASSERT (Selection
!= NULL
);
510 Selection
->Handle
= Handles
[Index
];
511 if (FormSetGuid
!= NULL
) {
512 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
513 Selection
->FormId
= FormId
;
515 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
519 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
520 ASSERT (FormSet
!= NULL
);
523 // Validate the HiiHandle
524 // if validate failed, find the first validate parent HiiHandle.
526 if (!ValidateHiiHandle(Selection
->Handle
)) {
527 FindNextMenu (Selection
, FormSetLevel
);
531 // Initialize internal data structures of FormSet
533 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
534 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
535 DestroyFormSet (FormSet
);
538 Selection
->FormSet
= FormSet
;
539 mSystemLevelFormSet
= FormSet
;
540 mDynamicFormUpdated
= FALSE
;
543 // Display this formset
545 gCurrentSelection
= Selection
;
547 Status
= SetupBrowser (Selection
);
549 gCurrentSelection
= NULL
;
550 mSystemLevelFormSet
= NULL
;
553 // If callback update form dynamically, it's not exiting of the formset for user so system do not reconnect driver hanlde
556 if (!mDynamicFormUpdated
&& (gFlagReconnect
|| gCallbackReconnect
)) {
557 RetVal
= ReconnectController (FormSet
->DriverHandle
);
559 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
561 gFlagReconnect
= FALSE
;
562 gCallbackReconnect
= FALSE
;
566 // If no data is changed, don't need to save current FormSet into the maintain list.
568 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
569 CleanBrowserStorage(FormSet
);
570 RemoveEntryList (&FormSet
->Link
);
571 DestroyFormSet (FormSet
);
574 if (EFI_ERROR (Status
)) {
577 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
579 FreePool (Selection
);
582 if (ActionRequest
!= NULL
) {
583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
584 if (gResetRequiredFormLevel
) {
585 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
589 mFormDisplay
->ExitDisplay();
592 // Clear the menu history data.
594 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
595 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
596 RemoveEntryList (&MenuList
->Link
);
601 // Restore globals used by SendForm()
603 RestoreBrowserContext ();
609 Get or set data to the storage.
611 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
612 @param ResultsData A string returned from an IFR browser or
613 equivalent. The results string will have no
614 routing information in them.
615 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
616 (if RetrieveData = TRUE) data from the uncommitted
617 browser state information or set (if RetrieveData
618 = FALSE) data in the uncommitted browser state
620 @param Storage The pointer to the storage.
622 @retval EFI_SUCCESS The results have been distributed or are awaiting
628 IN OUT UINTN
*ResultsDataSize
,
629 IN OUT EFI_STRING
*ResultsData
,
630 IN BOOLEAN RetrieveData
,
631 IN BROWSER_STORAGE
*Storage
640 FORMSET_STORAGE
*BrowserStorage
;
644 // Generate <ConfigResp>
646 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
647 if (EFI_ERROR (Status
)) {
652 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
653 // Also need to consider add "\0" at first time.
655 StrPtr
= StrStr (ConfigResp
, L
"PATH");
656 ASSERT (StrPtr
!= NULL
);
657 StrPtr
= StrStr (StrPtr
, L
"&");
659 BufferSize
= StrSize (StrPtr
);
662 // Copy the data if the input buffer is bigger enough.
664 if (*ResultsDataSize
>= BufferSize
) {
665 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
668 *ResultsDataSize
= BufferSize
;
669 FreePool (ConfigResp
);
672 // Prepare <ConfigResp>
674 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
675 ASSERT (BrowserStorage
!= NULL
);
676 TmpSize
= StrLen (*ResultsData
);
677 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
678 MaxLen
= BufferSize
/ sizeof (CHAR16
);
679 ConfigResp
= AllocateZeroPool (BufferSize
);
680 ASSERT (ConfigResp
!= NULL
);
682 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
683 StrCatS (ConfigResp
, MaxLen
, L
"&");
684 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
687 // Update Browser uncommited data
689 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
690 FreePool (ConfigResp
);
691 if (EFI_ERROR (Status
)) {
700 This routine called this service in the browser to retrieve or set certain uncommitted
701 state information that resides in the open formsets.
703 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
705 @param ResultsDataSize A pointer to the size of the buffer associated
707 @param ResultsData A string returned from an IFR browser or
708 equivalent. The results string will have no
709 routing information in them.
710 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
711 (if RetrieveData = TRUE) data from the uncommitted
712 browser state information or set (if RetrieveData
713 = FALSE) data in the uncommitted browser state
715 @param VariableGuid An optional field to indicate the target variable
717 @param VariableName An optional field to indicate the target
718 human-readable variable name.
720 @retval EFI_SUCCESS The results have been distributed or are awaiting
722 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
723 contain the results data.
729 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
730 IN OUT UINTN
*ResultsDataSize
,
731 IN OUT EFI_STRING ResultsData
,
732 IN BOOLEAN RetrieveData
,
733 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
734 IN CONST CHAR16
*VariableName OPTIONAL
739 BROWSER_STORAGE
*Storage
;
740 FORMSET_STORAGE
*FormsetStorage
;
744 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
745 return EFI_INVALID_PARAMETER
;
748 TotalSize
= *ResultsDataSize
;
751 Status
= EFI_SUCCESS
;
753 if (VariableGuid
!= NULL
) {
755 // Try to find target storage in the current formset.
757 Link
= GetFirstNode (&gBrowserStorageList
);
758 while (!IsNull (&gBrowserStorageList
, Link
)) {
759 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
760 Link
= GetNextNode (&gBrowserStorageList
, Link
);
762 // Check the current storage.
764 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
768 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
769 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
771 // Buffer storage require both GUID and Name
773 if (VariableName
== NULL
) {
774 return EFI_NOT_FOUND
;
777 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
782 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
783 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
784 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
785 return EFI_NOT_FOUND
;
788 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
793 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
794 if (EFI_ERROR (Status
)) {
798 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
799 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
803 // Different formsets may have same varstore, so here just set the flag
804 // not exit the circle.
811 return EFI_NOT_FOUND
;
815 // GUID/Name is not specified, take the first storage in FormSet
817 if (mSystemLevelFormSet
== NULL
) {
818 return EFI_NOT_READY
;
822 // Generate <ConfigResp>
824 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
825 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
826 return EFI_UNSUPPORTED
;
829 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
831 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
832 if (EFI_ERROR (Status
)) {
838 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
839 *ResultsDataSize
= TotalSize
;
848 Callback function for SimpleTextInEx protocol install events
850 @param Event the event that is signaled.
851 @param Context not used here.
856 FormDisplayCallback (
861 if (mFormDisplay
!= NULL
) {
865 gBS
->LocateProtocol (
866 &gEdkiiFormDisplayEngineProtocolGuid
,
868 (VOID
**) &mFormDisplay
873 Initialize Setup Browser driver.
875 @param ImageHandle The image handle.
876 @param SystemTable The system table.
878 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
879 @return Other value if failed to initialize the Setup Browser module.
885 IN EFI_HANDLE ImageHandle
,
886 IN EFI_SYSTEM_TABLE
*SystemTable
893 // Locate required Hii relative protocols
895 Status
= gBS
->LocateProtocol (
896 &gEfiHiiDatabaseProtocolGuid
,
898 (VOID
**) &mHiiDatabase
900 ASSERT_EFI_ERROR (Status
);
902 Status
= gBS
->LocateProtocol (
903 &gEfiHiiConfigRoutingProtocolGuid
,
905 (VOID
**) &mHiiConfigRouting
907 ASSERT_EFI_ERROR (Status
);
909 Status
= gBS
->LocateProtocol (
910 &gEfiDevicePathFromTextProtocolGuid
,
912 (VOID
**) &mPathFromText
916 // Install FormBrowser2 protocol
918 mPrivateData
.Handle
= NULL
;
919 Status
= gBS
->InstallProtocolInterface (
920 &mPrivateData
.Handle
,
921 &gEfiFormBrowser2ProtocolGuid
,
922 EFI_NATIVE_INTERFACE
,
923 &mPrivateData
.FormBrowser2
925 ASSERT_EFI_ERROR (Status
);
928 // Install FormBrowserEx2 protocol
930 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
931 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
932 mPrivateData
.Handle
= NULL
;
933 Status
= gBS
->InstallProtocolInterface (
934 &mPrivateData
.Handle
,
935 &gEdkiiFormBrowserEx2ProtocolGuid
,
936 EFI_NATIVE_INTERFACE
,
937 &mPrivateData
.FormBrowserEx2
939 ASSERT_EFI_ERROR (Status
);
941 Status
= gBS
->InstallProtocolInterface (
942 &mPrivateData
.Handle
,
943 &gEdkiiFormBrowserExProtocolGuid
,
944 EFI_NATIVE_INTERFACE
,
945 &mPrivateData
.FormBrowserEx
947 ASSERT_EFI_ERROR (Status
);
949 InitializeDisplayFormData ();
951 Status
= gBS
->LocateProtocol (
952 &gEdkiiFormDisplayEngineProtocolGuid
,
954 (VOID
**) &mFormDisplay
957 if (EFI_ERROR (Status
)) {
958 EfiCreateProtocolNotifyEvent (
959 &gEdkiiFormDisplayEngineProtocolGuid
,
972 Create a new string in HII Package List.
974 @param String The String to be added
975 @param HiiHandle The package list in the HII database to insert the
978 @return The output string.
984 IN EFI_HII_HANDLE HiiHandle
987 EFI_STRING_ID StringId
;
989 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
990 ASSERT (StringId
!= 0);
997 Delete a string from HII Package List.
999 @param StringId Id of the string in HII database.
1000 @param HiiHandle The HII package list handle.
1002 @retval EFI_SUCCESS The string was deleted successfully.
1007 IN EFI_STRING_ID StringId
,
1008 IN EFI_HII_HANDLE HiiHandle
1013 NullChar
= CHAR_NULL
;
1014 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
);
1046 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
) {
1066 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1067 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
);
1145 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1148 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
;
1192 if (Buffer
!= NULL
) {
1195 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1196 ASSERT (Buffer
!= NULL
);
1197 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1198 Node
->EditValue
= Buffer
;
1200 Node
->Value
= Buffer
;
1203 if (ReturnNode
!= NULL
) {
1210 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1213 return EFI_NOT_FOUND
;
1218 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1220 @param Storage The Storage to be conveted.
1221 @param ConfigResp The returned <ConfigResp>.
1222 @param ConfigRequest The ConfigRequest string.
1223 @param GetEditBuf Get the data from editbuffer or buffer.
1225 @retval EFI_SUCCESS Convert success.
1226 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1230 StorageToConfigResp (
1231 IN BROWSER_STORAGE
*Storage
,
1232 IN CHAR16
**ConfigResp
,
1233 IN CHAR16
*ConfigRequest
,
1234 IN BOOLEAN GetEditBuf
1238 EFI_STRING Progress
;
1240 NAME_VALUE_NODE
*Node
;
1242 FORMSET_STORAGE
*FormsetStorage
;
1244 Status
= EFI_SUCCESS
;
1246 switch (Storage
->Type
) {
1247 case EFI_HII_VARSTORE_BUFFER
:
1248 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1249 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1250 Status
= mHiiConfigRouting
->BlockToConfig (
1260 case EFI_HII_VARSTORE_NAME_VALUE
:
1262 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1263 ASSERT (FormsetStorage
!= NULL
);
1264 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1266 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1267 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1268 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1270 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1271 NewStringCat (ConfigResp
, L
"&");
1272 NewStringCat (ConfigResp
, Node
->Name
);
1273 NewStringCat (ConfigResp
, L
"=");
1275 NewStringCat (ConfigResp
, Node
->EditValue
);
1277 NewStringCat (ConfigResp
, Node
->Value
);
1280 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1284 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1286 Status
= EFI_INVALID_PARAMETER
;
1295 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1297 @param Storage The Storage to receive the settings.
1298 @param ConfigResp The <ConfigResp> to be converted.
1300 @retval EFI_SUCCESS Convert success.
1301 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1305 ConfigRespToStorage (
1306 IN BROWSER_STORAGE
*Storage
,
1307 IN CHAR16
*ConfigResp
1311 EFI_STRING Progress
;
1317 Status
= EFI_SUCCESS
;
1319 switch (Storage
->Type
) {
1320 case EFI_HII_VARSTORE_BUFFER
:
1321 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1322 BufferSize
= Storage
->Size
;
1323 Status
= mHiiConfigRouting
->ConfigToBlock (
1326 Storage
->EditBuffer
,
1332 case EFI_HII_VARSTORE_NAME_VALUE
:
1333 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1334 if (StrPtr
== NULL
) {
1337 StrPtr
= StrStr (ConfigResp
, L
"&");
1338 while (StrPtr
!= NULL
) {
1342 StrPtr
= StrPtr
+ 1;
1344 StrPtr
= StrStr (StrPtr
, L
"=");
1345 if (StrPtr
== NULL
) {
1353 StrPtr
= StrPtr
+ 1;
1355 StrPtr
= StrStr (StrPtr
, L
"&");
1356 if (StrPtr
!= NULL
) {
1359 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1363 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1365 Status
= EFI_INVALID_PARAMETER
;
1373 Get bit field value from the buffer and then set the value for the question.
1374 Note: Data type UINT32 can cover all the bit field value.
1376 @param Question The question refer to bit field.
1377 @param Buffer Point to the buffer which the question value get from.
1381 GetBitsQuestionValue (
1382 IN FORM_BROWSER_STATEMENT
*Question
,
1391 StartBit
= Question
->BitVarOffset
% 8;
1392 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1394 CopyMem ((UINT8
*) &BufferValue
, Buffer
, Question
->StorageWidth
);
1396 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1399 // Set question value.
1400 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1401 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1403 CopyMem ((UINT8
*) &Question
->HiiValue
.Value
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1407 Set bit field value to the buffer.
1408 Note: Data type UINT32 can cover all the bit field value.
1410 @param Question The question refer to bit field.
1411 @param Buffer Point to the buffer which the question value set to.
1412 @param Value The bit field value need to set.
1416 SetBitsQuestionValue (
1417 IN FORM_BROWSER_STATEMENT
*Question
,
1418 IN OUT UINT8
*Buffer
,
1427 StartBit
= Question
->BitVarOffset
% 8;
1428 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1430 CopyMem ((UINT8
*) &Operand
, Buffer
, Question
->StorageWidth
);
1432 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1434 CopyMem (Buffer
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1438 Convert the buffer value to HiiValue.
1440 @param Question The question.
1441 @param Value Unicode buffer save the question value.
1443 @retval Status whether convert the value success.
1448 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1453 BOOLEAN IsBufferStorage
;
1468 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1469 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1470 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1471 IsBufferStorage
= TRUE
;
1473 IsBufferStorage
= FALSE
;
1477 // Question Value is provided by Buffer Storage or NameValue Storage
1479 if (Question
->BufferValue
!= NULL
) {
1481 // This Question is password or orderedlist
1483 Dst
= Question
->BufferValue
;
1486 // Other type of Questions
1488 if (Question
->QuestionReferToBitField
) {
1489 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1490 if (Buffer
== NULL
) {
1491 return EFI_OUT_OF_RESOURCES
;
1495 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1500 // Temp cut at the end of this section, end with '\0' or '&'.
1503 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1506 TempChar
= *StringPtr
;
1509 LengthStr
= StrLen (Value
);
1512 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1513 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1514 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1515 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1517 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1518 Length
= (UINTN
) Question
->StorageWidth
* 2;
1523 Status
= EFI_SUCCESS
;
1524 if (!IsBufferStorage
&& IsString
) {
1526 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1527 // Add string tail char L'\0' into Length
1529 DstBuf
= (CHAR16
*) Dst
;
1530 ZeroMem (TemStr
, sizeof (TemStr
));
1531 for (Index
= 0; Index
< Length
; Index
+= 4) {
1532 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1533 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1536 // Add tailing L'\0' character
1538 DstBuf
[Index
/4] = L
'\0';
1540 ZeroMem (TemStr
, sizeof (TemStr
));
1541 for (Index
= 0; Index
< Length
; Index
++) {
1542 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1543 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1544 if ((Index
& 1) == 0) {
1545 Dst
[Index
/2] = DigitUint8
;
1547 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1552 *StringPtr
= TempChar
;
1554 if (Buffer
!= NULL
&& Question
->QuestionReferToBitField
) {
1555 GetBitsQuestionValue (Question
, Buffer
);
1563 Get Question's current Value.
1565 @param FormSet FormSet data structure.
1566 @param Form Form data structure.
1567 @param Question Question to be initialized.
1568 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1570 @retval EFI_SUCCESS The function completed successfully.
1575 IN FORM_BROWSER_FORMSET
*FormSet
,
1576 IN FORM_BROWSER_FORM
*Form
,
1577 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1578 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1587 BROWSER_STORAGE
*Storage
;
1588 FORMSET_STORAGE
*FormsetStorage
;
1589 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1590 CHAR16
*ConfigRequest
;
1595 BOOLEAN IsBufferStorage
;
1598 Status
= EFI_SUCCESS
;
1602 if (GetValueFrom
>= GetSetValueWithMax
) {
1603 return EFI_INVALID_PARAMETER
;
1607 // Question value is provided by an Expression, evaluate it
1609 if (Question
->ValueExpression
!= NULL
) {
1610 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1611 if (!EFI_ERROR (Status
)) {
1612 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1613 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1614 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1615 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1616 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1618 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1619 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1621 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1623 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1624 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1630 // Get question value by read expression.
1632 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1633 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1634 if (!EFI_ERROR (Status
) &&
1635 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1637 // Only update question value to the valid result.
1639 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1640 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1641 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1642 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1643 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1645 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1646 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1648 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1650 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1651 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1657 // Question value is provided by RTC
1659 Storage
= Question
->Storage
;
1660 QuestionValue
= &Question
->HiiValue
.Value
;
1661 if (Storage
== NULL
) {
1663 // It's a Question without storage, or RTC date/time
1665 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1667 // Date and time define the same Flags bit
1669 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1670 case QF_DATE_STORAGE_TIME
:
1671 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1674 case QF_DATE_STORAGE_WAKEUP
:
1675 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1678 case QF_DATE_STORAGE_NORMAL
:
1681 // For date/time without storage
1686 if (EFI_ERROR (Status
)) {
1687 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1688 QuestionValue
->date
.Year
= 0xff;
1689 QuestionValue
->date
.Month
= 0xff;
1690 QuestionValue
->date
.Day
= 0xff;
1692 QuestionValue
->time
.Hour
= 0xff;
1693 QuestionValue
->time
.Minute
= 0xff;
1694 QuestionValue
->time
.Second
= 0xff;
1699 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1700 QuestionValue
->date
.Year
= EfiTime
.Year
;
1701 QuestionValue
->date
.Month
= EfiTime
.Month
;
1702 QuestionValue
->date
.Day
= EfiTime
.Day
;
1704 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1705 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1706 QuestionValue
->time
.Second
= EfiTime
.Second
;
1714 // Question value is provided by EFI variable
1716 StorageWidth
= Question
->StorageWidth
;
1717 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1718 if (Question
->BufferValue
!= NULL
) {
1719 Dst
= Question
->BufferValue
;
1721 Dst
= (UINT8
*) QuestionValue
;
1724 Status
= gRT
->GetVariable (
1725 Question
->VariableName
,
1732 // Always return success, even this EFI variable doesn't exist
1738 // Question Value is provided by Buffer Storage or NameValue Storage
1740 if (Question
->BufferValue
!= NULL
) {
1742 // This Question is password or orderedlist
1744 Dst
= Question
->BufferValue
;
1747 // Other type of Questions
1749 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1752 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1753 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1754 IsBufferStorage
= TRUE
;
1756 IsBufferStorage
= FALSE
;
1758 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1759 if (IsBufferStorage
) {
1760 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1762 // Copy from storage Edit buffer
1763 // If the Question refer to bit filed, get the value in the related bit filed.
1765 if (Question
->QuestionReferToBitField
) {
1766 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1768 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1772 // Copy from storage Edit buffer
1773 // If the Question refer to bit filed, get the value in the related bit filed.
1775 if (Question
->QuestionReferToBitField
) {
1776 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1778 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1783 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1784 if (EFI_ERROR (Status
)) {
1788 ASSERT (Value
!= NULL
);
1789 Status
= BufferToValue (Question
, Value
);
1793 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1794 ASSERT (FormsetStorage
!= NULL
);
1796 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1797 // <ConfigHdr> + "&" + <VariableName>
1799 if (IsBufferStorage
) {
1800 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1801 Length
+= StrLen (Question
->BlockName
);
1803 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1804 Length
+= StrLen (Question
->VariableName
) + 1;
1806 // Allocate buffer include '\0'
1807 MaxLen
= Length
+ 1;
1808 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1809 ASSERT (ConfigRequest
!= NULL
);
1811 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1812 if (IsBufferStorage
) {
1813 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1815 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1816 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1820 // Request current settings from Configuration Driver
1822 Status
= mHiiConfigRouting
->ExtractConfig (
1828 FreePool (ConfigRequest
);
1829 if (EFI_ERROR (Status
)) {
1834 // Skip <ConfigRequest>
1836 if (IsBufferStorage
) {
1837 Value
= StrStr (Result
, L
"&VALUE");
1838 if (Value
== NULL
) {
1840 return EFI_NOT_FOUND
;
1847 Value
= Result
+ Length
;
1849 if (*Value
!= '=') {
1851 return EFI_NOT_FOUND
;
1854 // Skip '=', point to value
1858 Status
= BufferToValue (Question
, Value
);
1859 if (EFI_ERROR (Status
)) {
1865 // Synchronize Edit Buffer
1867 if (IsBufferStorage
) {
1868 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1870 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1873 if (Result
!= NULL
) {
1883 Save Question Value to edit copy(cached) or Storage(uncached).
1885 @param FormSet FormSet data structure.
1886 @param Form Form data structure.
1887 @param Question Pointer to the Question.
1888 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1890 @retval EFI_SUCCESS The function completed successfully.
1895 IN FORM_BROWSER_FORMSET
*FormSet
,
1896 IN FORM_BROWSER_FORM
*Form
,
1897 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1898 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1908 BROWSER_STORAGE
*Storage
;
1909 FORMSET_STORAGE
*FormsetStorage
;
1910 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1915 BOOLEAN IsBufferStorage
;
1921 NAME_VALUE_NODE
*Node
;
1924 Status
= EFI_SUCCESS
;
1927 if (SetValueTo
>= GetSetValueWithMax
) {
1928 return EFI_INVALID_PARAMETER
;
1932 // If Question value is provided by an Expression, then it is read only
1934 if (Question
->ValueExpression
!= NULL
) {
1939 // Before set question value, evaluate its write expression.
1941 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1942 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1943 if (EFI_ERROR (Status
)) {
1949 // Question value is provided by RTC
1951 Storage
= Question
->Storage
;
1952 QuestionValue
= &Question
->HiiValue
.Value
;
1953 if (Storage
== NULL
) {
1955 // It's a Question without storage, or RTC date/time
1957 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1959 // Date and time define the same Flags bit
1961 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1962 case QF_DATE_STORAGE_TIME
:
1963 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1966 case QF_DATE_STORAGE_WAKEUP
:
1967 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1970 case QF_DATE_STORAGE_NORMAL
:
1973 // For date/time without storage
1978 if (EFI_ERROR (Status
)) {
1982 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1983 EfiTime
.Year
= QuestionValue
->date
.Year
;
1984 EfiTime
.Month
= QuestionValue
->date
.Month
;
1985 EfiTime
.Day
= QuestionValue
->date
.Day
;
1987 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1988 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1989 EfiTime
.Second
= QuestionValue
->time
.Second
;
1992 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1993 Status
= gRT
->SetTime (&EfiTime
);
1995 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
2003 // Question value is provided by EFI variable
2005 StorageWidth
= Question
->StorageWidth
;
2006 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2007 if (Question
->BufferValue
!= NULL
) {
2008 Src
= Question
->BufferValue
;
2010 Src
= (UINT8
*) QuestionValue
;
2013 Status
= gRT
->SetVariable (
2014 Question
->VariableName
,
2016 Storage
->Attributes
,
2024 // Question Value is provided by Buffer Storage or NameValue Storage
2026 if (Question
->BufferValue
!= NULL
) {
2027 Src
= Question
->BufferValue
;
2029 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
2032 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2033 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2034 IsBufferStorage
= TRUE
;
2036 IsBufferStorage
= FALSE
;
2038 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2040 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
2041 if (IsBufferStorage
) {
2042 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2044 // Copy to storage edit buffer
2045 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2047 if (Question
->QuestionReferToBitField
) {
2048 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2050 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2052 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2054 // Copy to storage buffer
2055 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2057 if (Question
->QuestionReferToBitField
) {
2058 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2060 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2066 // Allocate enough string buffer.
2069 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
2070 Value
= AllocateZeroPool (BufferLen
);
2071 ASSERT (Value
!= NULL
);
2073 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2075 TemName
= (CHAR16
*) Src
;
2077 for (; *TemName
!= L
'\0'; TemName
++) {
2078 UnicodeValueToStringS (
2080 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2081 PREFIX_ZERO
| RADIX_HEX
,
2085 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2088 BufferLen
= StorageWidth
* 2 + 1;
2089 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2090 ASSERT (Value
!= NULL
);
2092 // Convert Buffer to Hex String
2094 TemBuffer
= Src
+ StorageWidth
- 1;
2096 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2097 UnicodeValueToStringS (
2099 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2100 PREFIX_ZERO
| RADIX_HEX
,
2104 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2108 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2110 if (EFI_ERROR (Status
)) {
2114 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2116 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2117 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2119 if (IsBufferStorage
) {
2120 Length
= StrLen (Question
->BlockName
) + 7;
2122 Length
= StrLen (Question
->VariableName
) + 2;
2124 if (!IsBufferStorage
&& IsString
) {
2125 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2127 Length
+= (StorageWidth
* 2);
2129 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2130 ASSERT (FormsetStorage
!= NULL
);
2131 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2132 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2133 ASSERT (ConfigResp
!= NULL
);
2135 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2136 if (IsBufferStorage
) {
2137 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2138 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2140 StrCatS (ConfigResp
, MaxLen
, L
"&");
2141 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2142 StrCatS (ConfigResp
, MaxLen
, L
"=");
2145 Value
= ConfigResp
+ StrLen (ConfigResp
);
2147 if (!IsBufferStorage
&& IsString
) {
2149 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2151 TemName
= (CHAR16
*) Src
;
2153 for (; *TemName
!= L
'\0'; TemName
++) {
2154 UnicodeValueToStringS (
2156 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2157 PREFIX_ZERO
| RADIX_HEX
,
2161 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2165 // Convert Buffer to Hex String
2167 TemBuffer
= Src
+ StorageWidth
- 1;
2169 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2170 UnicodeValueToStringS (
2172 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2173 PREFIX_ZERO
| RADIX_HEX
,
2177 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2182 // Convert to lower char.
2184 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2185 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2186 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2191 // Submit Question Value to Configuration Driver
2193 Status
= mHiiConfigRouting
->RouteConfig (
2198 if (EFI_ERROR (Status
)) {
2199 FreePool (ConfigResp
);
2202 FreePool (ConfigResp
);
2205 // Sync storage, from editbuffer to buffer.
2207 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2215 Perform nosubmitif check for a Form.
2217 @param FormSet FormSet data structure.
2218 @param Form Form data structure.
2219 @param Question The Question to be validated.
2220 @param Type Validation type: NoSubmit
2222 @retval EFI_SUCCESS Form validation pass.
2223 @retval other Form validation failed.
2228 IN FORM_BROWSER_FORMSET
*FormSet
,
2229 IN FORM_BROWSER_FORM
*Form
,
2230 IN FORM_BROWSER_STATEMENT
*Question
,
2236 LIST_ENTRY
*ListHead
;
2237 FORM_EXPRESSION
*Expression
;
2238 UINT32 BrowserStatus
;
2241 BrowserStatus
= BROWSER_SUCCESS
;
2245 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2246 ListHead
= &Question
->InconsistentListHead
;
2249 case EFI_HII_EXPRESSION_WARNING_IF
:
2250 ListHead
= &Question
->WarningListHead
;
2253 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2254 ListHead
= &Question
->NoSubmitListHead
;
2259 return EFI_UNSUPPORTED
;
2262 Link
= GetFirstNode (ListHead
);
2263 while (!IsNull (ListHead
, Link
)) {
2264 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2267 // Evaluate the expression
2269 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2270 if (EFI_ERROR (Status
)) {
2274 if (IsTrue (&Expression
->Result
)) {
2276 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2277 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2280 case EFI_HII_EXPRESSION_WARNING_IF
:
2281 BrowserStatus
= BROWSER_WARNING_IF
;
2284 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2285 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2287 // This code only used to compatible with old display engine,
2288 // New display engine will not use this field.
2290 if (Expression
->Error
!= 0) {
2291 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2300 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2302 // If in system submit process and for no_submit_if check, not popup this error message.
2303 // Will process this fail again later in not system submit process.
2305 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2308 if (ErrorStr
!= NULL
) {
2309 FreePool (ErrorStr
);
2312 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2315 return EFI_NOT_READY
;
2319 Link
= GetNextNode (ListHead
, Link
);
2326 Perform question check.
2328 If one question has more than one check, process form high priority to low.
2329 Only one error info will be popup.
2331 @param FormSet FormSet data structure.
2332 @param Form Form data structure.
2333 @param Question The Question to be validated.
2335 @retval EFI_SUCCESS Form validation pass.
2336 @retval other Form validation failed.
2340 ValueChangedValidation (
2341 IN FORM_BROWSER_FORMSET
*FormSet
,
2342 IN FORM_BROWSER_FORM
*Form
,
2343 IN FORM_BROWSER_STATEMENT
*Question
2348 Status
= EFI_SUCCESS
;
2351 // Do the inconsistentif check.
2353 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2354 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2355 if (EFI_ERROR (Status
)) {
2361 // Do the warningif check.
2363 if (!IsListEmpty (&Question
->WarningListHead
)) {
2364 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2371 Perform NoSubmit check for each Form in FormSet.
2373 @param FormSet FormSet data structure.
2374 @param CurrentForm Current input form data structure.
2375 @param Statement The statement for this check.
2377 @retval EFI_SUCCESS Form validation pass.
2378 @retval other Form validation failed.
2383 IN FORM_BROWSER_FORMSET
*FormSet
,
2384 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2385 OUT FORM_BROWSER_STATEMENT
**Statement
2390 FORM_BROWSER_STATEMENT
*Question
;
2391 FORM_BROWSER_FORM
*Form
;
2392 LIST_ENTRY
*LinkForm
;
2394 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2395 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2396 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2397 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2399 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2403 Link
= GetFirstNode (&Form
->StatementListHead
);
2404 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2405 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2406 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2407 if (EFI_ERROR (Status
)) {
2408 if (*CurrentForm
== NULL
) {
2409 *CurrentForm
= Form
;
2411 if (Statement
!= NULL
) {
2412 *Statement
= Question
;
2417 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2425 Fill storage's edit copy with settings requested from Configuration Driver.
2427 @param Storage The storage which need to sync.
2428 @param ConfigRequest The config request string which used to sync storage.
2429 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2430 editbuffer to buffer
2431 if TRUE, copy the editbuffer to the buffer.
2432 if FALSE, copy the buffer to the editbuffer.
2434 @retval EFI_SUCCESS The function completed successfully.
2438 SynchronizeStorage (
2439 OUT BROWSER_STORAGE
*Storage
,
2440 IN CHAR16
*ConfigRequest
,
2441 IN BOOLEAN SyncOrRestore
2445 EFI_STRING Progress
;
2449 NAME_VALUE_NODE
*Node
;
2453 Status
= EFI_SUCCESS
;
2456 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2457 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2458 BufferSize
= Storage
->Size
;
2460 if (SyncOrRestore
) {
2461 Src
= Storage
->EditBuffer
;
2462 Dst
= Storage
->Buffer
;
2464 Src
= Storage
->Buffer
;
2465 Dst
= Storage
->EditBuffer
;
2468 if (ConfigRequest
!= NULL
) {
2469 Status
= mHiiConfigRouting
->BlockToConfig(
2477 if (EFI_ERROR (Status
)) {
2481 Status
= mHiiConfigRouting
->ConfigToBlock (
2488 if (Result
!= NULL
) {
2492 CopyMem (Dst
, Src
, BufferSize
);
2494 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2495 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2496 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2497 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2499 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2500 (ConfigRequest
== NULL
)) {
2501 if (SyncOrRestore
) {
2502 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2504 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2508 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2516 When discard the question value, call the callback function with Changed type
2517 to inform the hii driver.
2519 @param FormSet FormSet data structure.
2520 @param Form Form data structure.
2524 SendDiscardInfoToDriver (
2525 IN FORM_BROWSER_FORMSET
*FormSet
,
2526 IN FORM_BROWSER_FORM
*Form
2530 FORM_BROWSER_STATEMENT
*Question
;
2531 EFI_IFR_TYPE_VALUE
*TypeValue
;
2532 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2534 if (FormSet
->ConfigAccess
== NULL
) {
2538 Link
= GetFirstNode (&Form
->StatementListHead
);
2539 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2540 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2541 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2543 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2547 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2551 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2555 if (!Question
->ValueChanged
) {
2560 // Restore the question value before call the CHANGED callback type.
2562 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2564 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2565 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2568 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2569 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2571 TypeValue
= &Question
->HiiValue
.Value
;
2574 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2575 FormSet
->ConfigAccess
->Callback (
2576 FormSet
->ConfigAccess
,
2577 EFI_BROWSER_ACTION_CHANGED
,
2578 Question
->QuestionId
,
2579 Question
->HiiValue
.Type
,
2587 When submit the question value, call the callback function with Submitted type
2588 to inform the hii driver.
2590 @param FormSet FormSet data structure.
2591 @param Form Form data structure.
2595 SubmitCallbackForForm (
2596 IN FORM_BROWSER_FORMSET
*FormSet
,
2597 IN FORM_BROWSER_FORM
*Form
2601 FORM_BROWSER_STATEMENT
*Question
;
2602 EFI_IFR_TYPE_VALUE
*TypeValue
;
2603 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2605 if (FormSet
->ConfigAccess
== NULL
) {
2609 Link
= GetFirstNode (&Form
->StatementListHead
);
2610 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2611 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2612 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2614 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2618 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2622 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2626 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2627 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2629 TypeValue
= &Question
->HiiValue
.Value
;
2632 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2633 FormSet
->ConfigAccess
->Callback (
2634 FormSet
->ConfigAccess
,
2635 EFI_BROWSER_ACTION_SUBMITTED
,
2636 Question
->QuestionId
,
2637 Question
->HiiValue
.Type
,
2645 When value set Success, call the submit callback function.
2647 @param FormSet FormSet data structure.
2648 @param Form Form data structure.
2653 IN FORM_BROWSER_FORMSET
*FormSet
,
2654 IN FORM_BROWSER_FORM
*Form
2657 FORM_BROWSER_FORM
*CurrentForm
;
2661 SubmitCallbackForForm(FormSet
, Form
);
2665 Link
= GetFirstNode (&FormSet
->FormListHead
);
2666 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2667 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2668 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2670 SubmitCallbackForForm(FormSet
, CurrentForm
);
2675 Validate the HiiHandle.
2677 @param HiiHandle The input HiiHandle which need to validate.
2679 @retval TRUE The handle is validate.
2680 @retval FALSE The handle is invalidate.
2685 EFI_HII_HANDLE HiiHandle
2688 EFI_HII_HANDLE
*HiiHandles
;
2692 if (HiiHandle
== NULL
) {
2698 HiiHandles
= HiiGetHiiHandles (NULL
);
2699 ASSERT (HiiHandles
!= NULL
);
2701 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2702 if (HiiHandles
[Index
] == HiiHandle
) {
2708 FreePool (HiiHandles
);
2714 Validate the FormSet. If the formset is not validate, remove it from the list.
2716 @param FormSet The input FormSet which need to validate.
2718 @retval TRUE The handle is validate.
2719 @retval FALSE The handle is invalidate.
2724 FORM_BROWSER_FORMSET
*FormSet
2729 ASSERT (FormSet
!= NULL
);
2731 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2733 // Should not remove the formset which is being used.
2735 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2736 CleanBrowserStorage(FormSet
);
2737 RemoveEntryList (&FormSet
->Link
);
2738 DestroyFormSet (FormSet
);
2744 Check whether need to enable the reset flag in form level.
2745 Also clean all ValueChanged flag in question.
2747 @param SetFlag Whether need to set the Reset Flag.
2748 @param FormSet FormSet data structure.
2749 @param Form Form data structure.
2755 IN FORM_BROWSER_FORMSET
*FormSet
,
2756 IN FORM_BROWSER_FORM
*Form
2760 FORM_BROWSER_STATEMENT
*Question
;
2763 Link
= GetFirstNode (&Form
->StatementListHead
);
2764 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2765 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2766 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2768 if (!Question
->ValueChanged
) {
2772 OldValue
= Question
->ValueChanged
;
2775 // Compare the buffer and editbuffer data to see whether the data has been saved.
2777 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2780 // Only the changed data has been saved, then need to set the reset flag.
2782 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2783 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2784 gResetRequiredFormLevel
= TRUE
;
2785 gResetRequiredSystemLevel
= TRUE
;
2788 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2789 gFlagReconnect
= TRUE
;
2796 Check whether need to enable the reset flag.
2797 Also clean ValueChanged flag for all statements.
2799 Form level or formset level, only one.
2801 @param SetFlag Whether need to set the Reset Flag.
2802 @param FormSet FormSet data structure.
2803 @param Form Form data structure.
2807 ValueChangeResetFlagUpdate (
2809 IN FORM_BROWSER_FORMSET
*FormSet
,
2810 IN FORM_BROWSER_FORM
*Form
2813 FORM_BROWSER_FORM
*CurrentForm
;
2817 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2821 Link
= GetFirstNode (&FormSet
->FormListHead
);
2822 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2823 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2824 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2826 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2831 Base on the return Progress string to find the form.
2833 Base on the first return Offset/Width (Name) string to find the form
2834 which keep this string.
2836 @param FormSet FormSet data structure.
2837 @param Storage Storage which has this Progress string.
2838 @param Progress The Progress string which has the first fail string.
2839 @param RetForm The return form for this progress string.
2840 @param RetQuestion The return question for the error progress string.
2842 @retval TRUE Find the error form and statement for this error progress string.
2843 @retval FALSE Not find the error form.
2847 FindQuestionFromProgress (
2848 IN FORM_BROWSER_FORMSET
*FormSet
,
2849 IN BROWSER_STORAGE
*Storage
,
2850 IN EFI_STRING Progress
,
2851 OUT FORM_BROWSER_FORM
**RetForm
,
2852 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2856 LIST_ENTRY
*LinkStorage
;
2857 LIST_ENTRY
*LinkStatement
;
2858 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2859 FORM_BROWSER_FORM
*Form
;
2861 FORM_BROWSER_STATEMENT
*Statement
;
2863 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2867 *RetQuestion
= NULL
;
2870 // Skip the first "&" or the ConfigHdr part.
2872 if (*Progress
== '&') {
2876 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2878 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2880 // For Name/Value type, Skip the ConfigHdr part.
2882 EndStr
= StrStr (Progress
, L
"PATH=");
2883 ASSERT (EndStr
!= NULL
);
2884 while (*EndStr
!= '&') {
2891 // For Buffer type, Skip the ConfigHdr part.
2893 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2894 ASSERT (EndStr
!= NULL
);
2898 Progress
= EndStr
+ 1;
2902 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2904 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2906 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2907 // here, just keep the "Fred" string.
2909 EndStr
= StrStr (Progress
, L
"=");
2910 ASSERT (EndStr
!= NULL
);
2914 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2915 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2917 EndStr
= StrStr (Progress
, L
"&VALUE=");
2918 ASSERT (EndStr
!= NULL
);
2923 // Search in the form list.
2925 Link
= GetFirstNode (&FormSet
->FormListHead
);
2926 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2927 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2928 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2931 // Search in the ConfigReqeust list in this form.
2933 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2934 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2935 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2936 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2938 if (Storage
!= ConfigInfo
->Storage
) {
2942 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2944 // Find the OffsetWidth string in this form.
2951 if (*RetForm
!= NULL
) {
2952 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2953 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2954 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2955 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2957 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2958 *RetQuestion
= Statement
;
2962 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2963 *RetQuestion
= Statement
;
2969 if (*RetForm
!= NULL
) {
2975 // restore the OffsetWidth string to the original format.
2977 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2983 return (BOOLEAN
) (*RetForm
!= NULL
);
2987 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2988 for form and formset.
2990 @param Storage Storage which has this Progress string.
2991 @param ConfigRequest The ConfigRequest string.
2992 @param Progress The Progress string which has the first fail string.
2993 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2994 @param SyncConfigRequest Return the SyncConfigRequest string.
2998 GetSyncRestoreConfigRequest(
2999 IN BROWSER_STORAGE
*Storage
,
3000 IN EFI_STRING ConfigRequest
,
3001 IN EFI_STRING Progress
,
3002 OUT EFI_STRING
*RestoreConfigRequest
,
3003 OUT EFI_STRING
*SyncConfigRequest
3007 EFI_STRING ConfigHdrEndStr
;
3008 EFI_STRING ElementStr
;
3010 UINTN RestoreEleSize
;
3013 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3015 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3016 // Need to restore all the fields in the ConfigRequest.
3018 if (*Progress
== L
'G') {
3019 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3020 ASSERT (*RestoreConfigRequest
!= NULL
);
3025 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3027 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3029 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3030 // here, just keep the "Fred" string.
3032 EndStr
= StrStr (Progress
, L
"=");
3033 ASSERT (EndStr
!= NULL
);
3036 // Find the ConfigHdr in ConfigRequest.
3038 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3039 ASSERT (ConfigHdrEndStr
!= NULL
);
3040 while (*ConfigHdrEndStr
!= L
'&') {
3045 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3046 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3048 EndStr
= StrStr (Progress
, L
"&VALUE=");
3049 ASSERT (EndStr
!= NULL
);
3052 // Find the ConfigHdr in ConfigRequest.
3054 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3057 // Find the first fail pair in the ConfigRequest.
3059 ElementStr
= StrStr (ConfigRequest
, Progress
);
3060 ASSERT (ElementStr
!= NULL
);
3062 // To get the RestoreConfigRequest.
3064 RestoreEleSize
= StrSize (ElementStr
);
3065 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3066 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3067 ASSERT (*RestoreConfigRequest
!= NULL
);
3068 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3069 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3071 // To get the SyncConfigRequest.
3073 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3074 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3075 ASSERT (*SyncConfigRequest
!= NULL
);
3076 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3079 // restore the Progress string to the original format.
3081 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3089 Popup an save error info and get user input.
3091 @param TitleId The form title id.
3092 @param HiiHandle The hii handle for this package.
3094 @retval UINT32 The user select option for the save fail.
3095 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3099 IN EFI_STRING_ID TitleId
,
3100 IN EFI_HII_HANDLE HiiHandle
3104 CHAR16
*StringBuffer
;
3107 FormTitle
= GetToken (TitleId
, HiiHandle
);
3109 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3110 ASSERT (StringBuffer
!= NULL
);
3114 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3115 L
"Submit Fail For Form: %s.",
3119 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3121 FreePool (StringBuffer
);
3122 FreePool (FormTitle
);
3128 Popup an NO_SUBMIT_IF error info and get user input.
3130 @param TitleId The form title id.
3131 @param HiiHandle The hii handle for this package.
3133 @retval UINT32 The user select option for the save fail.
3134 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3137 ConfirmNoSubmitFail (
3138 IN EFI_STRING_ID TitleId
,
3139 IN EFI_HII_HANDLE HiiHandle
3143 CHAR16
*StringBuffer
;
3146 FormTitle
= GetToken (TitleId
, HiiHandle
);
3148 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3149 ASSERT (StringBuffer
!= NULL
);
3153 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3154 L
"NO_SUBMIT_IF error For Form: %s.",
3158 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3160 FreePool (StringBuffer
);
3161 FreePool (FormTitle
);
3167 Discard data based on the input setting scope (Form, FormSet or System).
3169 @param FormSet FormSet data structure.
3170 @param Form Form data structure.
3171 @param SettingScope Setting Scope for Discard action.
3173 @retval EFI_SUCCESS The function completed successfully.
3174 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3179 IN FORM_BROWSER_FORMSET
*FormSet
,
3180 IN FORM_BROWSER_FORM
*Form
,
3181 IN BROWSER_SETTING_SCOPE SettingScope
3185 FORMSET_STORAGE
*Storage
;
3186 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3187 FORM_BROWSER_FORMSET
*LocalFormSet
;
3188 FORM_BROWSER_FORMSET
*OldFormSet
;
3191 // Check the supported setting level.
3193 if (SettingScope
>= MaxLevel
) {
3194 return EFI_UNSUPPORTED
;
3197 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3199 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3200 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3201 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3202 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3204 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3209 // Skip if there is no RequestElement
3211 if (ConfigInfo
->ElementCount
== 0) {
3216 // Prepare <ConfigResp>
3218 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3221 // Call callback with Changed type to inform the driver.
3223 SendDiscardInfoToDriver (FormSet
, Form
);
3226 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3227 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3230 // Discard Buffer storage or Name/Value storage
3232 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3233 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3234 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3235 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3237 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3242 // Skip if there is no RequestElement
3244 if (Storage
->ElementCount
== 0) {
3248 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3251 Link
= GetFirstNode (&FormSet
->FormListHead
);
3252 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3253 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3254 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3257 // Call callback with Changed type to inform the driver.
3259 SendDiscardInfoToDriver (FormSet
, Form
);
3262 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3263 } else if (SettingScope
== SystemLevel
) {
3265 // System Level Discard.
3267 OldFormSet
= mSystemLevelFormSet
;
3270 // Discard changed value for each FormSet in the maintain list.
3272 Link
= GetFirstNode (&gBrowserFormSetList
);
3273 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3274 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3275 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3276 if (!ValidateFormSet(LocalFormSet
)) {
3280 mSystemLevelFormSet
= LocalFormSet
;
3282 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3283 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3285 // Remove maintain backup list after discard except for the current using FormSet.
3287 CleanBrowserStorage(LocalFormSet
);
3288 RemoveEntryList (&LocalFormSet
->Link
);
3289 DestroyFormSet (LocalFormSet
);
3293 mSystemLevelFormSet
= OldFormSet
;
3300 Submit data for a form.
3302 @param FormSet FormSet data structure.
3303 @param Form Form data structure.
3305 @retval EFI_SUCCESS The function completed successfully.
3306 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3311 IN FORM_BROWSER_FORMSET
*FormSet
,
3312 IN FORM_BROWSER_FORM
*Form
3317 EFI_STRING ConfigResp
;
3318 EFI_STRING Progress
;
3319 BROWSER_STORAGE
*Storage
;
3320 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3321 BOOLEAN SubmitFormFail
;
3323 SubmitFormFail
= FALSE
;
3325 if (!IsNvUpdateRequiredForForm (Form
)) {
3329 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3330 if (EFI_ERROR (Status
)) {
3334 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3335 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3336 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3337 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3339 Storage
= ConfigInfo
->Storage
;
3340 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3345 // Skip if there is no RequestElement
3347 if (ConfigInfo
->ElementCount
== 0) {
3352 // 1. Prepare <ConfigResp>
3354 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3355 if (EFI_ERROR (Status
)) {
3360 // 2. Set value to hii config routine protocol.
3362 Status
= mHiiConfigRouting
->RouteConfig (
3368 if (EFI_ERROR (Status
)) {
3370 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3372 SubmitFormFail
= TRUE
;
3373 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3374 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3375 FreePool (ConfigResp
);
3379 FreePool (ConfigResp
);
3381 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3383 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3387 // 4. Process the save failed storage.
3389 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3390 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3391 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3392 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3393 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3394 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3396 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3397 // base on the SyncConfigRequest to Sync the buffer.
3399 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3400 FreePool (ConfigInfo
->RestoreConfigRequest
);
3401 ConfigInfo
->RestoreConfigRequest
= NULL
;
3402 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3403 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3404 FreePool (ConfigInfo
->SyncConfigRequest
);
3405 ConfigInfo
->SyncConfigRequest
= NULL
;
3408 Status
= EFI_SUCCESS
;
3410 SendDiscardInfoToDriver (FormSet
,Form
);
3412 Status
= EFI_UNSUPPORTED
;
3416 // Free Form save fail list.
3418 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3419 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3420 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3421 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3426 // 5. Update the NV flag.
3428 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3431 // 6 Call callback with Submitted type to inform the driver.
3433 if (!SubmitFormFail
) {
3434 SubmitCallback (FormSet
, Form
);
3441 Submit data for a formset.
3443 @param FormSet FormSet data structure.
3444 @param SkipProcessFail Whether skip to process the save failed storage.
3445 If submit formset is called when do system level save,
3446 set this value to true and process the failed formset
3448 if submit formset is called when do formset level save,
3449 set the value to false and process the failed storage
3450 right after process all storages for this formset.
3452 @retval EFI_SUCCESS The function completed successfully.
3453 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3458 IN FORM_BROWSER_FORMSET
*FormSet
,
3459 IN BOOLEAN SkipProcessFail
3464 EFI_STRING ConfigResp
;
3465 EFI_STRING Progress
;
3466 BROWSER_STORAGE
*Storage
;
3467 FORMSET_STORAGE
*FormSetStorage
;
3468 FORM_BROWSER_FORM
*Form
;
3469 BOOLEAN HasInserted
;
3470 FORM_BROWSER_STATEMENT
*Question
;
3471 BOOLEAN SubmitFormSetFail
;
3472 BOOLEAN DiscardChange
;
3474 HasInserted
= FALSE
;
3475 SubmitFormSetFail
= FALSE
;
3476 DiscardChange
= FALSE
;
3478 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3483 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3484 if (EFI_ERROR (Status
)) {
3485 if (SkipProcessFail
) {
3487 // Process NO_SUBMIT check first, so insert it at head.
3489 FormSet
->SaveFailForm
= Form
;
3490 FormSet
->SaveFailStatement
= Question
;
3491 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3500 // Submit Buffer storage or Name/Value storage
3502 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3503 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3504 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3505 Storage
= FormSetStorage
->BrowserStorage
;
3506 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3508 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3513 // Skip if there is no RequestElement
3515 if (FormSetStorage
->ElementCount
== 0) {
3520 // 1. Prepare <ConfigResp>
3522 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3523 if (EFI_ERROR (Status
)) {
3528 // 2. Send <ConfigResp> to Routine config Protocol.
3530 Status
= mHiiConfigRouting
->RouteConfig (
3535 if (EFI_ERROR (Status
)) {
3537 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3539 SubmitFormSetFail
= TRUE
;
3540 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3541 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3544 // Call submit formset for system level, save the formset info
3545 // and process later.
3547 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3548 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3549 FormSet
->SaveFailForm
= Form
;
3550 FormSet
->SaveFailStatement
= Question
;
3551 if (SkipProcessFail
) {
3552 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3557 FreePool (ConfigResp
);
3561 FreePool (ConfigResp
);
3563 // 3. Config success, update storage shadow Buffer
3565 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3569 // 4. Has save fail storage need to handle.
3572 if (!SkipProcessFail
) {
3574 // If not in system level, just handl the save failed storage here.
3576 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3577 DiscardChange
= TRUE
;
3578 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3579 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3580 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3581 Storage
= FormSetStorage
->BrowserStorage
;
3582 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3584 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3585 // base on the SyncConfigRequest to Sync the buffer.
3587 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3588 FreePool (FormSetStorage
->RestoreConfigRequest
);
3589 FormSetStorage
->RestoreConfigRequest
= NULL
;
3590 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3591 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3592 FreePool (FormSetStorage
->SyncConfigRequest
);
3593 FormSetStorage
->SyncConfigRequest
= NULL
;
3596 Status
= EFI_SUCCESS
;
3599 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3601 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3602 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3603 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3604 gCurrentSelection
->FormId
= Form
->FormId
;
3605 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3607 Status
= EFI_UNSUPPORTED
;
3611 // Free FormSet save fail list.
3613 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3614 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3615 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3616 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3620 // If in system level, just return error and handle the failed formset later.
3622 Status
= EFI_UNSUPPORTED
;
3627 // If user discard the change, send the discard info to driver.
3629 if (DiscardChange
) {
3630 Link
= GetFirstNode (&FormSet
->FormListHead
);
3631 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3632 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3633 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3635 // Call callback with Changed type to inform the driver.
3637 SendDiscardInfoToDriver (FormSet
, Form
);
3642 // 5. Update the NV flag.
3644 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3647 // 6. Call callback with Submitted type to inform the driver.
3649 if (!SubmitFormSetFail
) {
3650 SubmitCallback (FormSet
, NULL
);
3657 Submit data for all formsets.
3659 @retval EFI_SUCCESS The function completed successfully.
3660 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3670 LIST_ENTRY
*FormLink
;
3671 LIST_ENTRY
*StorageLink
;
3672 FORMSET_STORAGE
*FormSetStorage
;
3673 FORM_BROWSER_FORM
*Form
;
3674 FORM_BROWSER_FORMSET
*LocalFormSet
;
3675 UINT32 UserSelection
;
3676 FORM_BROWSER_STATEMENT
*Question
;
3678 mSystemSubmit
= TRUE
;
3679 Link
= GetFirstNode (&gBrowserFormSetList
);
3680 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3681 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3682 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3683 if (!ValidateFormSet(LocalFormSet
)) {
3687 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3688 if (EFI_ERROR (Status
)) {
3693 // Remove maintain backup list after save except for the current using FormSet.
3695 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3696 CleanBrowserStorage(LocalFormSet
);
3697 RemoveEntryList (&LocalFormSet
->Link
);
3698 DestroyFormSet (LocalFormSet
);
3701 mSystemSubmit
= FALSE
;
3703 Status
= EFI_SUCCESS
;
3706 // Process the save failed formsets.
3708 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3709 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3710 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3711 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3713 if (!ValidateFormSet(LocalFormSet
)) {
3717 Form
= LocalFormSet
->SaveFailForm
;
3718 Question
= LocalFormSet
->SaveFailStatement
;
3721 // Confirm with user, get user input.
3723 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3725 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3727 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3729 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3732 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3733 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3734 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3735 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3736 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3737 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3739 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3742 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3743 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3744 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3745 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3747 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3748 // base on the SyncConfigRequest to Sync the buffer.
3750 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3751 FreePool (FormSetStorage
->RestoreConfigRequest
);
3752 FormSetStorage
->RestoreConfigRequest
= NULL
;
3753 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3754 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3755 FreePool (FormSetStorage
->SyncConfigRequest
);
3756 FormSetStorage
->SyncConfigRequest
= NULL
;
3761 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3762 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3763 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3764 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3766 // Call callback with Changed type to inform the driver.
3768 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3771 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3772 CleanBrowserStorage(LocalFormSet
);
3773 RemoveEntryList (&LocalFormSet
->Link
);
3774 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3775 DestroyFormSet (LocalFormSet
);
3777 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3780 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3781 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3784 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3786 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3787 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3788 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3789 gCurrentSelection
->FormId
= Form
->FormId
;
3790 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3792 Status
= EFI_UNSUPPORTED
;
3798 // Clean the list which will not process.
3800 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3801 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3802 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3803 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3805 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3806 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3807 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3808 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3816 Submit data based on the input Setting level (Form, FormSet or System).
3818 @param FormSet FormSet data structure.
3819 @param Form Form data structure.
3820 @param SettingScope Setting Scope for Submit action.
3822 @retval EFI_SUCCESS The function completed successfully.
3823 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3828 IN FORM_BROWSER_FORMSET
*FormSet
,
3829 IN FORM_BROWSER_FORM
*Form
,
3830 IN BROWSER_SETTING_SCOPE SettingScope
3835 switch (SettingScope
) {
3837 Status
= SubmitForForm(FormSet
, Form
);
3841 Status
= SubmitForFormSet (FormSet
, FALSE
);
3845 Status
= SubmitForSystem ();
3849 Status
= EFI_UNSUPPORTED
;
3857 Converts the unicode character of the string from uppercase to lowercase.
3858 This is a internal function.
3860 @param ConfigString String to be converted
3866 IN EFI_STRING ConfigString
3872 ASSERT (ConfigString
!= NULL
);
3875 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3877 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3878 if (*String
== L
'=') {
3880 } else if (*String
== L
'&') {
3882 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3883 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3889 Find the point in the ConfigResp string for this question.
3891 @param Question The question.
3892 @param ConfigResp Get ConfigResp string.
3894 @retval point to the offset where is for this question.
3898 GetOffsetFromConfigResp (
3899 IN FORM_BROWSER_STATEMENT
*Question
,
3900 IN CHAR16
*ConfigResp
3903 CHAR16
*RequestElement
;
3907 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3909 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3910 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3911 if (RequestElement
!= NULL
) {
3913 // Skip the "VariableName=" field.
3915 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3918 return RequestElement
;
3922 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3926 // Convert all hex digits in ConfigResp to lower case before searching.
3928 HiiToLower (ConfigResp
);
3931 // 1. Directly use Question->BlockName to find.
3933 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3934 if (RequestElement
!= NULL
) {
3936 // Skip the "Question->BlockName&VALUE=" field.
3938 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3939 return RequestElement
;
3943 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3945 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3946 ASSERT (BlockData
!= NULL
);
3947 HiiToLower (BlockData
);
3948 RequestElement
= StrStr (ConfigResp
, BlockData
);
3949 FreePool (BlockData
);
3951 if (RequestElement
!= NULL
) {
3953 // Skip the "Question->BlockName&VALUE=" field.
3955 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3958 return RequestElement
;
3962 Get Question default value from AltCfg string.
3964 @param FormSet The form set.
3965 @param Form The form
3966 @param Question The question.
3968 @retval EFI_SUCCESS Question is reset to default value.
3972 GetDefaultValueFromAltCfg (
3973 IN FORM_BROWSER_FORMSET
*FormSet
,
3974 IN FORM_BROWSER_FORM
*Form
,
3975 IN OUT FORM_BROWSER_STATEMENT
*Question
3978 BROWSER_STORAGE
*Storage
;
3979 FORMSET_STORAGE
*FormSetStorage
;
3983 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3985 Storage
= Question
->Storage
;
3986 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3987 return EFI_NOT_FOUND
;
3991 // Try to get AltCfg string from form. If not found it, then
3992 // try to get it from formset.
3995 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3996 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3997 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3998 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4000 if (Storage
== ConfigInfo
->Storage
) {
4001 ConfigResp
= ConfigInfo
->ConfigAltResp
;
4006 if (ConfigResp
== NULL
) {
4007 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4008 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4009 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4010 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4012 if (Storage
== FormSetStorage
->BrowserStorage
) {
4013 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4019 if (ConfigResp
== NULL
) {
4020 return EFI_NOT_FOUND
;
4023 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4024 if (Value
== NULL
) {
4025 return EFI_NOT_FOUND
;
4028 return BufferToValue (Question
, Value
);
4032 Get default Id value used for browser.
4034 @param DefaultId The default id value used by hii.
4036 @retval Browser used default value.
4040 GetDefaultIdForCallBack (
4044 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4045 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4046 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4047 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4048 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4049 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4050 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
4051 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4052 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
4053 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4054 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
4055 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4064 Return data element in an Array by its Index.
4066 @param Array The data array.
4067 @param Type Type of the data in this array.
4068 @param Index Zero based index for data in this array.
4070 @retval Value The data to be returned
4082 ASSERT (Array
!= NULL
);
4086 case EFI_IFR_TYPE_NUM_SIZE_8
:
4087 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
4090 case EFI_IFR_TYPE_NUM_SIZE_16
:
4091 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
4094 case EFI_IFR_TYPE_NUM_SIZE_32
:
4095 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
4098 case EFI_IFR_TYPE_NUM_SIZE_64
:
4099 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4111 Set value of a data element in an Array by its Index.
4113 @param Array The data array.
4114 @param Type Type of the data in this array.
4115 @param Index Zero based index for data in this array.
4116 @param Value The value to be set.
4128 ASSERT (Array
!= NULL
);
4131 case EFI_IFR_TYPE_NUM_SIZE_8
:
4132 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4135 case EFI_IFR_TYPE_NUM_SIZE_16
:
4136 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4139 case EFI_IFR_TYPE_NUM_SIZE_32
:
4140 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4143 case EFI_IFR_TYPE_NUM_SIZE_64
:
4144 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4153 Search an Option of a Question by its value.
4155 @param Question The Question
4156 @param OptionValue Value for Option to be searched.
4158 @retval Pointer Pointer to the found Option.
4159 @retval NULL Option not found.
4164 IN FORM_BROWSER_STATEMENT
*Question
,
4165 IN EFI_HII_VALUE
*OptionValue
4169 QUESTION_OPTION
*Option
;
4172 Link
= GetFirstNode (&Question
->OptionListHead
);
4173 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4174 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4176 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4178 // Check the suppressif condition, only a valid option can be return.
4180 if ((Option
->SuppressExpression
== NULL
) ||
4181 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4186 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4194 Reset Question to its default value.
4196 @param FormSet The form set.
4197 @param Form The form.
4198 @param Question The question.
4199 @param DefaultId The Class of the default.
4201 @retval EFI_SUCCESS Question is reset to default value.
4205 GetQuestionDefault (
4206 IN FORM_BROWSER_FORMSET
*FormSet
,
4207 IN FORM_BROWSER_FORM
*Form
,
4208 IN FORM_BROWSER_STATEMENT
*Question
,
4214 QUESTION_DEFAULT
*Default
;
4215 QUESTION_OPTION
*Option
;
4216 EFI_HII_VALUE
*HiiValue
;
4218 EFI_STRING StrValue
;
4219 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4220 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4223 EFI_IFR_TYPE_VALUE
*TypeValue
;
4224 UINT16 OriginalDefaultId
;
4225 FORMSET_DEFAULTSTORE
*DefaultStore
;
4226 LIST_ENTRY
*DefaultLink
;
4228 Status
= EFI_NOT_FOUND
;
4230 OriginalDefaultId
= DefaultId
;
4231 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4234 // Statement don't have storage, skip them
4236 if (Question
->QuestionId
== 0) {
4241 // There are Five ways to specify default value for a Question:
4242 // 1, use call back function (highest priority)
4243 // 2, use ExtractConfig function
4244 // 3, use nested EFI_IFR_DEFAULT
4245 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4246 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4249 HiiValue
= &Question
->HiiValue
;
4250 TypeValue
= &HiiValue
->Value
;
4251 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4253 // For orderedlist, need to pass the BufferValue to Callback function.
4255 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4259 // Get Question defaut value from call back function.
4261 ConfigAccess
= FormSet
->ConfigAccess
;
4262 Action
= GetDefaultIdForCallBack (DefaultId
);
4263 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4264 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4265 Status
= ConfigAccess
->Callback (
4268 Question
->QuestionId
,
4273 if (!EFI_ERROR (Status
)) {
4274 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4275 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4276 ASSERT (NewString
!= NULL
);
4278 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4279 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4280 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4281 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4283 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4286 FreePool (NewString
);
4293 // Get default value from altcfg string.
4295 if (ConfigAccess
!= NULL
) {
4296 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4297 if (!EFI_ERROR (Status
)) {
4303 // EFI_IFR_DEFAULT has highest priority
4305 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4306 Link
= GetFirstNode (&Question
->DefaultListHead
);
4307 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4308 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4310 if (Default
->DefaultId
== DefaultId
) {
4311 if (Default
->ValueExpression
!= NULL
) {
4313 // Default is provided by an Expression, evaluate it
4315 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4316 if (EFI_ERROR (Status
)) {
4320 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4321 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4322 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4323 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4324 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4326 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4327 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4329 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4331 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4332 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4335 // Default value is embedded in EFI_IFR_DEFAULT
4337 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4338 ASSERT (HiiValue
->Buffer
!= NULL
);
4339 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4341 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4345 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4346 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4347 if (StrValue
== NULL
) {
4348 return EFI_NOT_FOUND
;
4350 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4351 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4352 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4354 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4361 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4366 // EFI_ONE_OF_OPTION
4368 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4369 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4371 // OneOfOption could only provide Standard and Manufacturing default
4373 Link
= GetFirstNode (&Question
->OptionListHead
);
4374 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4375 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4376 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4378 if ((Option
->SuppressExpression
!= NULL
) &&
4379 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4383 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4384 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4386 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4395 // EFI_IFR_CHECKBOX - lowest priority
4397 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4398 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4400 // Checkbox could only provide Standard and Manufacturing default
4402 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4403 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4405 HiiValue
->Value
.b
= TRUE
;
4413 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4414 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4415 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4417 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4418 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4419 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4420 DefaultId
= DefaultStore
->DefaultId
;
4421 if (DefaultId
== OriginalDefaultId
) {
4428 // For Questions without default value for all the default id in the DefaultStoreList.
4430 Status
= EFI_NOT_FOUND
;
4431 switch (Question
->Operand
) {
4432 case EFI_IFR_CHECKBOX_OP
:
4433 HiiValue
->Value
.b
= FALSE
;
4434 Status
= EFI_SUCCESS
;
4437 case EFI_IFR_NUMERIC_OP
:
4439 // Take minimum value as numeric default value
4441 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4443 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4445 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4446 case EFI_IFR_NUMERIC_SIZE_1
:
4447 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4448 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4449 Status
= EFI_SUCCESS
;
4452 case EFI_IFR_NUMERIC_SIZE_2
:
4453 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4454 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4455 Status
= EFI_SUCCESS
;
4458 case EFI_IFR_NUMERIC_SIZE_4
:
4459 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4460 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4461 Status
= EFI_SUCCESS
;
4464 case EFI_IFR_NUMERIC_SIZE_8
:
4465 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4466 HiiValue
->Value
.u64
= Question
->Minimum
;
4467 Status
= EFI_SUCCESS
;
4474 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4475 HiiValue
->Value
.u64
= Question
->Minimum
;
4476 Status
= EFI_SUCCESS
;
4481 case EFI_IFR_ONE_OF_OP
:
4483 // Take first oneof option as oneof's default value
4485 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4486 Link
= GetFirstNode (&Question
->OptionListHead
);
4487 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4488 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4489 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4491 if ((Option
->SuppressExpression
!= NULL
) &&
4492 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4496 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4497 Status
= EFI_SUCCESS
;
4503 case EFI_IFR_ORDERED_LIST_OP
:
4505 // Take option sequence in IFR as ordered list's default value
4508 Link
= GetFirstNode (&Question
->OptionListHead
);
4509 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4510 Status
= EFI_SUCCESS
;
4511 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4512 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4514 if ((Option
->SuppressExpression
!= NULL
) &&
4515 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4519 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4522 if (Index
>= Question
->MaxContainers
) {
4536 Get AltCfg string for current form.
4538 @param FormSet Form data structure.
4539 @param Form Form data structure.
4540 @param DefaultId The Class of the default.
4541 @param BrowserStorage The input request storage for the questions.
4545 ExtractAltCfgForForm (
4546 IN FORM_BROWSER_FORMSET
*FormSet
,
4547 IN FORM_BROWSER_FORM
*Form
,
4548 IN UINT16 DefaultId
,
4549 IN BROWSER_STORAGE
*BrowserStorage
4557 BROWSER_STORAGE
*Storage
;
4558 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4559 FORMSET_STORAGE
*FormSetStorage
;
4562 // Check whether has get AltCfg string for this formset.
4563 // If yes, no need to get AltCfg for form.
4565 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4566 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4567 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4568 Storage
= FormSetStorage
->BrowserStorage
;
4569 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4570 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4574 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4575 FormSetStorage
->ElementCount
!= 0 &&
4576 FormSetStorage
->HasCallAltCfg
) {
4582 // Get AltCfg string for each form.
4584 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4585 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4586 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4587 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4589 Storage
= ConfigInfo
->Storage
;
4590 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4594 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4599 // 1. Skip if there is no RequestElement
4601 if (ConfigInfo
->ElementCount
== 0) {
4606 // 2. Get value through hii config routine protocol.
4608 Status
= mHiiConfigRouting
->ExtractConfig (
4610 ConfigInfo
->ConfigRequest
,
4614 if (EFI_ERROR (Status
)) {
4619 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4620 // Get the default configuration string according to the default ID.
4622 Status
= mHiiConfigRouting
->GetAltConfig (
4628 &DefaultId
, // it can be NULL to get the current setting.
4632 if (EFI_ERROR (Status
)) {
4636 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4641 Clean AltCfg string for current form.
4643 @param Form Form data structure.
4647 CleanAltCfgForForm (
4648 IN FORM_BROWSER_FORM
*Form
4652 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4654 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4655 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4656 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4657 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4659 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4660 FreePool (ConfigInfo
->ConfigAltResp
);
4661 ConfigInfo
->ConfigAltResp
= NULL
;
4667 Get AltCfg string for current formset.
4669 @param FormSet Form data structure.
4670 @param DefaultId The Class of the default.
4671 @param BrowserStorage The input request storage for the questions.
4675 ExtractAltCfgForFormSet (
4676 IN FORM_BROWSER_FORMSET
*FormSet
,
4677 IN UINT16 DefaultId
,
4678 IN BROWSER_STORAGE
*BrowserStorage
4686 BROWSER_STORAGE
*Storage
;
4687 FORMSET_STORAGE
*FormSetStorage
;
4689 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4690 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4691 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4692 Storage
= FormSetStorage
->BrowserStorage
;
4693 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4695 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4699 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4704 // 1. Skip if there is no RequestElement
4706 if (FormSetStorage
->ElementCount
== 0) {
4710 FormSetStorage
->HasCallAltCfg
= TRUE
;
4713 // 2. Get value through hii config routine protocol.
4715 Status
= mHiiConfigRouting
->ExtractConfig (
4717 FormSetStorage
->ConfigRequest
,
4721 if (EFI_ERROR (Status
)) {
4726 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4727 // Get the default configuration string according to the default ID.
4729 Status
= mHiiConfigRouting
->GetAltConfig (
4735 &DefaultId
, // it can be NULL to get the current setting.
4740 if (EFI_ERROR (Status
)) {
4744 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4750 Clean AltCfg string for current formset.
4752 @param FormSet Form data structure.
4756 CleanAltCfgForFormSet (
4757 IN FORM_BROWSER_FORMSET
*FormSet
4761 FORMSET_STORAGE
*FormSetStorage
;
4763 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4764 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4765 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4766 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4768 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4769 FreePool (FormSetStorage
->ConfigAltResp
);
4770 FormSetStorage
->ConfigAltResp
= NULL
;
4773 FormSetStorage
->HasCallAltCfg
= FALSE
;
4778 Reset Questions to their initial value or default value in a Form, Formset or System.
4780 GetDefaultValueScope parameter decides which questions will reset
4781 to its default value.
4783 @param FormSet FormSet data structure.
4784 @param Form Form data structure.
4785 @param DefaultId The Class of the default.
4786 @param SettingScope Setting Scope for Default action.
4787 @param GetDefaultValueScope Get default value scope.
4788 @param Storage Get default value only for this storage.
4789 @param RetrieveValueFirst Whether call the retrieve call back to
4790 get the initial value before get default
4792 @param SkipGetAltCfg Whether skip the get altcfg string process.
4794 @retval EFI_SUCCESS The function completed successfully.
4795 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4800 IN FORM_BROWSER_FORMSET
*FormSet
,
4801 IN FORM_BROWSER_FORM
*Form
,
4802 IN UINT16 DefaultId
,
4803 IN BROWSER_SETTING_SCOPE SettingScope
,
4804 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4805 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4806 IN BOOLEAN RetrieveValueFirst
,
4807 IN BOOLEAN SkipGetAltCfg
4811 LIST_ENTRY
*FormLink
;
4813 FORM_BROWSER_STATEMENT
*Question
;
4814 FORM_BROWSER_FORMSET
*LocalFormSet
;
4815 FORM_BROWSER_FORMSET
*OldFormSet
;
4817 Status
= EFI_SUCCESS
;
4820 // Check the supported setting level.
4822 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4823 return EFI_UNSUPPORTED
;
4826 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4827 return EFI_UNSUPPORTED
;
4830 if (SettingScope
== FormLevel
) {
4832 // Prepare the AltCfg String for form.
4834 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4835 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4839 // Extract Form default
4841 Link
= GetFirstNode (&Form
->StatementListHead
);
4842 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4843 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4844 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4847 // If get default value only for this storage, check the storage first.
4849 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4854 // If get default value only for no storage question, just skip the question which has storage.
4856 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4861 // If Question is disabled, don't reset it to default
4863 if (Question
->Expression
!= NULL
) {
4864 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4869 if (RetrieveValueFirst
) {
4871 // Call the Retrieve call back to get the initial question value.
4873 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4877 // If not request to get the initial value or get initial value fail, then get default value.
4879 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4880 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4881 if (EFI_ERROR (Status
)) {
4887 // Synchronize Buffer storage's Edit buffer
4889 if ((Question
->Storage
!= NULL
) &&
4890 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4891 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4896 // Clean the AltCfg String.
4898 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4899 CleanAltCfgForForm(Form
);
4901 } else if (SettingScope
== FormSetLevel
) {
4903 // Prepare the AltCfg String for formset.
4905 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4906 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4909 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4910 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4911 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4912 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4913 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4917 // Clean the AltCfg String.
4919 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4920 CleanAltCfgForFormSet (FormSet
);
4922 } else if (SettingScope
== SystemLevel
) {
4924 // Preload all Hii formset.
4926 LoadAllHiiFormset();
4928 OldFormSet
= mSystemLevelFormSet
;
4931 // Set Default Value for each FormSet in the maintain list.
4933 Link
= GetFirstNode (&gBrowserFormSetList
);
4934 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4935 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4936 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4937 if (!ValidateFormSet(LocalFormSet
)) {
4941 mSystemLevelFormSet
= LocalFormSet
;
4943 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4946 mSystemLevelFormSet
= OldFormSet
;
4954 Validate whether this question's value has changed.
4956 @param FormSet FormSet data structure.
4957 @param Form Form data structure.
4958 @param Question Question to be initialized.
4959 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4961 @retval TRUE Question's value has changed.
4962 @retval FALSE Question's value has not changed
4966 IsQuestionValueChanged (
4967 IN FORM_BROWSER_FORMSET
*FormSet
,
4968 IN FORM_BROWSER_FORM
*Form
,
4969 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4970 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4973 EFI_HII_VALUE BackUpValue
;
4974 CHAR8
*BackUpBuffer
;
4975 EFI_HII_VALUE BackUpValue2
;
4976 CHAR8
*BackUpBuffer2
;
4978 BOOLEAN ValueChanged
;
4982 // For quetion without storage, always mark it as data not changed.
4984 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4988 BackUpBuffer
= NULL
;
4989 BackUpBuffer2
= NULL
;
4990 ValueChanged
= FALSE
;
4992 switch (Question
->Operand
) {
4993 case EFI_IFR_ORDERED_LIST_OP
:
4994 BufferWidth
= Question
->StorageWidth
;
4995 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4996 ASSERT (BackUpBuffer
!= NULL
);
4999 case EFI_IFR_STRING_OP
:
5000 case EFI_IFR_PASSWORD_OP
:
5001 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5002 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5003 ASSERT (BackUpBuffer
!= NULL
);
5010 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5012 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5013 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5014 ASSERT_EFI_ERROR(Status
);
5016 switch (Question
->Operand
) {
5017 case EFI_IFR_ORDERED_LIST_OP
:
5018 BufferWidth
= Question
->StorageWidth
;
5019 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5020 ASSERT (BackUpBuffer2
!= NULL
);
5023 case EFI_IFR_STRING_OP
:
5024 case EFI_IFR_PASSWORD_OP
:
5025 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5026 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5027 ASSERT (BackUpBuffer2
!= NULL
);
5034 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5036 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5037 ASSERT_EFI_ERROR(Status
);
5039 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5040 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
5041 ValueChanged
= TRUE
;
5044 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5045 ASSERT_EFI_ERROR(Status
);
5047 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5048 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
5049 ValueChanged
= TRUE
;
5053 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5054 if (BackUpBuffer
!= NULL
) {
5055 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5056 FreePool (BackUpBuffer
);
5059 if (BackUpBuffer2
!= NULL
) {
5060 FreePool (BackUpBuffer2
);
5063 Question
->ValueChanged
= ValueChanged
;
5065 return ValueChanged
;
5069 Initialize Question's Edit copy from Storage.
5071 @param Selection Selection contains the information about
5072 the Selection, form and formset to be displayed.
5073 Selection action may be updated in retrieve callback.
5074 If Selection is NULL, only initialize Question value.
5075 @param FormSet FormSet data structure.
5076 @param Form Form data structure.
5078 @retval EFI_SUCCESS The function completed successfully.
5083 IN OUT UI_MENU_SELECTION
*Selection
,
5084 IN FORM_BROWSER_FORMSET
*FormSet
,
5085 IN FORM_BROWSER_FORM
*Form
5090 FORM_BROWSER_STATEMENT
*Question
;
5092 Link
= GetFirstNode (&Form
->StatementListHead
);
5093 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5094 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5097 // Initialize local copy of Value for each Question
5099 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
5100 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5102 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5104 if (EFI_ERROR (Status
)) {
5108 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5109 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5112 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5119 Initialize Question's Edit copy from Storage for the whole Formset.
5121 @param Selection Selection contains the information about
5122 the Selection, form and formset to be displayed.
5123 Selection action may be updated in retrieve callback.
5124 If Selection is NULL, only initialize Question value.
5125 @param FormSet FormSet data structure.
5127 @retval EFI_SUCCESS The function completed successfully.
5132 IN OUT UI_MENU_SELECTION
*Selection
,
5133 IN FORM_BROWSER_FORMSET
*FormSet
5138 FORM_BROWSER_FORM
*Form
;
5140 Link
= GetFirstNode (&FormSet
->FormListHead
);
5141 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5142 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5145 // Initialize local copy of Value for each Form
5147 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5148 if (EFI_ERROR (Status
)) {
5152 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5156 // Finished question initialization.
5158 FormSet
->QuestionInited
= TRUE
;
5164 Remove the Request element from the Config Request.
5166 @param Storage Pointer to the browser storage.
5167 @param RequestElement The pointer to the Request element.
5172 IN OUT BROWSER_STORAGE
*Storage
,
5173 IN CHAR16
*RequestElement
5179 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5181 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5183 if (NewStr
== NULL
) {
5188 // Remove this element from this ConfigRequest.
5191 NewStr
+= StrLen (RequestElement
);
5192 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5194 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5198 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5200 @param Storage Pointer to the formset storage.
5201 @param ConfigRequest The pointer to the Request element.
5205 RemoveConfigRequest (
5206 FORMSET_STORAGE
*Storage
,
5207 CHAR16
*ConfigRequest
5210 CHAR16
*RequestElement
;
5211 CHAR16
*NextRequestElement
;
5215 // No request element in it, just return.
5217 if (ConfigRequest
== NULL
) {
5221 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5223 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5228 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5230 SearchKey
= L
"&OFFSET";
5234 // Find SearchKey storage
5236 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5237 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5238 ASSERT (RequestElement
!= NULL
);
5239 RequestElement
= StrStr (RequestElement
, SearchKey
);
5241 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5244 while (RequestElement
!= NULL
) {
5246 // +1 to avoid find header itself.
5248 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5251 // The last Request element in configRequest string.
5253 if (NextRequestElement
!= NULL
) {
5255 // Replace "&" with '\0'.
5257 *NextRequestElement
= L
'\0';
5260 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5262 if (NextRequestElement
!= NULL
) {
5264 // Restore '&' with '\0' for later used.
5266 *NextRequestElement
= L
'&';
5269 RequestElement
= NextRequestElement
;
5273 // If no request element remain, just remove the ConfigRequest string.
5275 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5276 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5277 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5278 Storage
->BrowserStorage
->SpareStrLen
= 0;
5283 Base on the current formset info, clean the ConfigRequest string in browser storage.
5285 @param FormSet Pointer of the FormSet
5289 CleanBrowserStorage (
5290 IN OUT FORM_BROWSER_FORMSET
*FormSet
5294 FORMSET_STORAGE
*Storage
;
5296 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5297 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5298 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5299 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5301 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5302 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5306 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5307 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5308 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5309 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5310 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5311 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5313 Storage
->BrowserStorage
->Initialized
= FALSE
;
5319 Check whether current element in the ConfigReqeust string.
5321 @param BrowserStorage Storage which includes ConfigReqeust.
5322 @param RequestElement New element need to check.
5324 @retval TRUE The Element is in the ConfigReqeust string.
5325 @retval FALSE The Element not in the configReqeust String.
5330 BROWSER_STORAGE
*BrowserStorage
,
5331 CHAR16
*RequestElement
5334 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5338 Append the Request element to the Config Request.
5340 @param ConfigRequest Current ConfigRequest info.
5341 @param SpareStrLen Current remain free buffer for config reqeust.
5342 @param RequestElement New Request element.
5346 AppendConfigRequest (
5347 IN OUT CHAR16
**ConfigRequest
,
5348 IN OUT UINTN
*SpareStrLen
,
5349 IN CHAR16
*RequestElement
5357 StrLength
= StrLen (RequestElement
);
5358 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5359 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5362 // Append <RequestElement> to <ConfigRequest>
5364 if (StrLength
> *SpareStrLen
) {
5366 // Old String buffer is not sufficient for RequestElement, allocate a new one
5368 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5369 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5370 ASSERT (NewStr
!= NULL
);
5372 if (*ConfigRequest
!= NULL
) {
5373 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5374 FreePool (*ConfigRequest
);
5376 *ConfigRequest
= NewStr
;
5377 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5380 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5381 *SpareStrLen
-= StrLength
;
5385 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5387 @param Storage Form set Storage.
5388 @param Request The input request string.
5389 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5391 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5392 @retval FALSE All elements covered by current used elements.
5396 ConfigRequestAdjust (
5397 IN BROWSER_STORAGE
*Storage
,
5399 IN BOOLEAN RespString
5402 CHAR16
*RequestElement
;
5403 CHAR16
*NextRequestElement
;
5404 CHAR16
*NextElementBakup
;
5408 CHAR16
*ConfigRequest
;
5411 NextElementBakup
= NULL
;
5414 if (Request
!= NULL
) {
5415 ConfigRequest
= Request
;
5417 ConfigRequest
= Storage
->ConfigRequest
;
5420 if (Storage
->ConfigRequest
== NULL
) {
5421 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5425 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5427 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5432 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5434 SearchKey
= L
"&OFFSET";
5435 ValueKey
= L
"&VALUE";
5439 // Find SearchKey storage
5441 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5442 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5443 ASSERT (RequestElement
!= NULL
);
5444 RequestElement
= StrStr (RequestElement
, SearchKey
);
5446 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5449 while (RequestElement
!= NULL
) {
5452 // +1 to avoid find header itself.
5454 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5457 // The last Request element in configRequest string.
5459 if (NextRequestElement
!= NULL
) {
5460 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5461 NextElementBakup
= NextRequestElement
;
5462 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5463 ASSERT (NextRequestElement
!= NULL
);
5466 // Replace "&" with '\0'.
5468 *NextRequestElement
= L
'\0';
5470 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5471 NextElementBakup
= NextRequestElement
;
5472 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5473 ASSERT (NextRequestElement
!= NULL
);
5475 // Replace "&" with '\0'.
5477 *NextRequestElement
= L
'\0';
5481 if (!ElementValidation (Storage
, RequestElement
)) {
5483 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5485 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5489 if (NextRequestElement
!= NULL
) {
5491 // Restore '&' with '\0' for later used.
5493 *NextRequestElement
= L
'&';
5496 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5497 RequestElement
= NextElementBakup
;
5499 RequestElement
= NextRequestElement
;
5507 Fill storage's edit copy with settings requested from Configuration Driver.
5509 @param FormSet FormSet data structure.
5510 @param Storage Buffer Storage.
5515 IN FORM_BROWSER_FORMSET
*FormSet
,
5516 IN FORMSET_STORAGE
*Storage
5520 EFI_STRING Progress
;
5523 EFI_STRING ConfigRequest
;
5526 ConfigRequest
= NULL
;
5528 switch (Storage
->BrowserStorage
->Type
) {
5529 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5532 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5533 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5534 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5539 case EFI_HII_VARSTORE_BUFFER
:
5540 case EFI_HII_VARSTORE_NAME_VALUE
:
5542 // Skip if there is no RequestElement.
5544 if (Storage
->ElementCount
== 0) {
5549 // Just update the ConfigRequest, if storage already initialized.
5551 if (Storage
->BrowserStorage
->Initialized
) {
5552 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5556 Storage
->BrowserStorage
->Initialized
= TRUE
;
5563 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5565 // Create the config request string to get all fields for this storage.
5566 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5567 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5569 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5570 ConfigRequest
= AllocateZeroPool (StrLen
);
5571 ASSERT (ConfigRequest
!= NULL
);
5575 L
"%s&OFFSET=0&WIDTH=%04x",
5577 Storage
->BrowserStorage
->Size
);
5579 ConfigRequest
= Storage
->ConfigRequest
;
5583 // Request current settings from Configuration Driver
5585 Status
= mHiiConfigRouting
->ExtractConfig (
5593 // If get value fail, extract default from IFR binary
5595 if (EFI_ERROR (Status
)) {
5596 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5599 // Convert Result from <ConfigAltResp> to <ConfigResp>
5601 StrPtr
= StrStr (Result
, L
"&GUID=");
5602 if (StrPtr
!= NULL
) {
5606 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5610 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5613 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5615 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5617 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5618 if (ConfigRequest
!= NULL
) {
5619 FreePool (ConfigRequest
);
5625 Get Value changed status from old question.
5627 @param NewFormSet FormSet data structure.
5628 @param OldQuestion Old question which has value changed.
5632 SyncStatusForQuestion (
5633 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5634 IN FORM_BROWSER_STATEMENT
*OldQuestion
5638 LIST_ENTRY
*QuestionLink
;
5639 FORM_BROWSER_FORM
*Form
;
5640 FORM_BROWSER_STATEMENT
*Question
;
5643 // For each form in one formset.
5645 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5646 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5647 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5648 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5651 // for each question in one form.
5653 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5654 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5655 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5656 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5658 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5659 Question
->ValueChanged
= TRUE
;
5667 Get Value changed status from old formset.
5669 @param NewFormSet FormSet data structure.
5670 @param OldFormSet FormSet data structure.
5674 SyncStatusForFormSet (
5675 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5676 IN FORM_BROWSER_FORMSET
*OldFormSet
5680 LIST_ENTRY
*QuestionLink
;
5681 FORM_BROWSER_FORM
*Form
;
5682 FORM_BROWSER_STATEMENT
*Question
;
5685 // For each form in one formset.
5687 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5688 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5689 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5690 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5693 // for each question in one form.
5695 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5696 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5697 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5698 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5700 if (!Question
->ValueChanged
) {
5705 // Find the same question in new formset and update the value changed flag.
5707 SyncStatusForQuestion (NewFormSet
, Question
);
5713 Get current setting of Questions.
5715 @param FormSet FormSet data structure.
5719 InitializeCurrentSetting (
5720 IN OUT FORM_BROWSER_FORMSET
*FormSet
5724 FORMSET_STORAGE
*Storage
;
5725 FORM_BROWSER_FORMSET
*OldFormSet
;
5728 // Try to find pre FormSet in the maintain backup list.
5729 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5731 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5732 if (OldFormSet
!= NULL
) {
5733 SyncStatusForFormSet (FormSet
, OldFormSet
);
5734 RemoveEntryList (&OldFormSet
->Link
);
5735 DestroyFormSet (OldFormSet
);
5737 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5740 // Extract default from IFR binary for no storage questions.
5742 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5745 // Request current settings from Configuration Driver
5747 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5748 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5749 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5751 LoadStorage (FormSet
, Storage
);
5753 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5759 Fetch the Ifr binary data of a FormSet.
5761 @param Handle PackageList Handle
5762 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5763 specified (NULL or zero GUID), take the first
5764 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5765 found in package list.
5766 On output, GUID of the formset found(if not NULL).
5767 @param BinaryLength The length of the FormSet IFR binary.
5768 @param BinaryData The buffer designed to receive the FormSet.
5770 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5771 BufferLength was updated.
5772 @retval EFI_INVALID_PARAMETER The handle is unknown.
5773 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5774 be found with the requested FormId.
5779 IN EFI_HII_HANDLE Handle
,
5780 IN OUT EFI_GUID
*FormSetGuid
,
5781 OUT UINTN
*BinaryLength
,
5782 OUT UINT8
**BinaryData
5786 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5792 UINT32 PackageListLength
;
5793 EFI_HII_PACKAGE_HEADER PackageHeader
;
5795 UINT8 NumberOfClassGuid
;
5796 BOOLEAN ClassGuidMatch
;
5797 EFI_GUID
*ClassGuid
;
5798 EFI_GUID
*ComparingGuid
;
5802 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5805 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5807 if (FormSetGuid
== NULL
) {
5808 ComparingGuid
= &gZeroGuid
;
5810 ComparingGuid
= FormSetGuid
;
5814 // Get HII PackageList
5817 HiiPackageList
= NULL
;
5818 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5819 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5820 HiiPackageList
= AllocatePool (BufferSize
);
5821 ASSERT (HiiPackageList
!= NULL
);
5823 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5825 if (EFI_ERROR (Status
)) {
5828 ASSERT (HiiPackageList
!= NULL
);
5831 // Get Form package from this HII package List
5833 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5835 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5837 ClassGuidMatch
= FALSE
;
5838 while (Offset
< PackageListLength
) {
5839 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5840 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5842 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5844 // Search FormSet in this Form Package
5846 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5847 while (Offset2
< PackageHeader
.Length
) {
5848 OpCodeData
= Package
+ Offset2
;
5850 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5852 // Try to compare against formset GUID
5854 if (IsZeroGuid (ComparingGuid
) ||
5855 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5859 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5861 // Try to compare against formset class GUID
5863 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5864 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5865 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5866 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5867 ClassGuidMatch
= TRUE
;
5871 if (ClassGuidMatch
) {
5874 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5875 ClassGuidMatch
= TRUE
;
5880 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5883 if (Offset2
< PackageHeader
.Length
) {
5885 // Target formset found
5891 Offset
+= PackageHeader
.Length
;
5894 if (Offset
>= PackageListLength
) {
5896 // Form package not found in this Package List
5898 FreePool (HiiPackageList
);
5899 return EFI_NOT_FOUND
;
5902 if (FormSetGuid
!= NULL
) {
5904 // Return the FormSet GUID
5906 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5910 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5911 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5912 // of the Form Package.
5914 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5915 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5917 FreePool (HiiPackageList
);
5919 if (*BinaryData
== NULL
) {
5920 return EFI_OUT_OF_RESOURCES
;
5928 Initialize the internal data structure of a FormSet.
5930 @param Handle PackageList Handle
5931 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5932 specified (NULL or zero GUID), take the first
5933 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5934 found in package list.
5935 On output, GUID of the formset found(if not NULL).
5936 @param FormSet FormSet data structure.
5938 @retval EFI_SUCCESS The function completed successfully.
5939 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5944 IN EFI_HII_HANDLE Handle
,
5945 IN OUT EFI_GUID
*FormSetGuid
,
5946 OUT FORM_BROWSER_FORMSET
*FormSet
5950 EFI_HANDLE DriverHandle
;
5952 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5953 if (EFI_ERROR (Status
)) {
5957 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5958 FormSet
->HiiHandle
= Handle
;
5959 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5960 FormSet
->QuestionInited
= FALSE
;
5963 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5965 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5966 if (EFI_ERROR (Status
)) {
5969 FormSet
->DriverHandle
= DriverHandle
;
5970 Status
= gBS
->HandleProtocol (
5972 &gEfiHiiConfigAccessProtocolGuid
,
5973 (VOID
**) &FormSet
->ConfigAccess
5975 if (EFI_ERROR (Status
)) {
5977 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5978 // list, then there will be no configuration action required
5980 FormSet
->ConfigAccess
= NULL
;
5984 // Parse the IFR binary OpCodes
5986 Status
= ParseOpCodes (FormSet
);
5993 Save globals used by previous call to SendForm(). SendForm() may be called from
5994 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5995 So, save globals of previous call to SendForm() and restore them upon exit.
5999 SaveBrowserContext (
6003 BROWSER_CONTEXT
*Context
;
6004 FORM_ENTRY_INFO
*MenuList
;
6005 FORM_BROWSER_FORMSET
*FormSet
;
6007 gBrowserContextCount
++;
6008 if (gBrowserContextCount
== 1) {
6010 // This is not reentry of SendForm(), no context to save
6015 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6016 ASSERT (Context
!= NULL
);
6018 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6021 // Save FormBrowser context
6023 Context
->Selection
= gCurrentSelection
;
6024 Context
->ResetRequired
= gResetRequiredFormLevel
;
6025 Context
->FlagReconnect
= gFlagReconnect
;
6026 Context
->CallbackReconnect
= gCallbackReconnect
;
6027 Context
->ExitRequired
= gExitRequired
;
6028 Context
->HiiHandle
= mCurrentHiiHandle
;
6029 Context
->FormId
= mCurrentFormId
;
6030 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6031 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6032 Context
->CurFakeQestId
= mCurFakeQestId
;
6033 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6034 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6037 // Save the menu history data.
6039 InitializeListHead(&Context
->FormHistoryList
);
6040 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6041 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6042 RemoveEntryList (&MenuList
->Link
);
6044 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
6048 // Save formset list.
6050 InitializeListHead(&Context
->FormSetList
);
6051 while (!IsListEmpty (&gBrowserFormSetList
)) {
6052 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6053 RemoveEntryList (&FormSet
->Link
);
6055 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
6059 // Insert to FormBrowser context list
6061 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6066 Restore globals used by previous call to SendForm().
6070 RestoreBrowserContext (
6075 BROWSER_CONTEXT
*Context
;
6076 FORM_ENTRY_INFO
*MenuList
;
6077 FORM_BROWSER_FORMSET
*FormSet
;
6079 ASSERT (gBrowserContextCount
!= 0);
6080 gBrowserContextCount
--;
6081 if (gBrowserContextCount
== 0) {
6083 // This is not reentry of SendForm(), no context to restore
6088 ASSERT (!IsListEmpty (&gBrowserContextList
));
6090 Link
= GetFirstNode (&gBrowserContextList
);
6091 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6094 // Restore FormBrowser context
6096 gCurrentSelection
= Context
->Selection
;
6097 gResetRequiredFormLevel
= Context
->ResetRequired
;
6098 gFlagReconnect
= Context
->FlagReconnect
;
6099 gCallbackReconnect
= Context
->CallbackReconnect
;
6100 gExitRequired
= Context
->ExitRequired
;
6101 mCurrentHiiHandle
= Context
->HiiHandle
;
6102 mCurrentFormId
= Context
->FormId
;
6103 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6104 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6105 mCurFakeQestId
= Context
->CurFakeQestId
;
6106 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6107 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6110 // Restore the menu history data.
6112 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6113 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6114 RemoveEntryList (&MenuList
->Link
);
6116 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6120 // Restore the Formset data.
6122 while (!IsListEmpty (&Context
->FormSetList
)) {
6123 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6124 RemoveEntryList (&FormSet
->Link
);
6126 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6130 // Remove from FormBrowser context list
6132 RemoveEntryList (&Context
->Link
);
6133 gBS
->FreePool (Context
);
6137 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6139 @param Handle The Hii Handle.
6141 @return the found FormSet context. If no found, NULL will return.
6144 FORM_BROWSER_FORMSET
*
6145 GetFormSetFromHiiHandle (
6146 EFI_HII_HANDLE Handle
6150 FORM_BROWSER_FORMSET
*FormSet
;
6152 Link
= GetFirstNode (&gBrowserFormSetList
);
6153 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6154 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6155 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6156 if (!ValidateFormSet(FormSet
)) {
6159 if (FormSet
->HiiHandle
== Handle
) {
6168 Check whether the input HII handle is the FormSet that is being used.
6170 @param Handle The Hii Handle.
6172 @retval TRUE HII handle is being used.
6173 @retval FALSE HII handle is not being used.
6177 IsHiiHandleInBrowserContext (
6178 EFI_HII_HANDLE Handle
6182 BROWSER_CONTEXT
*Context
;
6185 // HiiHandle is Current FormSet.
6187 if (mCurrentHiiHandle
== Handle
) {
6192 // Check whether HiiHandle is in BrowserContext.
6194 Link
= GetFirstNode (&gBrowserContextList
);
6195 while (!IsNull (&gBrowserContextList
, Link
)) {
6196 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6197 if (Context
->HiiHandle
== Handle
) {
6199 // HiiHandle is in BrowserContext
6203 Link
= GetNextNode (&gBrowserContextList
, Link
);
6210 Perform Password check.
6211 Passwork may be encrypted by driver that requires the specific check.
6213 @param Form Form where Password Statement is in.
6214 @param Statement Password statement
6215 @param PasswordString Password string to be checked. It may be NULL.
6216 NULL means to restore password.
6217 "" string can be used to checked whether old password does exist.
6219 @return Status Status of Password check.
6224 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6225 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6226 IN EFI_STRING PasswordString OPTIONAL
6230 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6231 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6232 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6233 FORM_BROWSER_STATEMENT
*Question
;
6235 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6236 Question
= GetBrowserStatement(Statement
);
6237 ASSERT (Question
!= NULL
);
6239 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6240 if (ConfigAccess
== NULL
) {
6241 return EFI_UNSUPPORTED
;
6245 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6247 return EFI_UNSUPPORTED
;
6251 // Prepare password string in HII database
6253 if (PasswordString
!= NULL
) {
6254 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6256 IfrTypeValue
.string
= 0;
6260 // Send password to Configuration Driver for validation
6262 Status
= ConfigAccess
->Callback (
6264 EFI_BROWSER_ACTION_CHANGING
,
6265 Question
->QuestionId
,
6266 Question
->HiiValue
.Type
,
6272 // Remove password string from HII database
6274 if (PasswordString
!= NULL
) {
6275 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6282 Find the registered HotKey based on KeyData.
6284 @param[in] KeyData A pointer to a buffer that describes the keystroke
6285 information for the hot key.
6287 @return The registered HotKey context. If no found, NULL will return.
6290 GetHotKeyFromRegisterList (
6291 IN EFI_INPUT_KEY
*KeyData
6295 BROWSER_HOT_KEY
*HotKey
;
6297 Link
= GetFirstNode (&gBrowserHotKeyList
);
6298 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6299 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6300 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6303 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6310 Configure what scope the hot key will impact.
6311 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6312 If no scope is set, the default scope will be FormSet level.
6313 After all registered hot keys are removed, previous Scope can reset to another level.
6315 @param[in] Scope Scope level to be set.
6317 @retval EFI_SUCCESS Scope is set correctly.
6318 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6319 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6325 IN BROWSER_SETTING_SCOPE Scope
6328 if (Scope
>= MaxLevel
) {
6329 return EFI_INVALID_PARAMETER
;
6333 // When no hot key registered in system or on the first setting,
6334 // Scope can be set.
6336 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6337 gBrowserSettingScope
= Scope
;
6338 mBrowserScopeFirstSet
= FALSE
;
6339 } else if (Scope
!= gBrowserSettingScope
) {
6340 return EFI_UNSUPPORTED
;
6347 Register the hot key with its browser action, or unregistered the hot key.
6348 Only support hot key that is not printable character (control key, function key, etc.).
6349 If the action value is zero, the hot key will be unregistered if it has been registered.
6350 If the same hot key has been registered, the new action and help string will override the previous ones.
6352 @param[in] KeyData A pointer to a buffer that describes the keystroke
6353 information for the hot key. Its type is EFI_INPUT_KEY to
6354 be supported by all ConsoleIn devices.
6355 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6356 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6357 @param[in] HelpString Help string that describes the hot key information.
6358 Its value may be NULL for the unregistered hot key.
6360 @retval EFI_SUCCESS Hot key is registered or unregistered.
6361 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6362 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6363 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6364 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6369 IN EFI_INPUT_KEY
*KeyData
,
6371 IN UINT16 DefaultId
,
6372 IN EFI_STRING HelpString OPTIONAL
6375 BROWSER_HOT_KEY
*HotKey
;
6378 // Check input parameters.
6380 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6381 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6382 return EFI_INVALID_PARAMETER
;
6386 // Check whether the input KeyData is in BrowserHotKeyList.
6388 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6391 // Unregister HotKey
6393 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6394 if (HotKey
!= NULL
) {
6396 // The registered HotKey is found.
6397 // Remove it from List, and free its resource.
6399 RemoveEntryList (&HotKey
->Link
);
6400 FreePool (HotKey
->KeyData
);
6401 FreePool (HotKey
->HelpString
);
6405 // The registered HotKey is not found.
6407 return EFI_NOT_FOUND
;
6411 if (HotKey
!= NULL
) {
6412 return EFI_ALREADY_STARTED
;
6416 // Create new Key, and add it into List.
6418 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6419 ASSERT (HotKey
!= NULL
);
6420 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6421 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6422 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6425 // Fill HotKey information.
6427 HotKey
->Action
= Action
;
6428 HotKey
->DefaultId
= DefaultId
;
6429 if (HotKey
->HelpString
!= NULL
) {
6430 FreePool (HotKey
->HelpString
);
6432 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6438 Register Exit handler function.
6439 When more than one handler function is registered, the latter one will override the previous one.
6440 When NULL handler is specified, the previous Exit handler will be unregistered.
6442 @param[in] Handler Pointer to handler function.
6447 RegiserExitHandler (
6448 IN EXIT_HANDLER Handler
6451 ExitHandlerFunction
= Handler
;
6456 Check whether the browser data has been modified.
6458 @retval TRUE Browser data is modified.
6459 @retval FALSE No browser data is modified.
6464 IsBrowserDataModified (
6469 FORM_BROWSER_FORMSET
*FormSet
;
6471 switch (gBrowserSettingScope
) {
6473 if (gCurrentSelection
== NULL
) {
6476 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6479 if (gCurrentSelection
== NULL
) {
6482 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6485 Link
= GetFirstNode (&gBrowserFormSetList
);
6486 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6487 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6488 if (!ValidateFormSet(FormSet
)) {
6492 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6495 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6505 Execute the action requested by the Action parameter.
6507 @param[in] Action Execute the request action.
6508 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6510 @retval EFI_SUCCESS Execute the request action succss.
6511 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6522 FORM_BROWSER_FORMSET
*FormSet
;
6523 FORM_BROWSER_FORM
*Form
;
6525 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6526 return EFI_NOT_READY
;
6529 Status
= EFI_SUCCESS
;
6532 if (gBrowserSettingScope
< SystemLevel
) {
6533 FormSet
= gCurrentSelection
->FormSet
;
6534 Form
= gCurrentSelection
->Form
;
6538 // Executet the discard action.
6540 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6541 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6542 if (EFI_ERROR (Status
)) {
6548 // Executet the difault action.
6550 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6551 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6552 if (EFI_ERROR (Status
)) {
6555 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6559 // Executet the submit action.
6561 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6562 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6563 if (EFI_ERROR (Status
)) {
6569 // Executet the reset action.
6571 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6572 gResetRequiredFormLevel
= TRUE
;
6573 gResetRequiredSystemLevel
= TRUE
;
6577 // Executet the exit action.
6579 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6580 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6581 if (gBrowserSettingScope
== SystemLevel
) {
6582 if (ExitHandlerFunction
!= NULL
) {
6583 ExitHandlerFunction ();
6587 gExitRequired
= TRUE
;
6594 Create reminder to let user to choose save or discard the changed browser data.
6595 Caller can use it to actively check the changed browser data.
6597 @retval BROWSER_NO_CHANGES No browser data is changed.
6598 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6599 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6600 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6610 FORM_BROWSER_FORMSET
*FormSet
;
6611 BOOLEAN IsDataChanged
;
6612 UINT32 DataSavedAction
;
6615 DataSavedAction
= BROWSER_NO_CHANGES
;
6616 IsDataChanged
= FALSE
;
6617 Link
= GetFirstNode (&gBrowserFormSetList
);
6618 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6619 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6620 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6621 if (!ValidateFormSet(FormSet
)) {
6624 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6625 IsDataChanged
= TRUE
;
6631 // No data is changed. No save is required.
6633 if (!IsDataChanged
) {
6634 return DataSavedAction
;
6638 // If data is changed, prompt user to save or discard it.
6641 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6643 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6644 SubmitForm (NULL
, NULL
, SystemLevel
);
6645 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6647 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6648 DiscardForm (NULL
, NULL
, SystemLevel
);
6649 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6651 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6652 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6657 return DataSavedAction
;
6661 Check whether the Reset Required for the browser
6663 @retval TRUE Browser required to reset after exit.
6664 @retval FALSE Browser not need to reset after exit.
6673 return gResetRequiredSystemLevel
;