2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 SETUP_DRIVER_PRIVATE_DATA mPrivateData
= {
18 SETUP_DRIVER_SIGNATURE
,
31 BROWSER_EXTENSION2_VERSION_1_1
,
35 IsBrowserDataModified
,
43 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
44 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
45 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
46 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
48 UINTN gBrowserContextCount
= 0;
49 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
50 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
51 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
52 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
53 LIST_ENTRY gBrowserSaveFailFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList
);
55 BOOLEAN mSystemSubmit
= FALSE
;
56 BOOLEAN gResetRequiredFormLevel
;
57 BOOLEAN gResetRequiredSystemLevel
= FALSE
;
58 BOOLEAN gExitRequired
;
59 BOOLEAN gFlagReconnect
;
60 BOOLEAN gCallbackReconnect
;
61 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
62 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
63 EXIT_HANDLER ExitHandlerFunction
= NULL
;
64 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
67 // Browser Global Strings
70 CHAR16
*mUnknownString
= L
"!";
72 extern EFI_GUID mCurrentFormSetGuid
;
73 extern EFI_HII_HANDLE mCurrentHiiHandle
;
74 extern UINT16 mCurrentFormId
;
75 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
78 Create a menu with specified formset GUID and form ID, and add it as a child
79 of the given parent menu.
81 @param HiiHandle Hii handle related to this formset.
82 @param FormSetGuid The Formset Guid of menu to be added.
83 @param FormId The Form ID of menu to be added.
84 @param QuestionId The question id of this menu to be added.
86 @return A pointer to the newly added menu or NULL if memory is insufficient.
91 IN EFI_HII_HANDLE HiiHandle
,
92 IN EFI_GUID
*FormSetGuid
,
97 FORM_ENTRY_INFO
*MenuList
;
99 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
100 if (MenuList
== NULL
) {
104 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
106 MenuList
->HiiHandle
= HiiHandle
;
107 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
108 MenuList
->FormId
= FormId
;
109 MenuList
->QuestionId
= QuestionId
;
112 // If parent is not specified, it is the root Form of a Formset
114 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
120 Return the form id for the input hiihandle and formset.
122 @param HiiHandle HiiHandle for FormSet.
123 @param FormSetGuid The Formset GUID of the menu to search.
125 @return First form's id for this form set.
130 IN EFI_HII_HANDLE HiiHandle
,
131 IN EFI_GUID
*FormSetGuid
135 FORM_BROWSER_FORM
*Form
;
137 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
138 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
144 Search Menu with given FormSetGuid and FormId in all cached menu list.
146 @param HiiHandle HiiHandle for FormSet.
147 @param FormSetGuid The Formset GUID of the menu to search.
148 @param FormId The Form ID of menu to search.
150 @return A pointer to menu found or NULL if not found.
155 IN EFI_HII_HANDLE HiiHandle
,
156 IN EFI_GUID
*FormSetGuid
,
161 FORM_ENTRY_INFO
*MenuList
;
162 FORM_ENTRY_INFO
*RetMenu
;
163 EFI_FORM_ID FirstFormId
;
167 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
168 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
169 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
170 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
173 // If already find the menu, free the menus behind it.
175 if (RetMenu
!= NULL
) {
176 RemoveEntryList (&MenuList
->Link
);
182 // Find the same FromSet.
184 if (MenuList
->HiiHandle
== HiiHandle
) {
185 if (IsZeroGuid (&MenuList
->FormSetGuid
)) {
187 // FormSetGuid is not specified.
190 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
191 if (MenuList
->FormId
== FormId
) {
193 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
194 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
195 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
207 Find parent menu for current menu.
209 @param CurrentMenu Current Menu
210 @param SettingLevel Whether find parent menu in Form Level or Formset level.
211 In form level, just find the parent menu;
212 In formset level, find the parent menu which has different
215 @retval The parent menu for current menu.
219 IN FORM_ENTRY_INFO
*CurrentMenu
,
220 IN BROWSER_SETTING_SCOPE SettingLevel
223 FORM_ENTRY_INFO
*ParentMenu
;
226 ASSERT (SettingLevel
== FormLevel
|| SettingLevel
== FormSetLevel
);
228 if (CurrentMenu
== NULL
) {
233 Link
= &CurrentMenu
->Link
;
235 while (Link
->BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
236 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (Link
->BackLink
);
238 if (SettingLevel
== FormLevel
) {
240 // For FormLevel, just find the parent menu, return.
245 if (!CompareGuid (&CurrentMenu
->FormSetGuid
, &ParentMenu
->FormSetGuid
)) {
247 // For SystemLevel, must find the menu which has different formset.
252 Link
= Link
->BackLink
;
256 // Not find the parent menu, just return NULL.
258 if (Link
->BackLink
== &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
266 Free Menu list linked list.
268 @param MenuListHead One Menu list point in the menu list.
273 LIST_ENTRY
*MenuListHead
276 FORM_ENTRY_INFO
*MenuList
;
278 while (!IsListEmpty (MenuListHead
)) {
279 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
280 RemoveEntryList (&MenuList
->Link
);
287 Copy current Menu list to the new menu list.
289 @param NewMenuListHead New create Menu list.
290 @param CurrentMenuListHead Current Menu list.
295 OUT LIST_ENTRY
*NewMenuListHead
,
296 IN LIST_ENTRY
*CurrentMenuListHead
300 FORM_ENTRY_INFO
*MenuList
;
301 FORM_ENTRY_INFO
*NewMenuEntry
;
304 // If new menu list not empty, free it first.
306 UiFreeMenuList (NewMenuListHead
);
308 Link
= GetFirstNode (CurrentMenuListHead
);
309 while (!IsNull (CurrentMenuListHead
, Link
)) {
310 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
311 Link
= GetNextNode (CurrentMenuListHead
, Link
);
313 NewMenuEntry
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
314 ASSERT (NewMenuEntry
!= NULL
);
315 NewMenuEntry
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
316 NewMenuEntry
->HiiHandle
= MenuList
->HiiHandle
;
317 CopyMem (&NewMenuEntry
->FormSetGuid
, &MenuList
->FormSetGuid
, sizeof (EFI_GUID
));
318 NewMenuEntry
->FormId
= MenuList
->FormId
;
319 NewMenuEntry
->QuestionId
= MenuList
->QuestionId
;
321 InsertTailList (NewMenuListHead
, &NewMenuEntry
->Link
);
326 Load all hii formset to the browser.
334 FORM_BROWSER_FORMSET
*LocalFormSet
;
335 EFI_HII_HANDLE
*HiiHandles
;
339 FORM_BROWSER_FORMSET
*OldFormset
;
341 OldFormset
= mSystemLevelFormSet
;
344 // Get all the Hii handles
346 HiiHandles
= HiiGetHiiHandles (NULL
);
347 ASSERT (HiiHandles
!= NULL
);
350 // Search for formset of each class type
352 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
354 // Check HiiHandles[Index] does exist in global maintain list.
356 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
361 // Initilize FormSet Setting
363 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
364 ASSERT (LocalFormSet
!= NULL
);
365 mSystemLevelFormSet
= LocalFormSet
;
367 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
368 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
369 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
370 DestroyFormSet (LocalFormSet
);
373 InitializeCurrentSetting (LocalFormSet
);
376 // Initilize Questions' Value
378 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
379 if (EFI_ERROR (Status
)) {
380 DestroyFormSet (LocalFormSet
);
386 // Free resources, and restore gOldFormSet and gClassOfVfr
388 FreePool (HiiHandles
);
390 mSystemLevelFormSet
= OldFormset
;
394 Pop up the error info.
396 @param BrowserStatus The input browser status.
397 @param HiiHandle The Hiihandle for this opcode.
398 @param OpCode The opcode use to get the erro info and timeout value.
399 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
404 IN UINT32 BrowserStatus
,
405 IN EFI_HII_HANDLE HiiHandle
,
406 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
407 IN CHAR16
*ErrorString
410 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
411 USER_INPUT UserInputData
;
415 if (OpCode
!= NULL
) {
416 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
417 ASSERT (Statement
!= NULL
);
418 Statement
->OpCode
= OpCode
;
419 gDisplayFormData
.HighLightedStatement
= Statement
;
423 // Used to compatible with old display engine.
424 // New display engine not use this field.
426 gDisplayFormData
.ErrorString
= ErrorString
;
427 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
429 if (HiiHandle
!= NULL
) {
430 gDisplayFormData
.HiiHandle
= HiiHandle
;
433 mFormDisplay
->FormDisplay (&gDisplayFormData
, &UserInputData
);
435 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
436 gDisplayFormData
.ErrorString
= NULL
;
438 if (OpCode
!= NULL
) {
439 FreePool (Statement
);
442 return UserInputData
.Action
;
446 This is the routine which an external caller uses to direct the browser
447 where to obtain it's information.
450 @param This The Form Browser protocol instanse.
451 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
452 display a list of the formsets for the handles specified.
453 @param HandleCount The number of Handles specified in Handle.
454 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
455 field in the EFI_IFR_FORM_SET op-code for the specified
456 forms-based package. If FormSetGuid is NULL, then this
457 function will display the first found forms package.
458 @param FormId This field specifies which EFI_IFR_FORM to render as the first
459 displayable page. If this field has a value of 0x0000, then
460 the forms browser will render the specified forms in their encoded order.
461 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
463 @param ActionRequest Points to the action recommended by the form.
465 @retval EFI_SUCCESS The function completed successfully.
466 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
467 @retval EFI_NOT_FOUND No valid forms could be found to display.
473 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
474 IN EFI_HII_HANDLE
*Handles
,
475 IN UINTN HandleCount
,
476 IN EFI_GUID
*FormSetGuid
, OPTIONAL
477 IN UINT16 FormId
, OPTIONAL
478 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
479 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
483 UI_MENU_SELECTION
*Selection
;
485 FORM_BROWSER_FORMSET
*FormSet
;
486 FORM_ENTRY_INFO
*MenuList
;
490 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
492 if (mFormDisplay
== NULL
) {
493 DEBUG ((DEBUG_ERROR
, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));
494 return EFI_UNSUPPORTED
;
498 // Save globals used by SendForm()
500 SaveBrowserContext ();
502 gFlagReconnect
= FALSE
;
503 gResetRequiredFormLevel
= FALSE
;
504 gExitRequired
= FALSE
;
505 gCallbackReconnect
= FALSE
;
506 Status
= EFI_SUCCESS
;
508 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
510 for (Index
= 0; Index
< HandleCount
; Index
++) {
511 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
512 ASSERT (Selection
!= NULL
);
514 Selection
->Handle
= Handles
[Index
];
515 if (FormSetGuid
!= NULL
) {
516 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
517 Selection
->FormId
= FormId
;
519 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
523 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
524 ASSERT (FormSet
!= NULL
);
527 // Validate the HiiHandle
528 // if validate failed, find the first validate parent HiiHandle.
530 if (!ValidateHiiHandle(Selection
->Handle
)) {
531 FindNextMenu (Selection
, FormSetLevel
);
535 // Initialize internal data structures of FormSet
537 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
538 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
539 DestroyFormSet (FormSet
);
542 Selection
->FormSet
= FormSet
;
543 mSystemLevelFormSet
= FormSet
;
546 // Display this formset
548 gCurrentSelection
= Selection
;
550 Status
= SetupBrowser (Selection
);
552 gCurrentSelection
= NULL
;
553 mSystemLevelFormSet
= NULL
;
555 if (gFlagReconnect
|| gCallbackReconnect
) {
556 RetVal
= ReconnectController (FormSet
->DriverHandle
);
558 PopupErrorMessage(BROWSER_RECONNECT_FAIL
, NULL
, NULL
, NULL
);
560 gFlagReconnect
= FALSE
;
561 gCallbackReconnect
= FALSE
;
565 // If no data is changed, don't need to save current FormSet into the maintain list.
567 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
568 CleanBrowserStorage(FormSet
);
569 RemoveEntryList (&FormSet
->Link
);
570 DestroyFormSet (FormSet
);
573 if (EFI_ERROR (Status
)) {
576 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
578 FreePool (Selection
);
581 if (ActionRequest
!= NULL
) {
582 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
583 if (gResetRequiredFormLevel
) {
584 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
588 mFormDisplay
->ExitDisplay();
591 // Clear the menu history data.
593 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
594 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
595 RemoveEntryList (&MenuList
->Link
);
600 // Restore globals used by SendForm()
602 RestoreBrowserContext ();
608 Get or set data to the storage.
610 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
611 @param ResultsData A string returned from an IFR browser or
612 equivalent. The results string will have no
613 routing information in them.
614 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
615 (if RetrieveData = TRUE) data from the uncommitted
616 browser state information or set (if RetrieveData
617 = FALSE) data in the uncommitted browser state
619 @param Storage The pointer to the storage.
621 @retval EFI_SUCCESS The results have been distributed or are awaiting
627 IN OUT UINTN
*ResultsDataSize
,
628 IN OUT EFI_STRING
*ResultsData
,
629 IN BOOLEAN RetrieveData
,
630 IN BROWSER_STORAGE
*Storage
639 FORMSET_STORAGE
*BrowserStorage
;
643 // Generate <ConfigResp>
645 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
646 if (EFI_ERROR (Status
)) {
651 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
652 // Also need to consider add "\0" at first time.
654 StrPtr
= StrStr (ConfigResp
, L
"PATH");
655 ASSERT (StrPtr
!= NULL
);
656 StrPtr
= StrStr (StrPtr
, L
"&");
658 BufferSize
= StrSize (StrPtr
);
661 // Copy the data if the input buffer is bigger enough.
663 if (*ResultsDataSize
>= BufferSize
) {
664 StrCpyS (*ResultsData
, *ResultsDataSize
/ sizeof (CHAR16
), StrPtr
);
667 *ResultsDataSize
= BufferSize
;
668 FreePool (ConfigResp
);
671 // Prepare <ConfigResp>
673 BrowserStorage
= GetFstStgFromBrsStg (Storage
);
674 ASSERT (BrowserStorage
!= NULL
);
675 TmpSize
= StrLen (*ResultsData
);
676 BufferSize
= (TmpSize
+ StrLen (BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
677 MaxLen
= BufferSize
/ sizeof (CHAR16
);
678 ConfigResp
= AllocateZeroPool (BufferSize
);
679 ASSERT (ConfigResp
!= NULL
);
681 StrCpyS (ConfigResp
, MaxLen
, BrowserStorage
->ConfigHdr
);
682 StrCatS (ConfigResp
, MaxLen
, L
"&");
683 StrCatS (ConfigResp
, MaxLen
, *ResultsData
);
686 // Update Browser uncommited data
688 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
689 FreePool (ConfigResp
);
690 if (EFI_ERROR (Status
)) {
699 This routine called this service in the browser to retrieve or set certain uncommitted
700 state information that resides in the open formsets.
702 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
704 @param ResultsDataSize A pointer to the size of the buffer associated
706 @param ResultsData A string returned from an IFR browser or
707 equivalent. The results string will have no
708 routing information in them.
709 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
710 (if RetrieveData = TRUE) data from the uncommitted
711 browser state information or set (if RetrieveData
712 = FALSE) data in the uncommitted browser state
714 @param VariableGuid An optional field to indicate the target variable
716 @param VariableName An optional field to indicate the target
717 human-readable variable name.
719 @retval EFI_SUCCESS The results have been distributed or are awaiting
721 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
722 contain the results data.
728 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
729 IN OUT UINTN
*ResultsDataSize
,
730 IN OUT EFI_STRING ResultsData
,
731 IN BOOLEAN RetrieveData
,
732 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
733 IN CONST CHAR16
*VariableName OPTIONAL
738 BROWSER_STORAGE
*Storage
;
739 FORMSET_STORAGE
*FormsetStorage
;
743 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
744 return EFI_INVALID_PARAMETER
;
747 TotalSize
= *ResultsDataSize
;
750 Status
= EFI_SUCCESS
;
752 if (VariableGuid
!= NULL
) {
754 // Try to find target storage in the current formset.
756 Link
= GetFirstNode (&gBrowserStorageList
);
757 while (!IsNull (&gBrowserStorageList
, Link
)) {
758 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
759 Link
= GetNextNode (&gBrowserStorageList
, Link
);
761 // Check the current storage.
763 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
767 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
768 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
770 // Buffer storage require both GUID and Name
772 if (VariableName
== NULL
) {
773 return EFI_NOT_FOUND
;
776 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
781 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
782 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
783 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
784 return EFI_NOT_FOUND
;
787 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
792 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
793 if (EFI_ERROR (Status
)) {
797 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
798 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
802 // Different formsets may have same varstore, so here just set the flag
803 // not exit the circle.
810 return EFI_NOT_FOUND
;
814 // GUID/Name is not specified, take the first storage in FormSet
816 if (mSystemLevelFormSet
== NULL
) {
817 return EFI_NOT_READY
;
821 // Generate <ConfigResp>
823 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
824 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
825 return EFI_UNSUPPORTED
;
828 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
830 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
831 if (EFI_ERROR (Status
)) {
837 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
838 *ResultsDataSize
= TotalSize
;
847 Callback function for SimpleTextInEx protocol install events
849 @param Event the event that is signaled.
850 @param Context not used here.
855 FormDisplayCallback (
860 if (mFormDisplay
!= NULL
) {
864 gBS
->LocateProtocol (
865 &gEdkiiFormDisplayEngineProtocolGuid
,
867 (VOID
**) &mFormDisplay
872 Initialize Setup Browser driver.
874 @param ImageHandle The image handle.
875 @param SystemTable The system table.
877 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
878 @return Other value if failed to initialize the Setup Browser module.
884 IN EFI_HANDLE ImageHandle
,
885 IN EFI_SYSTEM_TABLE
*SystemTable
892 // Locate required Hii relative protocols
894 Status
= gBS
->LocateProtocol (
895 &gEfiHiiDatabaseProtocolGuid
,
897 (VOID
**) &mHiiDatabase
899 ASSERT_EFI_ERROR (Status
);
901 Status
= gBS
->LocateProtocol (
902 &gEfiHiiConfigRoutingProtocolGuid
,
904 (VOID
**) &mHiiConfigRouting
906 ASSERT_EFI_ERROR (Status
);
908 Status
= gBS
->LocateProtocol (
909 &gEfiDevicePathFromTextProtocolGuid
,
911 (VOID
**) &mPathFromText
915 // Install FormBrowser2 protocol
917 mPrivateData
.Handle
= NULL
;
918 Status
= gBS
->InstallProtocolInterface (
919 &mPrivateData
.Handle
,
920 &gEfiFormBrowser2ProtocolGuid
,
921 EFI_NATIVE_INTERFACE
,
922 &mPrivateData
.FormBrowser2
924 ASSERT_EFI_ERROR (Status
);
927 // Install FormBrowserEx2 protocol
929 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
930 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
931 mPrivateData
.Handle
= NULL
;
932 Status
= gBS
->InstallProtocolInterface (
933 &mPrivateData
.Handle
,
934 &gEdkiiFormBrowserEx2ProtocolGuid
,
935 EFI_NATIVE_INTERFACE
,
936 &mPrivateData
.FormBrowserEx2
938 ASSERT_EFI_ERROR (Status
);
940 Status
= gBS
->InstallProtocolInterface (
941 &mPrivateData
.Handle
,
942 &gEdkiiFormBrowserExProtocolGuid
,
943 EFI_NATIVE_INTERFACE
,
944 &mPrivateData
.FormBrowserEx
946 ASSERT_EFI_ERROR (Status
);
948 InitializeDisplayFormData ();
950 Status
= gBS
->LocateProtocol (
951 &gEdkiiFormDisplayEngineProtocolGuid
,
953 (VOID
**) &mFormDisplay
956 if (EFI_ERROR (Status
)) {
957 EfiCreateProtocolNotifyEvent (
958 &gEdkiiFormDisplayEngineProtocolGuid
,
971 Create a new string in HII Package List.
973 @param String The String to be added
974 @param HiiHandle The package list in the HII database to insert the
977 @return The output string.
983 IN EFI_HII_HANDLE HiiHandle
986 EFI_STRING_ID StringId
;
988 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
989 ASSERT (StringId
!= 0);
996 Delete a string from HII Package List.
998 @param StringId Id of the string in HII database.
999 @param HiiHandle The HII package list handle.
1001 @retval EFI_SUCCESS The string was deleted successfully.
1006 IN EFI_STRING_ID StringId
,
1007 IN EFI_HII_HANDLE HiiHandle
1012 NullChar
= CHAR_NULL
;
1013 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
1019 Get the string based on the StringId and HII Package List Handle.
1021 @param Token The String's ID.
1022 @param HiiHandle The package list in the HII database to search for
1023 the specified string.
1025 @return The output string.
1030 IN EFI_STRING_ID Token
,
1031 IN EFI_HII_HANDLE HiiHandle
1036 if (HiiHandle
== NULL
) {
1040 String
= HiiGetString (HiiHandle
, Token
, NULL
);
1041 if (String
== NULL
) {
1042 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
1043 ASSERT (String
!= NULL
);
1045 return (CHAR16
*) String
;
1050 Allocate new memory and then copy the Unicode string Source to Destination.
1052 @param Dest Location to copy string
1053 @param Src String to copy
1058 IN OUT CHAR16
**Dest
,
1062 if (*Dest
!= NULL
) {
1065 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
1066 ASSERT (*Dest
!= NULL
);
1071 Allocate new memory and concatinate Source on the end of Destination.
1073 @param Dest String to added to the end of.
1074 @param Src String to concatinate.
1079 IN OUT CHAR16
**Dest
,
1086 if (*Dest
== NULL
) {
1087 NewStringCpy (Dest
, Src
);
1091 MaxLen
= ( StrSize (*Dest
) + StrSize (Src
) - 1) / sizeof (CHAR16
);
1092 NewString
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1093 ASSERT (NewString
!= NULL
);
1095 StrCpyS (NewString
, MaxLen
, *Dest
);
1096 StrCatS (NewString
, MaxLen
, Src
);
1103 Get Value for given Name from a NameValue Storage.
1105 @param Storage The NameValue Storage.
1106 @param Name The Name.
1107 @param Value The retured Value.
1108 @param GetValueFrom Where to get source value, from EditValue or Value.
1110 @retval EFI_SUCCESS Value found for given Name.
1111 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1116 IN BROWSER_STORAGE
*Storage
,
1118 IN OUT CHAR16
**Value
,
1119 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1123 NAME_VALUE_NODE
*Node
;
1125 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1126 return EFI_INVALID_PARAMETER
;
1131 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1132 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1133 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1135 if (StrCmp (Name
, Node
->Name
) == 0) {
1136 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1137 NewStringCpy (Value
, Node
->EditValue
);
1139 NewStringCpy (Value
, Node
->Value
);
1144 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1147 return EFI_NOT_FOUND
;
1152 Set Value of given Name in a NameValue Storage.
1154 @param Storage The NameValue Storage.
1155 @param Name The Name.
1156 @param Value The Value to set.
1157 @param SetValueTo Whether update editValue or Value.
1158 @param ReturnNode The node use the input name.
1160 @retval EFI_SUCCESS Value found for given Name.
1161 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1166 IN BROWSER_STORAGE
*Storage
,
1169 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1170 OUT NAME_VALUE_NODE
**ReturnNode
1174 NAME_VALUE_NODE
*Node
;
1177 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1178 return EFI_INVALID_PARAMETER
;
1181 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1182 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1183 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1185 if (StrCmp (Name
, Node
->Name
) == 0) {
1186 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1187 Buffer
= Node
->EditValue
;
1189 Buffer
= Node
->Value
;
1191 if (Buffer
!= NULL
) {
1194 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1195 ASSERT (Buffer
!= NULL
);
1196 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1197 Node
->EditValue
= Buffer
;
1199 Node
->Value
= Buffer
;
1202 if (ReturnNode
!= NULL
) {
1209 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1212 return EFI_NOT_FOUND
;
1217 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1219 @param Storage The Storage to be conveted.
1220 @param ConfigResp The returned <ConfigResp>.
1221 @param ConfigRequest The ConfigRequest string.
1222 @param GetEditBuf Get the data from editbuffer or buffer.
1224 @retval EFI_SUCCESS Convert success.
1225 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1229 StorageToConfigResp (
1230 IN BROWSER_STORAGE
*Storage
,
1231 IN CHAR16
**ConfigResp
,
1232 IN CHAR16
*ConfigRequest
,
1233 IN BOOLEAN GetEditBuf
1237 EFI_STRING Progress
;
1239 NAME_VALUE_NODE
*Node
;
1241 FORMSET_STORAGE
*FormsetStorage
;
1243 Status
= EFI_SUCCESS
;
1245 switch (Storage
->Type
) {
1246 case EFI_HII_VARSTORE_BUFFER
:
1247 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1248 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1249 Status
= mHiiConfigRouting
->BlockToConfig (
1259 case EFI_HII_VARSTORE_NAME_VALUE
:
1261 FormsetStorage
= GetFstStgFromBrsStg(Storage
);
1262 ASSERT (FormsetStorage
!= NULL
);
1263 NewStringCat (ConfigResp
, FormsetStorage
->ConfigHdr
);
1265 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1266 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1267 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1269 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1270 NewStringCat (ConfigResp
, L
"&");
1271 NewStringCat (ConfigResp
, Node
->Name
);
1272 NewStringCat (ConfigResp
, L
"=");
1274 NewStringCat (ConfigResp
, Node
->EditValue
);
1276 NewStringCat (ConfigResp
, Node
->Value
);
1279 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1283 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1285 Status
= EFI_INVALID_PARAMETER
;
1294 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1296 @param Storage The Storage to receive the settings.
1297 @param ConfigResp The <ConfigResp> to be converted.
1299 @retval EFI_SUCCESS Convert success.
1300 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1304 ConfigRespToStorage (
1305 IN BROWSER_STORAGE
*Storage
,
1306 IN CHAR16
*ConfigResp
1310 EFI_STRING Progress
;
1316 Status
= EFI_SUCCESS
;
1318 switch (Storage
->Type
) {
1319 case EFI_HII_VARSTORE_BUFFER
:
1320 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1321 BufferSize
= Storage
->Size
;
1322 Status
= mHiiConfigRouting
->ConfigToBlock (
1325 Storage
->EditBuffer
,
1331 case EFI_HII_VARSTORE_NAME_VALUE
:
1332 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1333 if (StrPtr
== NULL
) {
1336 StrPtr
= StrStr (ConfigResp
, L
"&");
1337 while (StrPtr
!= NULL
) {
1341 StrPtr
= StrPtr
+ 1;
1343 StrPtr
= StrStr (StrPtr
, L
"=");
1344 if (StrPtr
== NULL
) {
1352 StrPtr
= StrPtr
+ 1;
1354 StrPtr
= StrStr (StrPtr
, L
"&");
1355 if (StrPtr
!= NULL
) {
1358 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1362 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1364 Status
= EFI_INVALID_PARAMETER
;
1372 Get bit field value from the buffer and then set the value for the question.
1373 Note: Data type UINT32 can cover all the bit field value.
1375 @param Question The question refer to bit field.
1376 @param Buffer Point to the buffer which the question value get from.
1380 GetBitsQuestionValue (
1381 IN FORM_BROWSER_STATEMENT
*Question
,
1390 StartBit
= Question
->BitVarOffset
% 8;
1391 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1393 CopyMem ((UINT8
*) &BufferValue
, Buffer
, Question
->StorageWidth
);
1395 RetVal
= BitFieldRead32 (BufferValue
, StartBit
, EndBit
);
1398 // Set question value.
1399 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
1400 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.
1402 CopyMem ((UINT8
*) &Question
->HiiValue
.Value
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1406 Set bit field value to the buffer.
1407 Note: Data type UINT32 can cover all the bit field value.
1409 @param Question The question refer to bit field.
1410 @param Buffer Point to the buffer which the question value set to.
1411 @param Value The bit field value need to set.
1415 SetBitsQuestionValue (
1416 IN FORM_BROWSER_STATEMENT
*Question
,
1417 IN OUT UINT8
*Buffer
,
1426 StartBit
= Question
->BitVarOffset
% 8;
1427 EndBit
= StartBit
+ Question
->BitStorageWidth
- 1;
1429 CopyMem ((UINT8
*) &Operand
, Buffer
, Question
->StorageWidth
);
1431 RetVal
= BitFieldWrite32 (Operand
, StartBit
, EndBit
, Value
);
1433 CopyMem (Buffer
, (UINT8
*) &RetVal
, Question
->StorageWidth
);
1437 Convert the buffer value to HiiValue.
1439 @param Question The question.
1440 @param Value Unicode buffer save the question value.
1442 @retval Status whether convert the value success.
1447 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1452 BOOLEAN IsBufferStorage
;
1467 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1468 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1469 Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1470 IsBufferStorage
= TRUE
;
1472 IsBufferStorage
= FALSE
;
1476 // Question Value is provided by Buffer Storage or NameValue Storage
1478 if (Question
->BufferValue
!= NULL
) {
1480 // This Question is password or orderedlist
1482 Dst
= Question
->BufferValue
;
1485 // Other type of Questions
1487 if (Question
->QuestionReferToBitField
) {
1488 Buffer
= (UINT8
*)AllocateZeroPool (Question
->StorageWidth
);
1489 if (Buffer
== NULL
) {
1490 return EFI_OUT_OF_RESOURCES
;
1494 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1499 // Temp cut at the end of this section, end with '\0' or '&'.
1502 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1505 TempChar
= *StringPtr
;
1508 LengthStr
= StrLen (Value
);
1511 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
1512 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
1513 // So the maximum value string length of a question is : Question->StorageWidth * 2.
1514 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
1516 if (LengthStr
> (UINTN
) Question
->StorageWidth
* 2) {
1517 Length
= (UINTN
) Question
->StorageWidth
* 2;
1522 Status
= EFI_SUCCESS
;
1523 if (!IsBufferStorage
&& IsString
) {
1525 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1526 // Add string tail char L'\0' into Length
1528 DstBuf
= (CHAR16
*) Dst
;
1529 ZeroMem (TemStr
, sizeof (TemStr
));
1530 for (Index
= 0; Index
< Length
; Index
+= 4) {
1531 StrnCpyS (TemStr
, sizeof (TemStr
) / sizeof (CHAR16
), Value
+ Index
, 4);
1532 DstBuf
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1535 // Add tailing L'\0' character
1537 DstBuf
[Index
/4] = L
'\0';
1539 ZeroMem (TemStr
, sizeof (TemStr
));
1540 for (Index
= 0; Index
< Length
; Index
++) {
1541 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1542 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1543 if ((Index
& 1) == 0) {
1544 Dst
[Index
/2] = DigitUint8
;
1546 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1551 *StringPtr
= TempChar
;
1553 if (Buffer
!= NULL
&& Question
->QuestionReferToBitField
) {
1554 GetBitsQuestionValue (Question
, Buffer
);
1562 Get Question's current Value.
1564 @param FormSet FormSet data structure.
1565 @param Form Form data structure.
1566 @param Question Question to be initialized.
1567 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1569 @retval EFI_SUCCESS The function completed successfully.
1574 IN FORM_BROWSER_FORMSET
*FormSet
,
1575 IN FORM_BROWSER_FORM
*Form
,
1576 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1577 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1586 BROWSER_STORAGE
*Storage
;
1587 FORMSET_STORAGE
*FormsetStorage
;
1588 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1589 CHAR16
*ConfigRequest
;
1594 BOOLEAN IsBufferStorage
;
1597 Status
= EFI_SUCCESS
;
1601 if (GetValueFrom
>= GetSetValueWithMax
) {
1602 return EFI_INVALID_PARAMETER
;
1606 // Question value is provided by an Expression, evaluate it
1608 if (Question
->ValueExpression
!= NULL
) {
1609 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1610 if (!EFI_ERROR (Status
)) {
1611 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1612 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1613 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1614 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1615 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1617 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1618 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1620 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1622 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1623 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1629 // Get question value by read expression.
1631 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1632 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1633 if (!EFI_ERROR (Status
) &&
1634 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1636 // Only update question value to the valid result.
1638 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1639 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1640 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1641 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1642 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1644 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1645 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1647 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1649 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1650 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1656 // Question value is provided by RTC
1658 Storage
= Question
->Storage
;
1659 QuestionValue
= &Question
->HiiValue
.Value
;
1660 if (Storage
== NULL
) {
1662 // It's a Question without storage, or RTC date/time
1664 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1666 // Date and time define the same Flags bit
1668 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1669 case QF_DATE_STORAGE_TIME
:
1670 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1673 case QF_DATE_STORAGE_WAKEUP
:
1674 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1677 case QF_DATE_STORAGE_NORMAL
:
1680 // For date/time without storage
1685 if (EFI_ERROR (Status
)) {
1686 if (Question
->Operand
== EFI_IFR_DATE_OP
){
1687 QuestionValue
->date
.Year
= 0xff;
1688 QuestionValue
->date
.Month
= 0xff;
1689 QuestionValue
->date
.Day
= 0xff;
1691 QuestionValue
->time
.Hour
= 0xff;
1692 QuestionValue
->time
.Minute
= 0xff;
1693 QuestionValue
->time
.Second
= 0xff;
1698 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1699 QuestionValue
->date
.Year
= EfiTime
.Year
;
1700 QuestionValue
->date
.Month
= EfiTime
.Month
;
1701 QuestionValue
->date
.Day
= EfiTime
.Day
;
1703 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1704 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1705 QuestionValue
->time
.Second
= EfiTime
.Second
;
1713 // Question value is provided by EFI variable
1715 StorageWidth
= Question
->StorageWidth
;
1716 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1717 if (Question
->BufferValue
!= NULL
) {
1718 Dst
= Question
->BufferValue
;
1720 Dst
= (UINT8
*) QuestionValue
;
1723 Status
= gRT
->GetVariable (
1724 Question
->VariableName
,
1731 // Always return success, even this EFI variable doesn't exist
1737 // Question Value is provided by Buffer Storage or NameValue Storage
1739 if (Question
->BufferValue
!= NULL
) {
1741 // This Question is password or orderedlist
1743 Dst
= Question
->BufferValue
;
1746 // Other type of Questions
1748 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1751 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1752 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1753 IsBufferStorage
= TRUE
;
1755 IsBufferStorage
= FALSE
;
1757 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1758 if (IsBufferStorage
) {
1759 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1761 // Copy from storage Edit buffer
1762 // If the Question refer to bit filed, get the value in the related bit filed.
1764 if (Question
->QuestionReferToBitField
) {
1765 GetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
);
1767 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1771 // Copy from storage Edit buffer
1772 // If the Question refer to bit filed, get the value in the related bit filed.
1774 if (Question
->QuestionReferToBitField
) {
1775 GetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
);
1777 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1782 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1783 if (EFI_ERROR (Status
)) {
1787 ASSERT (Value
!= NULL
);
1788 Status
= BufferToValue (Question
, Value
);
1792 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
1793 ASSERT (FormsetStorage
!= NULL
);
1795 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1796 // <ConfigHdr> + "&" + <VariableName>
1798 if (IsBufferStorage
) {
1799 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1800 Length
+= StrLen (Question
->BlockName
);
1802 Length
= StrLen (FormsetStorage
->ConfigHdr
);
1803 Length
+= StrLen (Question
->VariableName
) + 1;
1805 // Allocate buffer include '\0'
1806 MaxLen
= Length
+ 1;
1807 ConfigRequest
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1808 ASSERT (ConfigRequest
!= NULL
);
1810 StrCpyS (ConfigRequest
, MaxLen
, FormsetStorage
->ConfigHdr
);
1811 if (IsBufferStorage
) {
1812 StrCatS (ConfigRequest
, MaxLen
, Question
->BlockName
);
1814 StrCatS (ConfigRequest
, MaxLen
, L
"&");
1815 StrCatS (ConfigRequest
, MaxLen
, Question
->VariableName
);
1819 // Request current settings from Configuration Driver
1821 Status
= mHiiConfigRouting
->ExtractConfig (
1827 FreePool (ConfigRequest
);
1828 if (EFI_ERROR (Status
)) {
1833 // Skip <ConfigRequest>
1835 if (IsBufferStorage
) {
1836 Value
= StrStr (Result
, L
"&VALUE");
1837 if (Value
== NULL
) {
1839 return EFI_NOT_FOUND
;
1846 Value
= Result
+ Length
;
1848 if (*Value
!= '=') {
1850 return EFI_NOT_FOUND
;
1853 // Skip '=', point to value
1857 Status
= BufferToValue (Question
, Value
);
1858 if (EFI_ERROR (Status
)) {
1864 // Synchronize Edit Buffer
1866 if (IsBufferStorage
) {
1867 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1869 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1872 if (Result
!= NULL
) {
1882 Save Question Value to edit copy(cached) or Storage(uncached).
1884 @param FormSet FormSet data structure.
1885 @param Form Form data structure.
1886 @param Question Pointer to the Question.
1887 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1889 @retval EFI_SUCCESS The function completed successfully.
1894 IN FORM_BROWSER_FORMSET
*FormSet
,
1895 IN FORM_BROWSER_FORM
*Form
,
1896 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1897 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1907 BROWSER_STORAGE
*Storage
;
1908 FORMSET_STORAGE
*FormsetStorage
;
1909 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1914 BOOLEAN IsBufferStorage
;
1920 NAME_VALUE_NODE
*Node
;
1923 Status
= EFI_SUCCESS
;
1926 if (SetValueTo
>= GetSetValueWithMax
) {
1927 return EFI_INVALID_PARAMETER
;
1931 // If Question value is provided by an Expression, then it is read only
1933 if (Question
->ValueExpression
!= NULL
) {
1938 // Before set question value, evaluate its write expression.
1940 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1941 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1942 if (EFI_ERROR (Status
)) {
1948 // Question value is provided by RTC
1950 Storage
= Question
->Storage
;
1951 QuestionValue
= &Question
->HiiValue
.Value
;
1952 if (Storage
== NULL
) {
1954 // It's a Question without storage, or RTC date/time
1956 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1958 // Date and time define the same Flags bit
1960 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1961 case QF_DATE_STORAGE_TIME
:
1962 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1965 case QF_DATE_STORAGE_WAKEUP
:
1966 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1969 case QF_DATE_STORAGE_NORMAL
:
1972 // For date/time without storage
1977 if (EFI_ERROR (Status
)) {
1981 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1982 EfiTime
.Year
= QuestionValue
->date
.Year
;
1983 EfiTime
.Month
= QuestionValue
->date
.Month
;
1984 EfiTime
.Day
= QuestionValue
->date
.Day
;
1986 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1987 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1988 EfiTime
.Second
= QuestionValue
->time
.Second
;
1991 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1992 Status
= gRT
->SetTime (&EfiTime
);
1994 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
2002 // Question value is provided by EFI variable
2004 StorageWidth
= Question
->StorageWidth
;
2005 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2006 if (Question
->BufferValue
!= NULL
) {
2007 Src
= Question
->BufferValue
;
2009 Src
= (UINT8
*) QuestionValue
;
2012 Status
= gRT
->SetVariable (
2013 Question
->VariableName
,
2015 Storage
->Attributes
,
2023 // Question Value is provided by Buffer Storage or NameValue Storage
2025 if (Question
->BufferValue
!= NULL
) {
2026 Src
= Question
->BufferValue
;
2028 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
2031 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2032 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2033 IsBufferStorage
= TRUE
;
2035 IsBufferStorage
= FALSE
;
2037 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2039 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
2040 if (IsBufferStorage
) {
2041 if (SetValueTo
== GetSetValueWithEditBuffer
) {
2043 // Copy to storage edit buffer
2044 // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
2046 if (Question
->QuestionReferToBitField
) {
2047 SetBitsQuestionValue (Question
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2049 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2051 } else if (SetValueTo
== GetSetValueWithBuffer
) {
2053 // Copy to storage buffer
2054 // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.
2056 if (Question
->QuestionReferToBitField
) {
2057 SetBitsQuestionValue (Question
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, (UINT32
)(*Src
));
2059 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2065 // Allocate enough string buffer.
2068 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
2069 Value
= AllocateZeroPool (BufferLen
);
2070 ASSERT (Value
!= NULL
);
2072 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2074 TemName
= (CHAR16
*) Src
;
2076 for (; *TemName
!= L
'\0'; TemName
++) {
2077 UnicodeValueToStringS (
2079 BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
),
2080 PREFIX_ZERO
| RADIX_HEX
,
2084 TemString
+= StrnLenS (TemString
, (BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
)) / sizeof (CHAR16
));
2087 BufferLen
= StorageWidth
* 2 + 1;
2088 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
2089 ASSERT (Value
!= NULL
);
2091 // Convert Buffer to Hex String
2093 TemBuffer
= Src
+ StorageWidth
- 1;
2095 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2096 UnicodeValueToStringS (
2098 BufferLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)Value
),
2099 PREFIX_ZERO
| RADIX_HEX
,
2103 TemString
+= StrnLenS (TemString
, BufferLen
- ((UINTN
)TemString
- (UINTN
)Value
) / sizeof (CHAR16
));
2107 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
2109 if (EFI_ERROR (Status
)) {
2113 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
2115 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
2116 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
2118 if (IsBufferStorage
) {
2119 Length
= StrLen (Question
->BlockName
) + 7;
2121 Length
= StrLen (Question
->VariableName
) + 2;
2123 if (!IsBufferStorage
&& IsString
) {
2124 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
2126 Length
+= (StorageWidth
* 2);
2128 FormsetStorage
= GetFstStgFromVarId(FormSet
, Question
->VarStoreId
);
2129 ASSERT (FormsetStorage
!= NULL
);
2130 MaxLen
= StrLen (FormsetStorage
->ConfigHdr
) + Length
+ 1;
2131 ConfigResp
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
2132 ASSERT (ConfigResp
!= NULL
);
2134 StrCpyS (ConfigResp
, MaxLen
, FormsetStorage
->ConfigHdr
);
2135 if (IsBufferStorage
) {
2136 StrCatS (ConfigResp
, MaxLen
, Question
->BlockName
);
2137 StrCatS (ConfigResp
, MaxLen
, L
"&VALUE=");
2139 StrCatS (ConfigResp
, MaxLen
, L
"&");
2140 StrCatS (ConfigResp
, MaxLen
, Question
->VariableName
);
2141 StrCatS (ConfigResp
, MaxLen
, L
"=");
2144 Value
= ConfigResp
+ StrLen (ConfigResp
);
2146 if (!IsBufferStorage
&& IsString
) {
2148 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
2150 TemName
= (CHAR16
*) Src
;
2152 for (; *TemName
!= L
'\0'; TemName
++) {
2153 UnicodeValueToStringS (
2155 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2156 PREFIX_ZERO
| RADIX_HEX
,
2160 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2164 // Convert Buffer to Hex String
2166 TemBuffer
= Src
+ StorageWidth
- 1;
2168 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
2169 UnicodeValueToStringS (
2171 MaxLen
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ConfigResp
),
2172 PREFIX_ZERO
| RADIX_HEX
,
2176 TemString
+= StrnLenS (TemString
, MaxLen
- ((UINTN
)TemString
- (UINTN
)ConfigResp
) / sizeof (CHAR16
));
2181 // Convert to lower char.
2183 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
2184 if (*Value
>= L
'A' && *Value
<= L
'Z') {
2185 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
2190 // Submit Question Value to Configuration Driver
2192 Status
= mHiiConfigRouting
->RouteConfig (
2197 if (EFI_ERROR (Status
)) {
2198 FreePool (ConfigResp
);
2201 FreePool (ConfigResp
);
2204 // Sync storage, from editbuffer to buffer.
2206 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
2214 Perform nosubmitif check for a Form.
2216 @param FormSet FormSet data structure.
2217 @param Form Form data structure.
2218 @param Question The Question to be validated.
2219 @param Type Validation type: NoSubmit
2221 @retval EFI_SUCCESS Form validation pass.
2222 @retval other Form validation failed.
2227 IN FORM_BROWSER_FORMSET
*FormSet
,
2228 IN FORM_BROWSER_FORM
*Form
,
2229 IN FORM_BROWSER_STATEMENT
*Question
,
2235 LIST_ENTRY
*ListHead
;
2236 FORM_EXPRESSION
*Expression
;
2237 UINT32 BrowserStatus
;
2240 BrowserStatus
= BROWSER_SUCCESS
;
2244 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2245 ListHead
= &Question
->InconsistentListHead
;
2248 case EFI_HII_EXPRESSION_WARNING_IF
:
2249 ListHead
= &Question
->WarningListHead
;
2252 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2253 ListHead
= &Question
->NoSubmitListHead
;
2258 return EFI_UNSUPPORTED
;
2261 Link
= GetFirstNode (ListHead
);
2262 while (!IsNull (ListHead
, Link
)) {
2263 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2266 // Evaluate the expression
2268 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2269 if (EFI_ERROR (Status
)) {
2273 if (IsTrue (&Expression
->Result
)) {
2275 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
2276 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
2279 case EFI_HII_EXPRESSION_WARNING_IF
:
2280 BrowserStatus
= BROWSER_WARNING_IF
;
2283 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2284 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2286 // This code only used to compatible with old display engine,
2287 // New display engine will not use this field.
2289 if (Expression
->Error
!= 0) {
2290 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2299 if (!((Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) && mSystemSubmit
)) {
2301 // If in system submit process and for no_submit_if check, not popup this error message.
2302 // Will process this fail again later in not system submit process.
2304 PopupErrorMessage(BrowserStatus
, FormSet
->HiiHandle
, Expression
->OpCode
, ErrorStr
);
2307 if (ErrorStr
!= NULL
) {
2308 FreePool (ErrorStr
);
2311 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2314 return EFI_NOT_READY
;
2318 Link
= GetNextNode (ListHead
, Link
);
2325 Perform question check.
2327 If one question has more than one check, process form high priority to low.
2328 Only one error info will be popup.
2330 @param FormSet FormSet data structure.
2331 @param Form Form data structure.
2332 @param Question The Question to be validated.
2334 @retval EFI_SUCCESS Form validation pass.
2335 @retval other Form validation failed.
2339 ValueChangedValidation (
2340 IN FORM_BROWSER_FORMSET
*FormSet
,
2341 IN FORM_BROWSER_FORM
*Form
,
2342 IN FORM_BROWSER_STATEMENT
*Question
2347 Status
= EFI_SUCCESS
;
2350 // Do the inconsistentif check.
2352 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2353 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2354 if (EFI_ERROR (Status
)) {
2360 // Do the warningif check.
2362 if (!IsListEmpty (&Question
->WarningListHead
)) {
2363 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2370 Perform NoSubmit check for each Form in FormSet.
2372 @param FormSet FormSet data structure.
2373 @param CurrentForm Current input form data structure.
2374 @param Statement The statement for this check.
2376 @retval EFI_SUCCESS Form validation pass.
2377 @retval other Form validation failed.
2382 IN FORM_BROWSER_FORMSET
*FormSet
,
2383 IN OUT FORM_BROWSER_FORM
**CurrentForm
,
2384 OUT FORM_BROWSER_STATEMENT
**Statement
2389 FORM_BROWSER_STATEMENT
*Question
;
2390 FORM_BROWSER_FORM
*Form
;
2391 LIST_ENTRY
*LinkForm
;
2393 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2394 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2395 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2396 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2398 if (*CurrentForm
!= NULL
&& *CurrentForm
!= Form
) {
2402 Link
= GetFirstNode (&Form
->StatementListHead
);
2403 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2404 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2405 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2406 if (EFI_ERROR (Status
)) {
2407 if (*CurrentForm
== NULL
) {
2408 *CurrentForm
= Form
;
2410 if (Statement
!= NULL
) {
2411 *Statement
= Question
;
2416 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2424 Fill storage's edit copy with settings requested from Configuration Driver.
2426 @param Storage The storage which need to sync.
2427 @param ConfigRequest The config request string which used to sync storage.
2428 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2429 editbuffer to buffer
2430 if TRUE, copy the editbuffer to the buffer.
2431 if FALSE, copy the buffer to the editbuffer.
2433 @retval EFI_SUCCESS The function completed successfully.
2437 SynchronizeStorage (
2438 OUT BROWSER_STORAGE
*Storage
,
2439 IN CHAR16
*ConfigRequest
,
2440 IN BOOLEAN SyncOrRestore
2444 EFI_STRING Progress
;
2448 NAME_VALUE_NODE
*Node
;
2452 Status
= EFI_SUCCESS
;
2455 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2456 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2457 BufferSize
= Storage
->Size
;
2459 if (SyncOrRestore
) {
2460 Src
= Storage
->EditBuffer
;
2461 Dst
= Storage
->Buffer
;
2463 Src
= Storage
->Buffer
;
2464 Dst
= Storage
->EditBuffer
;
2467 if (ConfigRequest
!= NULL
) {
2468 Status
= mHiiConfigRouting
->BlockToConfig(
2476 if (EFI_ERROR (Status
)) {
2480 Status
= mHiiConfigRouting
->ConfigToBlock (
2487 if (Result
!= NULL
) {
2491 CopyMem (Dst
, Src
, BufferSize
);
2493 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2494 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2495 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2496 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2498 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2499 (ConfigRequest
== NULL
)) {
2500 if (SyncOrRestore
) {
2501 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2503 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2507 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2515 When discard the question value, call the callback function with Changed type
2516 to inform the hii driver.
2518 @param FormSet FormSet data structure.
2519 @param Form Form data structure.
2523 SendDiscardInfoToDriver (
2524 IN FORM_BROWSER_FORMSET
*FormSet
,
2525 IN FORM_BROWSER_FORM
*Form
2529 FORM_BROWSER_STATEMENT
*Question
;
2530 EFI_IFR_TYPE_VALUE
*TypeValue
;
2531 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2533 if (FormSet
->ConfigAccess
== NULL
) {
2537 Link
= GetFirstNode (&Form
->StatementListHead
);
2538 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2539 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2540 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2542 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2546 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2550 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2554 if (!Question
->ValueChanged
) {
2559 // Restore the question value before call the CHANGED callback type.
2561 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2563 if (Question
->Operand
== EFI_IFR_STRING_OP
){
2564 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
2567 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2568 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2570 TypeValue
= &Question
->HiiValue
.Value
;
2573 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2574 FormSet
->ConfigAccess
->Callback (
2575 FormSet
->ConfigAccess
,
2576 EFI_BROWSER_ACTION_CHANGED
,
2577 Question
->QuestionId
,
2578 Question
->HiiValue
.Type
,
2586 When submit the question value, call the callback function with Submitted type
2587 to inform the hii driver.
2589 @param FormSet FormSet data structure.
2590 @param Form Form data structure.
2594 SubmitCallbackForForm (
2595 IN FORM_BROWSER_FORMSET
*FormSet
,
2596 IN FORM_BROWSER_FORM
*Form
2600 FORM_BROWSER_STATEMENT
*Question
;
2601 EFI_IFR_TYPE_VALUE
*TypeValue
;
2602 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2604 if (FormSet
->ConfigAccess
== NULL
) {
2608 Link
= GetFirstNode (&Form
->StatementListHead
);
2609 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2610 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2611 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2613 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2617 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2621 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2625 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2626 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2628 TypeValue
= &Question
->HiiValue
.Value
;
2631 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2632 FormSet
->ConfigAccess
->Callback (
2633 FormSet
->ConfigAccess
,
2634 EFI_BROWSER_ACTION_SUBMITTED
,
2635 Question
->QuestionId
,
2636 Question
->HiiValue
.Type
,
2644 When value set Success, call the submit callback function.
2646 @param FormSet FormSet data structure.
2647 @param Form Form data structure.
2652 IN FORM_BROWSER_FORMSET
*FormSet
,
2653 IN FORM_BROWSER_FORM
*Form
2656 FORM_BROWSER_FORM
*CurrentForm
;
2660 SubmitCallbackForForm(FormSet
, Form
);
2664 Link
= GetFirstNode (&FormSet
->FormListHead
);
2665 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2666 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2667 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2669 SubmitCallbackForForm(FormSet
, CurrentForm
);
2674 Validate the HiiHandle.
2676 @param HiiHandle The input HiiHandle which need to validate.
2678 @retval TRUE The handle is validate.
2679 @retval FALSE The handle is invalidate.
2684 EFI_HII_HANDLE HiiHandle
2687 EFI_HII_HANDLE
*HiiHandles
;
2691 if (HiiHandle
== NULL
) {
2697 HiiHandles
= HiiGetHiiHandles (NULL
);
2698 ASSERT (HiiHandles
!= NULL
);
2700 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2701 if (HiiHandles
[Index
] == HiiHandle
) {
2707 FreePool (HiiHandles
);
2713 Validate the FormSet. If the formset is not validate, remove it from the list.
2715 @param FormSet The input FormSet which need to validate.
2717 @retval TRUE The handle is validate.
2718 @retval FALSE The handle is invalidate.
2723 FORM_BROWSER_FORMSET
*FormSet
2728 ASSERT (FormSet
!= NULL
);
2730 Find
= ValidateHiiHandle(FormSet
->HiiHandle
);
2732 // Should not remove the formset which is being used.
2734 if (!Find
&& (FormSet
!= gCurrentSelection
->FormSet
)) {
2735 CleanBrowserStorage(FormSet
);
2736 RemoveEntryList (&FormSet
->Link
);
2737 DestroyFormSet (FormSet
);
2743 Check whether need to enable the reset flag in form level.
2744 Also clean all ValueChanged flag in question.
2746 @param SetFlag Whether need to set the Reset Flag.
2747 @param FormSet FormSet data structure.
2748 @param Form Form data structure.
2754 IN FORM_BROWSER_FORMSET
*FormSet
,
2755 IN FORM_BROWSER_FORM
*Form
2759 FORM_BROWSER_STATEMENT
*Question
;
2762 Link
= GetFirstNode (&Form
->StatementListHead
);
2763 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2764 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2765 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2767 if (!Question
->ValueChanged
) {
2771 OldValue
= Question
->ValueChanged
;
2774 // Compare the buffer and editbuffer data to see whether the data has been saved.
2776 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBothBuffer
);
2779 // Only the changed data has been saved, then need to set the reset flag.
2781 if (SetFlag
&& OldValue
&& !Question
->ValueChanged
) {
2782 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0) {
2783 gResetRequiredFormLevel
= TRUE
;
2784 gResetRequiredSystemLevel
= TRUE
;
2787 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_RECONNECT_REQUIRED
) != 0) {
2788 gFlagReconnect
= TRUE
;
2795 Check whether need to enable the reset flag.
2796 Also clean ValueChanged flag for all statements.
2798 Form level or formset level, only one.
2800 @param SetFlag Whether need to set the Reset Flag.
2801 @param FormSet FormSet data structure.
2802 @param Form Form data structure.
2806 ValueChangeResetFlagUpdate (
2808 IN FORM_BROWSER_FORMSET
*FormSet
,
2809 IN FORM_BROWSER_FORM
*Form
2812 FORM_BROWSER_FORM
*CurrentForm
;
2816 UpdateFlagForForm(SetFlag
, FormSet
, Form
);
2820 Link
= GetFirstNode (&FormSet
->FormListHead
);
2821 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2822 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2823 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2825 UpdateFlagForForm(SetFlag
, FormSet
, CurrentForm
);
2830 Base on the return Progress string to find the form.
2832 Base on the first return Offset/Width (Name) string to find the form
2833 which keep this string.
2835 @param FormSet FormSet data structure.
2836 @param Storage Storage which has this Progress string.
2837 @param Progress The Progress string which has the first fail string.
2838 @param RetForm The return form for this progress string.
2839 @param RetQuestion The return question for the error progress string.
2841 @retval TRUE Find the error form and statement for this error progress string.
2842 @retval FALSE Not find the error form.
2846 FindQuestionFromProgress (
2847 IN FORM_BROWSER_FORMSET
*FormSet
,
2848 IN BROWSER_STORAGE
*Storage
,
2849 IN EFI_STRING Progress
,
2850 OUT FORM_BROWSER_FORM
**RetForm
,
2851 OUT FORM_BROWSER_STATEMENT
**RetQuestion
2855 LIST_ENTRY
*LinkStorage
;
2856 LIST_ENTRY
*LinkStatement
;
2857 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2858 FORM_BROWSER_FORM
*Form
;
2860 FORM_BROWSER_STATEMENT
*Statement
;
2862 ASSERT ((*Progress
== '&') || (*Progress
== 'G'));
2866 *RetQuestion
= NULL
;
2869 // Skip the first "&" or the ConfigHdr part.
2871 if (*Progress
== '&') {
2875 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2877 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2879 // For Name/Value type, Skip the ConfigHdr part.
2881 EndStr
= StrStr (Progress
, L
"PATH=");
2882 ASSERT (EndStr
!= NULL
);
2883 while (*EndStr
!= '&') {
2890 // For Buffer type, Skip the ConfigHdr part.
2892 EndStr
= StrStr (Progress
, L
"&OFFSET=");
2893 ASSERT (EndStr
!= NULL
);
2897 Progress
= EndStr
+ 1;
2901 // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
2903 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2905 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
2906 // here, just keep the "Fred" string.
2908 EndStr
= StrStr (Progress
, L
"=");
2909 ASSERT (EndStr
!= NULL
);
2913 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
2914 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
2916 EndStr
= StrStr (Progress
, L
"&VALUE=");
2917 ASSERT (EndStr
!= NULL
);
2922 // Search in the form list.
2924 Link
= GetFirstNode (&FormSet
->FormListHead
);
2925 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2926 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2927 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2930 // Search in the ConfigReqeust list in this form.
2932 LinkStorage
= GetFirstNode (&Form
->ConfigRequestHead
);
2933 while (!IsNull (&Form
->ConfigRequestHead
, LinkStorage
)) {
2934 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage
);
2935 LinkStorage
= GetNextNode (&Form
->ConfigRequestHead
, LinkStorage
);
2937 if (Storage
!= ConfigInfo
->Storage
) {
2941 if (StrStr (ConfigInfo
->ConfigRequest
, Progress
) != NULL
) {
2943 // Find the OffsetWidth string in this form.
2950 if (*RetForm
!= NULL
) {
2951 LinkStatement
= GetFirstNode (&Form
->StatementListHead
);
2952 while (!IsNull (&Form
->StatementListHead
, LinkStatement
)) {
2953 Statement
= FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement
);
2954 LinkStatement
= GetNextNode (&Form
->StatementListHead
, LinkStatement
);
2956 if (Statement
->BlockName
!= NULL
&& StrStr (Statement
->BlockName
, Progress
) != NULL
) {
2957 *RetQuestion
= Statement
;
2961 if (Statement
->VariableName
!= NULL
&& StrStr (Statement
->VariableName
, Progress
) != NULL
) {
2962 *RetQuestion
= Statement
;
2968 if (*RetForm
!= NULL
) {
2974 // restore the OffsetWidth string to the original format.
2976 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2982 return (BOOLEAN
) (*RetForm
!= NULL
);
2986 Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest
2987 for form and formset.
2989 @param Storage Storage which has this Progress string.
2990 @param ConfigRequest The ConfigRequest string.
2991 @param Progress The Progress string which has the first fail string.
2992 @param RestoreConfigRequest Return the RestoreConfigRequest string.
2993 @param SyncConfigRequest Return the SyncConfigRequest string.
2997 GetSyncRestoreConfigRequest(
2998 IN BROWSER_STORAGE
*Storage
,
2999 IN EFI_STRING ConfigRequest
,
3000 IN EFI_STRING Progress
,
3001 OUT EFI_STRING
*RestoreConfigRequest
,
3002 OUT EFI_STRING
*SyncConfigRequest
3006 EFI_STRING ConfigHdrEndStr
;
3007 EFI_STRING ElementStr
;
3009 UINTN RestoreEleSize
;
3012 ASSERT ((*Progress
== L
'&') || (*Progress
== L
'G'));
3014 // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.
3015 // Need to restore all the fields in the ConfigRequest.
3017 if (*Progress
== L
'G') {
3018 *RestoreConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3019 ASSERT (*RestoreConfigRequest
!= NULL
);
3024 // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.
3026 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3028 // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,
3029 // here, just keep the "Fred" string.
3031 EndStr
= StrStr (Progress
, L
"=");
3032 ASSERT (EndStr
!= NULL
);
3035 // Find the ConfigHdr in ConfigRequest.
3037 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"PATH=");
3038 ASSERT (ConfigHdrEndStr
!= NULL
);
3039 while (*ConfigHdrEndStr
!= L
'&') {
3044 // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",
3045 // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.
3047 EndStr
= StrStr (Progress
, L
"&VALUE=");
3048 ASSERT (EndStr
!= NULL
);
3051 // Find the ConfigHdr in ConfigRequest.
3053 ConfigHdrEndStr
= StrStr (ConfigRequest
, L
"&OFFSET=");
3056 // Find the first fail pair in the ConfigRequest.
3058 ElementStr
= StrStr (ConfigRequest
, Progress
);
3059 ASSERT (ElementStr
!= NULL
);
3061 // To get the RestoreConfigRequest.
3063 RestoreEleSize
= StrSize (ElementStr
);
3064 TotalSize
= (ConfigHdrEndStr
- ConfigRequest
) * sizeof (CHAR16
) + RestoreEleSize
+ sizeof (CHAR16
);
3065 *RestoreConfigRequest
= AllocateZeroPool (TotalSize
);
3066 ASSERT (*RestoreConfigRequest
!= NULL
);
3067 StrnCpyS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ConfigRequest
, ConfigHdrEndStr
- ConfigRequest
);
3068 StrCatS (*RestoreConfigRequest
, TotalSize
/ sizeof (CHAR16
), ElementStr
);
3070 // To get the SyncConfigRequest.
3072 SyncSize
= StrSize (ConfigRequest
) - RestoreEleSize
+ sizeof (CHAR16
);
3073 *SyncConfigRequest
= AllocateZeroPool (SyncSize
);
3074 ASSERT (*SyncConfigRequest
!= NULL
);
3075 StrnCpyS (*SyncConfigRequest
, SyncSize
/ sizeof (CHAR16
), ConfigRequest
, SyncSize
/ sizeof (CHAR16
) - 1);
3078 // restore the Progress string to the original format.
3080 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3088 Popup an save error info and get user input.
3090 @param TitleId The form title id.
3091 @param HiiHandle The hii handle for this package.
3093 @retval UINT32 The user select option for the save fail.
3094 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3098 IN EFI_STRING_ID TitleId
,
3099 IN EFI_HII_HANDLE HiiHandle
3103 CHAR16
*StringBuffer
;
3106 FormTitle
= GetToken (TitleId
, HiiHandle
);
3108 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3109 ASSERT (StringBuffer
!= NULL
);
3113 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3114 L
"Submit Fail For Form: %s.",
3118 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL
, NULL
, NULL
, StringBuffer
);
3120 FreePool (StringBuffer
);
3121 FreePool (FormTitle
);
3127 Popup an NO_SUBMIT_IF error info and get user input.
3129 @param TitleId The form title id.
3130 @param HiiHandle The hii handle for this package.
3132 @retval UINT32 The user select option for the save fail.
3133 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET
3136 ConfirmNoSubmitFail (
3137 IN EFI_STRING_ID TitleId
,
3138 IN EFI_HII_HANDLE HiiHandle
3142 CHAR16
*StringBuffer
;
3145 FormTitle
= GetToken (TitleId
, HiiHandle
);
3147 StringBuffer
= AllocateZeroPool (256 * sizeof (CHAR16
));
3148 ASSERT (StringBuffer
!= NULL
);
3152 24 * sizeof (CHAR16
) + StrSize (FormTitle
),
3153 L
"NO_SUBMIT_IF error For Form: %s.",
3157 RetVal
= PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF
, NULL
, NULL
, StringBuffer
);
3159 FreePool (StringBuffer
);
3160 FreePool (FormTitle
);
3166 Discard data based on the input setting scope (Form, FormSet or System).
3168 @param FormSet FormSet data structure.
3169 @param Form Form data structure.
3170 @param SettingScope Setting Scope for Discard action.
3172 @retval EFI_SUCCESS The function completed successfully.
3173 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3178 IN FORM_BROWSER_FORMSET
*FormSet
,
3179 IN FORM_BROWSER_FORM
*Form
,
3180 IN BROWSER_SETTING_SCOPE SettingScope
3184 FORMSET_STORAGE
*Storage
;
3185 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3186 FORM_BROWSER_FORMSET
*LocalFormSet
;
3187 FORM_BROWSER_FORMSET
*OldFormSet
;
3190 // Check the supported setting level.
3192 if (SettingScope
>= MaxLevel
) {
3193 return EFI_UNSUPPORTED
;
3196 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
3198 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3199 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3200 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3201 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3203 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3208 // Skip if there is no RequestElement
3210 if (ConfigInfo
->ElementCount
== 0) {
3215 // Prepare <ConfigResp>
3217 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
3220 // Call callback with Changed type to inform the driver.
3222 SendDiscardInfoToDriver (FormSet
, Form
);
3225 ValueChangeResetFlagUpdate (FALSE
, FormSet
, Form
);
3226 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
3229 // Discard Buffer storage or Name/Value storage
3231 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3232 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3233 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3234 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3236 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3241 // Skip if there is no RequestElement
3243 if (Storage
->ElementCount
== 0) {
3247 SynchronizeStorage(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
3250 Link
= GetFirstNode (&FormSet
->FormListHead
);
3251 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3252 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3253 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3256 // Call callback with Changed type to inform the driver.
3258 SendDiscardInfoToDriver (FormSet
, Form
);
3261 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
3262 } else if (SettingScope
== SystemLevel
) {
3264 // System Level Discard.
3266 OldFormSet
= mSystemLevelFormSet
;
3269 // Discard changed value for each FormSet in the maintain list.
3271 Link
= GetFirstNode (&gBrowserFormSetList
);
3272 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3273 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3274 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3275 if (!ValidateFormSet(LocalFormSet
)) {
3279 mSystemLevelFormSet
= LocalFormSet
;
3281 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
3282 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3284 // Remove maintain backup list after discard except for the current using FormSet.
3286 CleanBrowserStorage(LocalFormSet
);
3287 RemoveEntryList (&LocalFormSet
->Link
);
3288 DestroyFormSet (LocalFormSet
);
3292 mSystemLevelFormSet
= OldFormSet
;
3299 Submit data for a form.
3301 @param FormSet FormSet data structure.
3302 @param Form Form data structure.
3304 @retval EFI_SUCCESS The function completed successfully.
3305 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3310 IN FORM_BROWSER_FORMSET
*FormSet
,
3311 IN FORM_BROWSER_FORM
*Form
3316 EFI_STRING ConfigResp
;
3317 EFI_STRING Progress
;
3318 BROWSER_STORAGE
*Storage
;
3319 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3320 BOOLEAN SubmitFormFail
;
3322 SubmitFormFail
= FALSE
;
3324 if (!IsNvUpdateRequiredForForm (Form
)) {
3328 Status
= NoSubmitCheck (FormSet
, &Form
, NULL
);
3329 if (EFI_ERROR (Status
)) {
3333 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3334 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3335 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3336 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3338 Storage
= ConfigInfo
->Storage
;
3339 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3344 // Skip if there is no RequestElement
3346 if (ConfigInfo
->ElementCount
== 0) {
3351 // 1. Prepare <ConfigResp>
3353 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
3354 if (EFI_ERROR (Status
)) {
3359 // 2. Set value to hii config routine protocol.
3361 Status
= mHiiConfigRouting
->RouteConfig (
3367 if (EFI_ERROR (Status
)) {
3369 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3371 SubmitFormFail
= TRUE
;
3372 GetSyncRestoreConfigRequest (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, Progress
, &ConfigInfo
->RestoreConfigRequest
, &ConfigInfo
->SyncConfigRequest
);
3373 InsertTailList (&gBrowserSaveFailFormSetList
, &ConfigInfo
->SaveFailLink
);
3374 FreePool (ConfigResp
);
3378 FreePool (ConfigResp
);
3380 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
3382 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
3386 // 4. Process the save failed storage.
3388 if (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3389 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3390 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3391 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3392 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3393 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3395 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3396 // base on the SyncConfigRequest to Sync the buffer.
3398 SynchronizeStorage (ConfigInfo
->Storage
, ConfigInfo
->RestoreConfigRequest
, FALSE
);
3399 FreePool (ConfigInfo
->RestoreConfigRequest
);
3400 ConfigInfo
->RestoreConfigRequest
= NULL
;
3401 if (ConfigInfo
->SyncConfigRequest
!= NULL
) {
3402 SynchronizeStorage(ConfigInfo
->Storage
, ConfigInfo
->SyncConfigRequest
, TRUE
);
3403 FreePool (ConfigInfo
->SyncConfigRequest
);
3404 ConfigInfo
->SyncConfigRequest
= NULL
;
3407 Status
= EFI_SUCCESS
;
3409 SendDiscardInfoToDriver (FormSet
,Form
);
3411 Status
= EFI_UNSUPPORTED
;
3415 // Free Form save fail list.
3417 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3418 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3419 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link
);
3420 RemoveEntryList (&ConfigInfo
->SaveFailLink
);
3425 // 5. Update the NV flag.
3427 ValueChangeResetFlagUpdate(TRUE
, FormSet
, Form
);
3430 // 6 Call callback with Submitted type to inform the driver.
3432 if (!SubmitFormFail
) {
3433 SubmitCallback (FormSet
, Form
);
3440 Submit data for a formset.
3442 @param FormSet FormSet data structure.
3443 @param SkipProcessFail Whether skip to process the save failed storage.
3444 If submit formset is called when do system level save,
3445 set this value to true and process the failed formset
3447 if submit formset is called when do formset level save,
3448 set the value to false and process the failed storage
3449 right after process all storages for this formset.
3451 @retval EFI_SUCCESS The function completed successfully.
3452 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3457 IN FORM_BROWSER_FORMSET
*FormSet
,
3458 IN BOOLEAN SkipProcessFail
3463 EFI_STRING ConfigResp
;
3464 EFI_STRING Progress
;
3465 BROWSER_STORAGE
*Storage
;
3466 FORMSET_STORAGE
*FormSetStorage
;
3467 FORM_BROWSER_FORM
*Form
;
3468 BOOLEAN HasInserted
;
3469 FORM_BROWSER_STATEMENT
*Question
;
3470 BOOLEAN SubmitFormSetFail
;
3471 BOOLEAN DiscardChange
;
3473 HasInserted
= FALSE
;
3474 SubmitFormSetFail
= FALSE
;
3475 DiscardChange
= FALSE
;
3477 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
3482 Status
= NoSubmitCheck (FormSet
, &Form
, &Question
);
3483 if (EFI_ERROR (Status
)) {
3484 if (SkipProcessFail
) {
3486 // Process NO_SUBMIT check first, so insert it at head.
3488 FormSet
->SaveFailForm
= Form
;
3489 FormSet
->SaveFailStatement
= Question
;
3490 InsertHeadList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3499 // Submit Buffer storage or Name/Value storage
3501 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3502 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3503 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
3504 Storage
= FormSetStorage
->BrowserStorage
;
3505 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3507 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3512 // Skip if there is no RequestElement
3514 if (FormSetStorage
->ElementCount
== 0) {
3519 // 1. Prepare <ConfigResp>
3521 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
3522 if (EFI_ERROR (Status
)) {
3527 // 2. Send <ConfigResp> to Routine config Protocol.
3529 Status
= mHiiConfigRouting
->RouteConfig (
3534 if (EFI_ERROR (Status
)) {
3536 // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.
3538 SubmitFormSetFail
= TRUE
;
3539 GetSyncRestoreConfigRequest (FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, Progress
, &FormSetStorage
->RestoreConfigRequest
, &FormSetStorage
->SyncConfigRequest
);
3540 InsertTailList (&FormSet
->SaveFailStorageListHead
, &FormSetStorage
->SaveFailLink
);
3543 // Call submit formset for system level, save the formset info
3544 // and process later.
3546 FindQuestionFromProgress(FormSet
, Storage
, Progress
, &Form
, &Question
);
3547 ASSERT (Form
!= NULL
&& Question
!= NULL
);
3548 FormSet
->SaveFailForm
= Form
;
3549 FormSet
->SaveFailStatement
= Question
;
3550 if (SkipProcessFail
) {
3551 InsertTailList (&gBrowserSaveFailFormSetList
, &FormSet
->SaveFailLink
);
3556 FreePool (ConfigResp
);
3560 FreePool (ConfigResp
);
3562 // 3. Config success, update storage shadow Buffer
3564 SynchronizeStorage (Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
3568 // 4. Has save fail storage need to handle.
3571 if (!SkipProcessFail
) {
3573 // If not in system level, just handl the save failed storage here.
3575 if (ConfirmSaveFail (Form
->FormTitle
, FormSet
->HiiHandle
) == BROWSER_ACTION_DISCARD
) {
3576 DiscardChange
= TRUE
;
3577 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3578 while (!IsNull (&FormSet
->SaveFailStorageListHead
, Link
)) {
3579 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3580 Storage
= FormSetStorage
->BrowserStorage
;
3581 Link
= GetNextNode (&FormSet
->SaveFailStorageListHead
, Link
);
3583 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3584 // base on the SyncConfigRequest to Sync the buffer.
3586 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3587 FreePool (FormSetStorage
->RestoreConfigRequest
);
3588 FormSetStorage
->RestoreConfigRequest
= NULL
;
3589 if (FormSetStorage
->SyncConfigRequest
!= NULL
) {
3590 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3591 FreePool (FormSetStorage
->SyncConfigRequest
);
3592 FormSetStorage
->SyncConfigRequest
= NULL
;
3595 Status
= EFI_SUCCESS
;
3598 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3600 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3601 gCurrentSelection
->Handle
= FormSet
->HiiHandle
;
3602 CopyGuid (&gCurrentSelection
->FormSetGuid
, &FormSet
->Guid
);
3603 gCurrentSelection
->FormId
= Form
->FormId
;
3604 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3606 Status
= EFI_UNSUPPORTED
;
3610 // Free FormSet save fail list.
3612 while (!IsListEmpty (&FormSet
->SaveFailStorageListHead
)) {
3613 Link
= GetFirstNode (&FormSet
->SaveFailStorageListHead
);
3614 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link
);
3615 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3619 // If in system level, just return error and handle the failed formset later.
3621 Status
= EFI_UNSUPPORTED
;
3626 // If user discard the change, send the discard info to driver.
3628 if (DiscardChange
) {
3629 Link
= GetFirstNode (&FormSet
->FormListHead
);
3630 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3631 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3632 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3634 // Call callback with Changed type to inform the driver.
3636 SendDiscardInfoToDriver (FormSet
, Form
);
3641 // 5. Update the NV flag.
3643 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
3646 // 6. Call callback with Submitted type to inform the driver.
3648 if (!SubmitFormSetFail
) {
3649 SubmitCallback (FormSet
, NULL
);
3656 Submit data for all formsets.
3658 @retval EFI_SUCCESS The function completed successfully.
3659 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3669 LIST_ENTRY
*FormLink
;
3670 LIST_ENTRY
*StorageLink
;
3671 FORMSET_STORAGE
*FormSetStorage
;
3672 FORM_BROWSER_FORM
*Form
;
3673 FORM_BROWSER_FORMSET
*LocalFormSet
;
3674 UINT32 UserSelection
;
3675 FORM_BROWSER_STATEMENT
*Question
;
3677 mSystemSubmit
= TRUE
;
3678 Link
= GetFirstNode (&gBrowserFormSetList
);
3679 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3680 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3681 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3682 if (!ValidateFormSet(LocalFormSet
)) {
3686 Status
= SubmitForFormSet (LocalFormSet
, TRUE
);
3687 if (EFI_ERROR (Status
)) {
3692 // Remove maintain backup list after save except for the current using FormSet.
3694 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3695 CleanBrowserStorage(LocalFormSet
);
3696 RemoveEntryList (&LocalFormSet
->Link
);
3697 DestroyFormSet (LocalFormSet
);
3700 mSystemSubmit
= FALSE
;
3702 Status
= EFI_SUCCESS
;
3705 // Process the save failed formsets.
3707 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3708 while (!IsNull (&gBrowserSaveFailFormSetList
, Link
)) {
3709 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3710 Link
= GetNextNode (&gBrowserSaveFailFormSetList
, Link
);
3712 if (!ValidateFormSet(LocalFormSet
)) {
3716 Form
= LocalFormSet
->SaveFailForm
;
3717 Question
= LocalFormSet
->SaveFailStatement
;
3720 // Confirm with user, get user input.
3722 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3724 // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.
3726 UserSelection
= ConfirmNoSubmitFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3728 UserSelection
= ConfirmSaveFail (Form
->FormTitle
, LocalFormSet
->HiiHandle
);
3731 if (UserSelection
== BROWSER_ACTION_DISCARD
) {
3732 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3733 StorageLink
= GetFirstNode (&LocalFormSet
->StorageListHead
);
3734 while (!IsNull (&LocalFormSet
->StorageListHead
, StorageLink
)) {
3735 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (StorageLink
);
3736 StorageLink
= GetNextNode (&LocalFormSet
->StorageListHead
, StorageLink
);
3738 SynchronizeStorage(FormSetStorage
->BrowserStorage
, FormSetStorage
->ConfigRequest
, FALSE
);
3741 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3742 while (!IsNull (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
)) {
3743 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3744 StorageLink
= GetNextNode (&LocalFormSet
->SaveFailStorageListHead
, StorageLink
);
3746 // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer
3747 // base on the SyncConfigRequest to Sync the buffer.
3749 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->RestoreConfigRequest
, FALSE
);
3750 FreePool (FormSetStorage
->RestoreConfigRequest
);
3751 FormSetStorage
->RestoreConfigRequest
= NULL
;
3752 if ( FormSetStorage
->SyncConfigRequest
!= NULL
) {
3753 SynchronizeStorage (FormSetStorage
->BrowserStorage
, FormSetStorage
->SyncConfigRequest
, TRUE
);
3754 FreePool (FormSetStorage
->SyncConfigRequest
);
3755 FormSetStorage
->SyncConfigRequest
= NULL
;
3760 FormLink
= GetFirstNode (&LocalFormSet
->FormListHead
);
3761 while (!IsNull (&LocalFormSet
->FormListHead
, FormLink
)) {
3762 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3763 FormLink
= GetNextNode (&LocalFormSet
->FormListHead
, FormLink
);
3765 // Call callback with Changed type to inform the driver.
3767 SendDiscardInfoToDriver (LocalFormSet
, Form
);
3770 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
3771 CleanBrowserStorage(LocalFormSet
);
3772 RemoveEntryList (&LocalFormSet
->Link
);
3773 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3774 DestroyFormSet (LocalFormSet
);
3776 ValueChangeResetFlagUpdate(FALSE
, LocalFormSet
, NULL
);
3779 if (IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3780 NoSubmitCheck (LocalFormSet
, &Form
, &Question
);
3783 UiCopyMenuList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &Form
->FormViewListHead
);
3785 gCurrentSelection
->Action
= UI_ACTION_REFRESH_FORMSET
;
3786 gCurrentSelection
->Handle
= LocalFormSet
->HiiHandle
;
3787 CopyGuid (&gCurrentSelection
->FormSetGuid
, &LocalFormSet
->Guid
);
3788 gCurrentSelection
->FormId
= Form
->FormId
;
3789 gCurrentSelection
->QuestionId
= Question
->QuestionId
;
3791 Status
= EFI_UNSUPPORTED
;
3797 // Clean the list which will not process.
3799 while (!IsListEmpty (&gBrowserSaveFailFormSetList
)) {
3800 Link
= GetFirstNode (&gBrowserSaveFailFormSetList
);
3801 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link
);
3802 RemoveEntryList (&LocalFormSet
->SaveFailLink
);
3804 while (!IsListEmpty (&LocalFormSet
->SaveFailStorageListHead
)) {
3805 StorageLink
= GetFirstNode (&LocalFormSet
->SaveFailStorageListHead
);
3806 FormSetStorage
= FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink
);
3807 RemoveEntryList (&FormSetStorage
->SaveFailLink
);
3815 Submit data based on the input Setting level (Form, FormSet or System).
3817 @param FormSet FormSet data structure.
3818 @param Form Form data structure.
3819 @param SettingScope Setting Scope for Submit action.
3821 @retval EFI_SUCCESS The function completed successfully.
3822 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3827 IN FORM_BROWSER_FORMSET
*FormSet
,
3828 IN FORM_BROWSER_FORM
*Form
,
3829 IN BROWSER_SETTING_SCOPE SettingScope
3834 switch (SettingScope
) {
3836 Status
= SubmitForForm(FormSet
, Form
);
3840 Status
= SubmitForFormSet (FormSet
, FALSE
);
3844 Status
= SubmitForSystem ();
3848 Status
= EFI_UNSUPPORTED
;
3856 Converts the unicode character of the string from uppercase to lowercase.
3857 This is a internal function.
3859 @param ConfigString String to be converted
3865 IN EFI_STRING ConfigString
3871 ASSERT (ConfigString
!= NULL
);
3874 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
3876 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
3877 if (*String
== L
'=') {
3879 } else if (*String
== L
'&') {
3881 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
3882 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
3888 Find the point in the ConfigResp string for this question.
3890 @param Question The question.
3891 @param ConfigResp Get ConfigResp string.
3893 @retval point to the offset where is for this question.
3897 GetOffsetFromConfigResp (
3898 IN FORM_BROWSER_STATEMENT
*Question
,
3899 IN CHAR16
*ConfigResp
3902 CHAR16
*RequestElement
;
3906 // Type is EFI_HII_VARSTORE_NAME_VALUE.
3908 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3909 RequestElement
= StrStr (ConfigResp
, Question
->VariableName
);
3910 if (RequestElement
!= NULL
) {
3912 // Skip the "VariableName=" field.
3914 RequestElement
+= StrLen (Question
->VariableName
) + 1;
3917 return RequestElement
;
3921 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
3925 // Convert all hex digits in ConfigResp to lower case before searching.
3927 HiiToLower (ConfigResp
);
3930 // 1. Directly use Question->BlockName to find.
3932 RequestElement
= StrStr (ConfigResp
, Question
->BlockName
);
3933 if (RequestElement
!= NULL
) {
3935 // Skip the "Question->BlockName&VALUE=" field.
3937 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3938 return RequestElement
;
3942 // 2. Change all hex digits in Question->BlockName to lower and compare again.
3944 BlockData
= AllocateCopyPool (StrSize(Question
->BlockName
), Question
->BlockName
);
3945 ASSERT (BlockData
!= NULL
);
3946 HiiToLower (BlockData
);
3947 RequestElement
= StrStr (ConfigResp
, BlockData
);
3948 FreePool (BlockData
);
3950 if (RequestElement
!= NULL
) {
3952 // Skip the "Question->BlockName&VALUE=" field.
3954 RequestElement
+= StrLen (Question
->BlockName
) + StrLen (L
"&VALUE=");
3957 return RequestElement
;
3961 Get Question default value from AltCfg string.
3963 @param FormSet The form set.
3964 @param Form The form
3965 @param Question The question.
3967 @retval EFI_SUCCESS Question is reset to default value.
3971 GetDefaultValueFromAltCfg (
3972 IN FORM_BROWSER_FORMSET
*FormSet
,
3973 IN FORM_BROWSER_FORM
*Form
,
3974 IN OUT FORM_BROWSER_STATEMENT
*Question
3977 BROWSER_STORAGE
*Storage
;
3978 FORMSET_STORAGE
*FormSetStorage
;
3982 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
3984 Storage
= Question
->Storage
;
3985 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3986 return EFI_NOT_FOUND
;
3990 // Try to get AltCfg string from form. If not found it, then
3991 // try to get it from formset.
3994 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
3995 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
3996 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
3997 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
3999 if (Storage
== ConfigInfo
->Storage
) {
4000 ConfigResp
= ConfigInfo
->ConfigAltResp
;
4005 if (ConfigResp
== NULL
) {
4006 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4007 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4008 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4009 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4011 if (Storage
== FormSetStorage
->BrowserStorage
) {
4012 ConfigResp
= FormSetStorage
->ConfigAltResp
;
4018 if (ConfigResp
== NULL
) {
4019 return EFI_NOT_FOUND
;
4022 Value
= GetOffsetFromConfigResp (Question
, ConfigResp
);
4023 if (Value
== NULL
) {
4024 return EFI_NOT_FOUND
;
4027 return BufferToValue (Question
, Value
);
4031 Get default Id value used for browser.
4033 @param DefaultId The default id value used by hii.
4035 @retval Browser used default value.
4039 GetDefaultIdForCallBack (
4043 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
4044 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
4045 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4046 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
4047 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
4048 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
4049 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
4050 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
4051 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
4052 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
4053 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
4054 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
4063 Return data element in an Array by its Index.
4065 @param Array The data array.
4066 @param Type Type of the data in this array.
4067 @param Index Zero based index for data in this array.
4069 @retval Value The data to be returned
4081 ASSERT (Array
!= NULL
);
4085 case EFI_IFR_TYPE_NUM_SIZE_8
:
4086 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
4089 case EFI_IFR_TYPE_NUM_SIZE_16
:
4090 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
4093 case EFI_IFR_TYPE_NUM_SIZE_32
:
4094 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
4097 case EFI_IFR_TYPE_NUM_SIZE_64
:
4098 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
4110 Set value of a data element in an Array by its Index.
4112 @param Array The data array.
4113 @param Type Type of the data in this array.
4114 @param Index Zero based index for data in this array.
4115 @param Value The value to be set.
4127 ASSERT (Array
!= NULL
);
4130 case EFI_IFR_TYPE_NUM_SIZE_8
:
4131 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
4134 case EFI_IFR_TYPE_NUM_SIZE_16
:
4135 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
4138 case EFI_IFR_TYPE_NUM_SIZE_32
:
4139 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
4142 case EFI_IFR_TYPE_NUM_SIZE_64
:
4143 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
4152 Search an Option of a Question by its value.
4154 @param Question The Question
4155 @param OptionValue Value for Option to be searched.
4157 @retval Pointer Pointer to the found Option.
4158 @retval NULL Option not found.
4163 IN FORM_BROWSER_STATEMENT
*Question
,
4164 IN EFI_HII_VALUE
*OptionValue
4168 QUESTION_OPTION
*Option
;
4171 Link
= GetFirstNode (&Question
->OptionListHead
);
4172 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4173 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4175 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
4177 // Check the suppressif condition, only a valid option can be return.
4179 if ((Option
->SuppressExpression
== NULL
) ||
4180 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
4185 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4193 Reset Question to its default value.
4195 @param FormSet The form set.
4196 @param Form The form.
4197 @param Question The question.
4198 @param DefaultId The Class of the default.
4200 @retval EFI_SUCCESS Question is reset to default value.
4204 GetQuestionDefault (
4205 IN FORM_BROWSER_FORMSET
*FormSet
,
4206 IN FORM_BROWSER_FORM
*Form
,
4207 IN FORM_BROWSER_STATEMENT
*Question
,
4213 QUESTION_DEFAULT
*Default
;
4214 QUESTION_OPTION
*Option
;
4215 EFI_HII_VALUE
*HiiValue
;
4217 EFI_STRING StrValue
;
4218 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4219 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4222 EFI_IFR_TYPE_VALUE
*TypeValue
;
4223 UINT16 OriginalDefaultId
;
4224 FORMSET_DEFAULTSTORE
*DefaultStore
;
4225 LIST_ENTRY
*DefaultLink
;
4227 Status
= EFI_NOT_FOUND
;
4229 OriginalDefaultId
= DefaultId
;
4230 DefaultLink
= GetFirstNode (&FormSet
->DefaultStoreListHead
);
4233 // Statement don't have storage, skip them
4235 if (Question
->QuestionId
== 0) {
4240 // There are Five ways to specify default value for a Question:
4241 // 1, use call back function (highest priority)
4242 // 2, use ExtractConfig function
4243 // 3, use nested EFI_IFR_DEFAULT
4244 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
4245 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
4248 HiiValue
= &Question
->HiiValue
;
4249 TypeValue
= &HiiValue
->Value
;
4250 if (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
) {
4252 // For orderedlist, need to pass the BufferValue to Callback function.
4254 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
4258 // Get Question defaut value from call back function.
4260 ConfigAccess
= FormSet
->ConfigAccess
;
4261 Action
= GetDefaultIdForCallBack (DefaultId
);
4262 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
4263 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
4264 Status
= ConfigAccess
->Callback (
4267 Question
->QuestionId
,
4272 if (!EFI_ERROR (Status
)) {
4273 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4274 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
4275 ASSERT (NewString
!= NULL
);
4277 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
4278 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
4279 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4280 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
4282 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
4285 FreePool (NewString
);
4292 // Get default value from altcfg string.
4294 if (ConfigAccess
!= NULL
) {
4295 Status
= GetDefaultValueFromAltCfg(FormSet
, Form
, Question
);
4296 if (!EFI_ERROR (Status
)) {
4302 // EFI_IFR_DEFAULT has highest priority
4304 if (!IsListEmpty (&Question
->DefaultListHead
)) {
4305 Link
= GetFirstNode (&Question
->DefaultListHead
);
4306 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
4307 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
4309 if (Default
->DefaultId
== DefaultId
) {
4310 if (Default
->ValueExpression
!= NULL
) {
4312 // Default is provided by an Expression, evaluate it
4314 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
4315 if (EFI_ERROR (Status
)) {
4319 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
4320 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
4321 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
4322 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
4323 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
4325 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
4326 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
4328 FreePool (Default
->ValueExpression
->Result
.Buffer
);
4330 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
4331 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
4334 // Default value is embedded in EFI_IFR_DEFAULT
4336 if (Default
->Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
4337 ASSERT (HiiValue
->Buffer
!= NULL
);
4338 CopyMem (HiiValue
->Buffer
, Default
->Value
.Buffer
, Default
->Value
.BufferLen
);
4340 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
4344 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
4345 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
4346 if (StrValue
== NULL
) {
4347 return EFI_NOT_FOUND
;
4349 if (Question
->StorageWidth
> StrSize (StrValue
)) {
4350 ZeroMem (Question
->BufferValue
, Question
->StorageWidth
);
4351 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
4353 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
4360 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
4365 // EFI_ONE_OF_OPTION
4367 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
4368 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4370 // OneOfOption could only provide Standard and Manufacturing default
4372 Link
= GetFirstNode (&Question
->OptionListHead
);
4373 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4374 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4375 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4377 if ((Option
->SuppressExpression
!= NULL
) &&
4378 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4382 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
4383 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
4385 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4394 // EFI_IFR_CHECKBOX - lowest priority
4396 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
4397 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
4399 // Checkbox could only provide Standard and Manufacturing default
4401 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
4402 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
4404 HiiValue
->Value
.b
= TRUE
;
4412 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
4413 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
4414 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
4416 while (!IsNull(&FormSet
->DefaultStoreListHead
, DefaultLink
)) {
4417 DefaultStore
= FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink
);
4418 DefaultLink
= GetNextNode (&FormSet
->DefaultStoreListHead
,DefaultLink
);
4419 DefaultId
= DefaultStore
->DefaultId
;
4420 if (DefaultId
== OriginalDefaultId
) {
4427 // For Questions without default value for all the default id in the DefaultStoreList.
4429 Status
= EFI_NOT_FOUND
;
4430 switch (Question
->Operand
) {
4431 case EFI_IFR_CHECKBOX_OP
:
4432 HiiValue
->Value
.b
= FALSE
;
4433 Status
= EFI_SUCCESS
;
4436 case EFI_IFR_NUMERIC_OP
:
4438 // Take minimum value as numeric default value
4440 if ((Question
->Flags
& EFI_IFR_DISPLAY
) == 0) {
4442 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
4444 switch (Question
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
4445 case EFI_IFR_NUMERIC_SIZE_1
:
4446 if (((INT8
) HiiValue
->Value
.u8
< (INT8
) Question
->Minimum
) || ((INT8
) HiiValue
->Value
.u8
> (INT8
) Question
->Maximum
)) {
4447 HiiValue
->Value
.u8
= (UINT8
) Question
->Minimum
;
4448 Status
= EFI_SUCCESS
;
4451 case EFI_IFR_NUMERIC_SIZE_2
:
4452 if (((INT16
) HiiValue
->Value
.u16
< (INT16
) Question
->Minimum
) || ((INT16
) HiiValue
->Value
.u16
> (INT16
) Question
->Maximum
)) {
4453 HiiValue
->Value
.u16
= (UINT16
) Question
->Minimum
;
4454 Status
= EFI_SUCCESS
;
4457 case EFI_IFR_NUMERIC_SIZE_4
:
4458 if (((INT32
) HiiValue
->Value
.u32
< (INT32
) Question
->Minimum
) || ((INT32
) HiiValue
->Value
.u32
> (INT32
) Question
->Maximum
)) {
4459 HiiValue
->Value
.u32
= (UINT32
) Question
->Minimum
;
4460 Status
= EFI_SUCCESS
;
4463 case EFI_IFR_NUMERIC_SIZE_8
:
4464 if (((INT64
) HiiValue
->Value
.u64
< (INT64
) Question
->Minimum
) || ((INT64
) HiiValue
->Value
.u64
> (INT64
) Question
->Maximum
)) {
4465 HiiValue
->Value
.u64
= Question
->Minimum
;
4466 Status
= EFI_SUCCESS
;
4473 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
4474 HiiValue
->Value
.u64
= Question
->Minimum
;
4475 Status
= EFI_SUCCESS
;
4480 case EFI_IFR_ONE_OF_OP
:
4482 // Take first oneof option as oneof's default value
4484 if (ValueToOption (Question
, HiiValue
) == NULL
) {
4485 Link
= GetFirstNode (&Question
->OptionListHead
);
4486 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4487 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4488 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4490 if ((Option
->SuppressExpression
!= NULL
) &&
4491 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4495 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
4496 Status
= EFI_SUCCESS
;
4502 case EFI_IFR_ORDERED_LIST_OP
:
4504 // Take option sequence in IFR as ordered list's default value
4507 Link
= GetFirstNode (&Question
->OptionListHead
);
4508 while (!IsNull (&Question
->OptionListHead
, Link
)) {
4509 Status
= EFI_SUCCESS
;
4510 Option
= QUESTION_OPTION_FROM_LINK (Link
);
4511 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
4513 if ((Option
->SuppressExpression
!= NULL
) &&
4514 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
4518 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
4521 if (Index
>= Question
->MaxContainers
) {
4535 Get AltCfg string for current form.
4537 @param FormSet Form data structure.
4538 @param Form Form data structure.
4539 @param DefaultId The Class of the default.
4540 @param BrowserStorage The input request storage for the questions.
4544 ExtractAltCfgForForm (
4545 IN FORM_BROWSER_FORMSET
*FormSet
,
4546 IN FORM_BROWSER_FORM
*Form
,
4547 IN UINT16 DefaultId
,
4548 IN BROWSER_STORAGE
*BrowserStorage
4556 BROWSER_STORAGE
*Storage
;
4557 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4558 FORMSET_STORAGE
*FormSetStorage
;
4561 // Check whether has get AltCfg string for this formset.
4562 // If yes, no need to get AltCfg for form.
4564 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4565 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4566 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4567 Storage
= FormSetStorage
->BrowserStorage
;
4568 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4569 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4573 if (Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
&&
4574 FormSetStorage
->ElementCount
!= 0 &&
4575 FormSetStorage
->HasCallAltCfg
) {
4581 // Get AltCfg string for each form.
4583 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4584 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4585 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4586 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4588 Storage
= ConfigInfo
->Storage
;
4589 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4593 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4598 // 1. Skip if there is no RequestElement
4600 if (ConfigInfo
->ElementCount
== 0) {
4605 // 2. Get value through hii config routine protocol.
4607 Status
= mHiiConfigRouting
->ExtractConfig (
4609 ConfigInfo
->ConfigRequest
,
4613 if (EFI_ERROR (Status
)) {
4618 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4619 // Get the default configuration string according to the default ID.
4621 Status
= mHiiConfigRouting
->GetAltConfig (
4627 &DefaultId
, // it can be NULL to get the current setting.
4631 if (EFI_ERROR (Status
)) {
4635 ConfigInfo
->ConfigAltResp
= ConfigResp
;
4640 Clean AltCfg string for current form.
4642 @param Form Form data structure.
4646 CleanAltCfgForForm (
4647 IN FORM_BROWSER_FORM
*Form
4651 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
4653 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
4654 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
4655 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
4656 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
4658 if (ConfigInfo
->ConfigAltResp
!= NULL
) {
4659 FreePool (ConfigInfo
->ConfigAltResp
);
4660 ConfigInfo
->ConfigAltResp
= NULL
;
4666 Get AltCfg string for current formset.
4668 @param FormSet Form data structure.
4669 @param DefaultId The Class of the default.
4670 @param BrowserStorage The input request storage for the questions.
4674 ExtractAltCfgForFormSet (
4675 IN FORM_BROWSER_FORMSET
*FormSet
,
4676 IN UINT16 DefaultId
,
4677 IN BROWSER_STORAGE
*BrowserStorage
4685 BROWSER_STORAGE
*Storage
;
4686 FORMSET_STORAGE
*FormSetStorage
;
4688 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4689 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4690 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4691 Storage
= FormSetStorage
->BrowserStorage
;
4692 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4694 if (BrowserStorage
!= NULL
&& BrowserStorage
!= Storage
) {
4698 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
4703 // 1. Skip if there is no RequestElement
4705 if (FormSetStorage
->ElementCount
== 0) {
4709 FormSetStorage
->HasCallAltCfg
= TRUE
;
4712 // 2. Get value through hii config routine protocol.
4714 Status
= mHiiConfigRouting
->ExtractConfig (
4716 FormSetStorage
->ConfigRequest
,
4720 if (EFI_ERROR (Status
)) {
4725 // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
4726 // Get the default configuration string according to the default ID.
4728 Status
= mHiiConfigRouting
->GetAltConfig (
4734 &DefaultId
, // it can be NULL to get the current setting.
4739 if (EFI_ERROR (Status
)) {
4743 FormSetStorage
->ConfigAltResp
= ConfigResp
;
4749 Clean AltCfg string for current formset.
4751 @param FormSet Form data structure.
4755 CleanAltCfgForFormSet (
4756 IN FORM_BROWSER_FORMSET
*FormSet
4760 FORMSET_STORAGE
*FormSetStorage
;
4762 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4763 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4764 FormSetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
4765 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4767 if (FormSetStorage
->ConfigAltResp
!= NULL
) {
4768 FreePool (FormSetStorage
->ConfigAltResp
);
4769 FormSetStorage
->ConfigAltResp
= NULL
;
4772 FormSetStorage
->HasCallAltCfg
= FALSE
;
4777 Reset Questions to their initial value or default value in a Form, Formset or System.
4779 GetDefaultValueScope parameter decides which questions will reset
4780 to its default value.
4782 @param FormSet FormSet data structure.
4783 @param Form Form data structure.
4784 @param DefaultId The Class of the default.
4785 @param SettingScope Setting Scope for Default action.
4786 @param GetDefaultValueScope Get default value scope.
4787 @param Storage Get default value only for this storage.
4788 @param RetrieveValueFirst Whether call the retrieve call back to
4789 get the initial value before get default
4791 @param SkipGetAltCfg Whether skip the get altcfg string process.
4793 @retval EFI_SUCCESS The function completed successfully.
4794 @retval EFI_UNSUPPORTED Unsupport SettingScope.
4799 IN FORM_BROWSER_FORMSET
*FormSet
,
4800 IN FORM_BROWSER_FORM
*Form
,
4801 IN UINT16 DefaultId
,
4802 IN BROWSER_SETTING_SCOPE SettingScope
,
4803 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
4804 IN BROWSER_STORAGE
*Storage OPTIONAL
,
4805 IN BOOLEAN RetrieveValueFirst
,
4806 IN BOOLEAN SkipGetAltCfg
4810 LIST_ENTRY
*FormLink
;
4812 FORM_BROWSER_STATEMENT
*Question
;
4813 FORM_BROWSER_FORMSET
*LocalFormSet
;
4814 FORM_BROWSER_FORMSET
*OldFormSet
;
4816 Status
= EFI_SUCCESS
;
4819 // Check the supported setting level.
4821 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
4822 return EFI_UNSUPPORTED
;
4825 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
4826 return EFI_UNSUPPORTED
;
4829 if (SettingScope
== FormLevel
) {
4831 // Prepare the AltCfg String for form.
4833 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4834 ExtractAltCfgForForm (FormSet
, Form
, DefaultId
, Storage
);
4838 // Extract Form default
4840 Link
= GetFirstNode (&Form
->StatementListHead
);
4841 while (!IsNull (&Form
->StatementListHead
, Link
)) {
4842 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
4843 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
4846 // If get default value only for this storage, check the storage first.
4848 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
4853 // If get default value only for no storage question, just skip the question which has storage.
4855 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
4860 // If Question is disabled, don't reset it to default
4862 if (Question
->Expression
!= NULL
) {
4863 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
4868 if (RetrieveValueFirst
) {
4870 // Call the Retrieve call back to get the initial question value.
4872 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
4876 // If not request to get the initial value or get initial value fail, then get default value.
4878 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
4879 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
4880 if (EFI_ERROR (Status
)) {
4886 // Synchronize Buffer storage's Edit buffer
4888 if ((Question
->Storage
!= NULL
) &&
4889 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
4890 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
4895 // Clean the AltCfg String.
4897 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4898 CleanAltCfgForForm(Form
);
4900 } else if (SettingScope
== FormSetLevel
) {
4902 // Prepare the AltCfg String for formset.
4904 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4905 ExtractAltCfgForFormSet (FormSet
, DefaultId
, Storage
);
4908 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
4909 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
4910 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
4911 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4912 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
4916 // Clean the AltCfg String.
4918 if (!SkipGetAltCfg
&& (GetDefaultValueScope
!= GetDefaultForNoStorage
)) {
4919 CleanAltCfgForFormSet (FormSet
);
4921 } else if (SettingScope
== SystemLevel
) {
4923 // Preload all Hii formset.
4925 LoadAllHiiFormset();
4927 OldFormSet
= mSystemLevelFormSet
;
4930 // Set Default Value for each FormSet in the maintain list.
4932 Link
= GetFirstNode (&gBrowserFormSetList
);
4933 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4934 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4935 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4936 if (!ValidateFormSet(LocalFormSet
)) {
4940 mSystemLevelFormSet
= LocalFormSet
;
4942 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
, SkipGetAltCfg
);
4945 mSystemLevelFormSet
= OldFormSet
;
4953 Validate whether this question's value has changed.
4955 @param FormSet FormSet data structure.
4956 @param Form Form data structure.
4957 @param Question Question to be initialized.
4958 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
4960 @retval TRUE Question's value has changed.
4961 @retval FALSE Question's value has not changed
4965 IsQuestionValueChanged (
4966 IN FORM_BROWSER_FORMSET
*FormSet
,
4967 IN FORM_BROWSER_FORM
*Form
,
4968 IN OUT FORM_BROWSER_STATEMENT
*Question
,
4969 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
4972 EFI_HII_VALUE BackUpValue
;
4973 CHAR8
*BackUpBuffer
;
4974 EFI_HII_VALUE BackUpValue2
;
4975 CHAR8
*BackUpBuffer2
;
4977 BOOLEAN ValueChanged
;
4981 // For quetion without storage, always mark it as data not changed.
4983 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
4987 BackUpBuffer
= NULL
;
4988 BackUpBuffer2
= NULL
;
4989 ValueChanged
= FALSE
;
4991 switch (Question
->Operand
) {
4992 case EFI_IFR_ORDERED_LIST_OP
:
4993 BufferWidth
= Question
->StorageWidth
;
4994 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
4995 ASSERT (BackUpBuffer
!= NULL
);
4998 case EFI_IFR_STRING_OP
:
4999 case EFI_IFR_PASSWORD_OP
:
5000 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5001 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5002 ASSERT (BackUpBuffer
!= NULL
);
5009 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5011 if (GetValueFrom
== GetSetValueWithBothBuffer
) {
5012 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5013 ASSERT_EFI_ERROR(Status
);
5015 switch (Question
->Operand
) {
5016 case EFI_IFR_ORDERED_LIST_OP
:
5017 BufferWidth
= Question
->StorageWidth
;
5018 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5019 ASSERT (BackUpBuffer2
!= NULL
);
5022 case EFI_IFR_STRING_OP
:
5023 case EFI_IFR_PASSWORD_OP
:
5024 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
5025 BackUpBuffer2
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
5026 ASSERT (BackUpBuffer2
!= NULL
);
5033 CopyMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
5035 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
5036 ASSERT_EFI_ERROR(Status
);
5038 if (CompareMem (&BackUpValue2
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5039 CompareMem (BackUpBuffer2
, Question
->BufferValue
, BufferWidth
) != 0) {
5040 ValueChanged
= TRUE
;
5043 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
5044 ASSERT_EFI_ERROR(Status
);
5046 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
5047 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
5048 ValueChanged
= TRUE
;
5052 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
5053 if (BackUpBuffer
!= NULL
) {
5054 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
5055 FreePool (BackUpBuffer
);
5058 if (BackUpBuffer2
!= NULL
) {
5059 FreePool (BackUpBuffer2
);
5062 Question
->ValueChanged
= ValueChanged
;
5064 return ValueChanged
;
5068 Initialize Question's Edit copy from Storage.
5070 @param Selection Selection contains the information about
5071 the Selection, form and formset to be displayed.
5072 Selection action may be updated in retrieve callback.
5073 If Selection is NULL, only initialize Question value.
5074 @param FormSet FormSet data structure.
5075 @param Form Form data structure.
5077 @retval EFI_SUCCESS The function completed successfully.
5082 IN OUT UI_MENU_SELECTION
*Selection
,
5083 IN FORM_BROWSER_FORMSET
*FormSet
,
5084 IN FORM_BROWSER_FORM
*Form
5089 FORM_BROWSER_STATEMENT
*Question
;
5091 Link
= GetFirstNode (&Form
->StatementListHead
);
5092 while (!IsNull (&Form
->StatementListHead
, Link
)) {
5093 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
5096 // Initialize local copy of Value for each Question
5098 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
5099 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
5101 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
5103 if (EFI_ERROR (Status
)) {
5107 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
5108 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
5111 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
5118 Initialize Question's Edit copy from Storage for the whole Formset.
5120 @param Selection Selection contains the information about
5121 the Selection, form and formset to be displayed.
5122 Selection action may be updated in retrieve callback.
5123 If Selection is NULL, only initialize Question value.
5124 @param FormSet FormSet data structure.
5126 @retval EFI_SUCCESS The function completed successfully.
5131 IN OUT UI_MENU_SELECTION
*Selection
,
5132 IN FORM_BROWSER_FORMSET
*FormSet
5137 FORM_BROWSER_FORM
*Form
;
5139 Link
= GetFirstNode (&FormSet
->FormListHead
);
5140 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
5141 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5144 // Initialize local copy of Value for each Form
5146 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
5147 if (EFI_ERROR (Status
)) {
5151 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
5155 // Finished question initialization.
5157 FormSet
->QuestionInited
= TRUE
;
5163 Remove the Request element from the Config Request.
5165 @param Storage Pointer to the browser storage.
5166 @param RequestElement The pointer to the Request element.
5171 IN OUT BROWSER_STORAGE
*Storage
,
5172 IN CHAR16
*RequestElement
5178 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
5180 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
5182 if (NewStr
== NULL
) {
5187 // Remove this element from this ConfigRequest.
5190 NewStr
+= StrLen (RequestElement
);
5191 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
5193 Storage
->SpareStrLen
+= StrLen (RequestElement
);
5197 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
5199 @param Storage Pointer to the formset storage.
5200 @param ConfigRequest The pointer to the Request element.
5204 RemoveConfigRequest (
5205 FORMSET_STORAGE
*Storage
,
5206 CHAR16
*ConfigRequest
5209 CHAR16
*RequestElement
;
5210 CHAR16
*NextRequestElement
;
5214 // No request element in it, just return.
5216 if (ConfigRequest
== NULL
) {
5220 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5222 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5227 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5229 SearchKey
= L
"&OFFSET";
5233 // Find SearchKey storage
5235 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5236 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5237 ASSERT (RequestElement
!= NULL
);
5238 RequestElement
= StrStr (RequestElement
, SearchKey
);
5240 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5243 while (RequestElement
!= NULL
) {
5245 // +1 to avoid find header itself.
5247 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5250 // The last Request element in configRequest string.
5252 if (NextRequestElement
!= NULL
) {
5254 // Replace "&" with '\0'.
5256 *NextRequestElement
= L
'\0';
5259 RemoveElement (Storage
->BrowserStorage
, RequestElement
);
5261 if (NextRequestElement
!= NULL
) {
5263 // Restore '&' with '\0' for later used.
5265 *NextRequestElement
= L
'&';
5268 RequestElement
= NextRequestElement
;
5272 // If no request element remain, just remove the ConfigRequest string.
5274 if (StrCmp (Storage
->BrowserStorage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
5275 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5276 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5277 Storage
->BrowserStorage
->SpareStrLen
= 0;
5282 Base on the current formset info, clean the ConfigRequest string in browser storage.
5284 @param FormSet Pointer of the FormSet
5288 CleanBrowserStorage (
5289 IN OUT FORM_BROWSER_FORMSET
*FormSet
5293 FORMSET_STORAGE
*Storage
;
5295 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5296 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5297 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5298 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5300 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
5301 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
5305 RemoveConfigRequest (Storage
, Storage
->ConfigRequest
);
5306 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
5307 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5308 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5309 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
5310 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
5312 Storage
->BrowserStorage
->Initialized
= FALSE
;
5318 Check whether current element in the ConfigReqeust string.
5320 @param BrowserStorage Storage which includes ConfigReqeust.
5321 @param RequestElement New element need to check.
5323 @retval TRUE The Element is in the ConfigReqeust string.
5324 @retval FALSE The Element not in the configReqeust String.
5329 BROWSER_STORAGE
*BrowserStorage
,
5330 CHAR16
*RequestElement
5333 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
5337 Append the Request element to the Config Request.
5339 @param ConfigRequest Current ConfigRequest info.
5340 @param SpareStrLen Current remain free buffer for config reqeust.
5341 @param RequestElement New Request element.
5345 AppendConfigRequest (
5346 IN OUT CHAR16
**ConfigRequest
,
5347 IN OUT UINTN
*SpareStrLen
,
5348 IN CHAR16
*RequestElement
5356 StrLength
= StrLen (RequestElement
);
5357 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
5358 MaxLen
= StringSize
/ sizeof (CHAR16
) + *SpareStrLen
;
5361 // Append <RequestElement> to <ConfigRequest>
5363 if (StrLength
> *SpareStrLen
) {
5365 // Old String buffer is not sufficient for RequestElement, allocate a new one
5367 MaxLen
= StringSize
/ sizeof (CHAR16
) + CONFIG_REQUEST_STRING_INCREMENTAL
;
5368 NewStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
5369 ASSERT (NewStr
!= NULL
);
5371 if (*ConfigRequest
!= NULL
) {
5372 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
5373 FreePool (*ConfigRequest
);
5375 *ConfigRequest
= NewStr
;
5376 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
5379 StrCatS (*ConfigRequest
, MaxLen
, RequestElement
);
5380 *SpareStrLen
-= StrLength
;
5384 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
5386 @param Storage Form set Storage.
5387 @param Request The input request string.
5388 @param RespString Whether the input is ConfigRequest or ConfigResp format.
5390 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
5391 @retval FALSE All elements covered by current used elements.
5395 ConfigRequestAdjust (
5396 IN BROWSER_STORAGE
*Storage
,
5398 IN BOOLEAN RespString
5401 CHAR16
*RequestElement
;
5402 CHAR16
*NextRequestElement
;
5403 CHAR16
*NextElementBakup
;
5407 CHAR16
*ConfigRequest
;
5410 NextElementBakup
= NULL
;
5413 if (Request
!= NULL
) {
5414 ConfigRequest
= Request
;
5416 ConfigRequest
= Storage
->ConfigRequest
;
5419 if (Storage
->ConfigRequest
== NULL
) {
5420 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5424 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5426 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
5431 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
5433 SearchKey
= L
"&OFFSET";
5434 ValueKey
= L
"&VALUE";
5438 // Find SearchKey storage
5440 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
5441 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
5442 ASSERT (RequestElement
!= NULL
);
5443 RequestElement
= StrStr (RequestElement
, SearchKey
);
5445 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
5448 while (RequestElement
!= NULL
) {
5451 // +1 to avoid find header itself.
5453 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
5456 // The last Request element in configRequest string.
5458 if (NextRequestElement
!= NULL
) {
5459 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5460 NextElementBakup
= NextRequestElement
;
5461 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5462 ASSERT (NextRequestElement
!= NULL
);
5465 // Replace "&" with '\0'.
5467 *NextRequestElement
= L
'\0';
5469 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5470 NextElementBakup
= NextRequestElement
;
5471 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
5472 ASSERT (NextRequestElement
!= NULL
);
5474 // Replace "&" with '\0'.
5476 *NextRequestElement
= L
'\0';
5480 if (!ElementValidation (Storage
, RequestElement
)) {
5482 // Add this element to the Storage->BrowserStorage->AllRequestElement.
5484 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
5488 if (NextRequestElement
!= NULL
) {
5490 // Restore '&' with '\0' for later used.
5492 *NextRequestElement
= L
'&';
5495 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
5496 RequestElement
= NextElementBakup
;
5498 RequestElement
= NextRequestElement
;
5506 Fill storage's edit copy with settings requested from Configuration Driver.
5508 @param FormSet FormSet data structure.
5509 @param Storage Buffer Storage.
5514 IN FORM_BROWSER_FORMSET
*FormSet
,
5515 IN FORMSET_STORAGE
*Storage
5519 EFI_STRING Progress
;
5522 EFI_STRING ConfigRequest
;
5525 ConfigRequest
= NULL
;
5527 switch (Storage
->BrowserStorage
->Type
) {
5528 case EFI_HII_VARSTORE_EFI_VARIABLE
:
5531 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
5532 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
5533 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5538 case EFI_HII_VARSTORE_BUFFER
:
5539 case EFI_HII_VARSTORE_NAME_VALUE
:
5541 // Skip if there is no RequestElement.
5543 if (Storage
->ElementCount
== 0) {
5548 // Just update the ConfigRequest, if storage already initialized.
5550 if (Storage
->BrowserStorage
->Initialized
) {
5551 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
5555 Storage
->BrowserStorage
->Initialized
= TRUE
;
5562 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5564 // Create the config request string to get all fields for this storage.
5565 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
5566 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
5568 StrLen
= StrSize (Storage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
5569 ConfigRequest
= AllocateZeroPool (StrLen
);
5570 ASSERT (ConfigRequest
!= NULL
);
5574 L
"%s&OFFSET=0&WIDTH=%04x",
5576 Storage
->BrowserStorage
->Size
);
5578 ConfigRequest
= Storage
->ConfigRequest
;
5582 // Request current settings from Configuration Driver
5584 Status
= mHiiConfigRouting
->ExtractConfig (
5592 // If get value fail, extract default from IFR binary
5594 if (EFI_ERROR (Status
)) {
5595 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
, TRUE
);
5598 // Convert Result from <ConfigAltResp> to <ConfigResp>
5600 StrPtr
= StrStr (Result
, L
"&GUID=");
5601 if (StrPtr
!= NULL
) {
5605 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
5609 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
5612 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
5614 SynchronizeStorage(Storage
->BrowserStorage
, NULL
, TRUE
);
5616 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
5617 if (ConfigRequest
!= NULL
) {
5618 FreePool (ConfigRequest
);
5624 Get Value changed status from old question.
5626 @param NewFormSet FormSet data structure.
5627 @param OldQuestion Old question which has value changed.
5631 SyncStatusForQuestion (
5632 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5633 IN FORM_BROWSER_STATEMENT
*OldQuestion
5637 LIST_ENTRY
*QuestionLink
;
5638 FORM_BROWSER_FORM
*Form
;
5639 FORM_BROWSER_STATEMENT
*Question
;
5642 // For each form in one formset.
5644 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
5645 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
5646 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5647 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
5650 // for each question in one form.
5652 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5653 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5654 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5655 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5657 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
5658 Question
->ValueChanged
= TRUE
;
5666 Get Value changed status from old formset.
5668 @param NewFormSet FormSet data structure.
5669 @param OldFormSet FormSet data structure.
5673 SyncStatusForFormSet (
5674 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
5675 IN FORM_BROWSER_FORMSET
*OldFormSet
5679 LIST_ENTRY
*QuestionLink
;
5680 FORM_BROWSER_FORM
*Form
;
5681 FORM_BROWSER_STATEMENT
*Question
;
5684 // For each form in one formset.
5686 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
5687 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
5688 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
5689 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
5692 // for each question in one form.
5694 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
5695 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
5696 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
5697 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
5699 if (!Question
->ValueChanged
) {
5704 // Find the same question in new formset and update the value changed flag.
5706 SyncStatusForQuestion (NewFormSet
, Question
);
5712 Get current setting of Questions.
5714 @param FormSet FormSet data structure.
5718 InitializeCurrentSetting (
5719 IN OUT FORM_BROWSER_FORMSET
*FormSet
5723 FORMSET_STORAGE
*Storage
;
5724 FORM_BROWSER_FORMSET
*OldFormSet
;
5727 // Try to find pre FormSet in the maintain backup list.
5728 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
5730 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
5731 if (OldFormSet
!= NULL
) {
5732 SyncStatusForFormSet (FormSet
, OldFormSet
);
5733 RemoveEntryList (&OldFormSet
->Link
);
5734 DestroyFormSet (OldFormSet
);
5736 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
5739 // Extract default from IFR binary for no storage questions.
5741 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
, FALSE
);
5744 // Request current settings from Configuration Driver
5746 Link
= GetFirstNode (&FormSet
->StorageListHead
);
5747 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
5748 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
5750 LoadStorage (FormSet
, Storage
);
5752 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
5758 Fetch the Ifr binary data of a FormSet.
5760 @param Handle PackageList Handle
5761 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5762 specified (NULL or zero GUID), take the first
5763 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5764 found in package list.
5765 On output, GUID of the formset found(if not NULL).
5766 @param BinaryLength The length of the FormSet IFR binary.
5767 @param BinaryData The buffer designed to receive the FormSet.
5769 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
5770 BufferLength was updated.
5771 @retval EFI_INVALID_PARAMETER The handle is unknown.
5772 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
5773 be found with the requested FormId.
5778 IN EFI_HII_HANDLE Handle
,
5779 IN OUT EFI_GUID
*FormSetGuid
,
5780 OUT UINTN
*BinaryLength
,
5781 OUT UINT8
**BinaryData
5785 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
5791 UINT32 PackageListLength
;
5792 EFI_HII_PACKAGE_HEADER PackageHeader
;
5794 UINT8 NumberOfClassGuid
;
5795 BOOLEAN ClassGuidMatch
;
5796 EFI_GUID
*ClassGuid
;
5797 EFI_GUID
*ComparingGuid
;
5801 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
5804 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
5806 if (FormSetGuid
== NULL
) {
5807 ComparingGuid
= &gZeroGuid
;
5809 ComparingGuid
= FormSetGuid
;
5813 // Get HII PackageList
5816 HiiPackageList
= NULL
;
5817 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5818 if (Status
== EFI_BUFFER_TOO_SMALL
) {
5819 HiiPackageList
= AllocatePool (BufferSize
);
5820 ASSERT (HiiPackageList
!= NULL
);
5822 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
5824 if (EFI_ERROR (Status
)) {
5827 ASSERT (HiiPackageList
!= NULL
);
5830 // Get Form package from this HII package List
5832 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
5834 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
5836 ClassGuidMatch
= FALSE
;
5837 while (Offset
< PackageListLength
) {
5838 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
5839 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
5841 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
5843 // Search FormSet in this Form Package
5845 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
5846 while (Offset2
< PackageHeader
.Length
) {
5847 OpCodeData
= Package
+ Offset2
;
5849 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
5851 // Try to compare against formset GUID
5853 if (IsZeroGuid (FormSetGuid
) ||
5854 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
5858 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
5860 // Try to compare against formset class GUID
5862 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
5863 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
5864 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
5865 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
5866 ClassGuidMatch
= TRUE
;
5870 if (ClassGuidMatch
) {
5873 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
5874 ClassGuidMatch
= TRUE
;
5879 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
5882 if (Offset2
< PackageHeader
.Length
) {
5884 // Target formset found
5890 Offset
+= PackageHeader
.Length
;
5893 if (Offset
>= PackageListLength
) {
5895 // Form package not found in this Package List
5897 FreePool (HiiPackageList
);
5898 return EFI_NOT_FOUND
;
5901 if (FormSetGuid
!= NULL
) {
5903 // Return the FormSet GUID
5905 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
5909 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
5910 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
5911 // of the Form Package.
5913 *BinaryLength
= PackageHeader
.Length
- Offset2
;
5914 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
5916 FreePool (HiiPackageList
);
5918 if (*BinaryData
== NULL
) {
5919 return EFI_OUT_OF_RESOURCES
;
5927 Initialize the internal data structure of a FormSet.
5929 @param Handle PackageList Handle
5930 @param FormSetGuid On input, GUID or class GUID of a formset. If not
5931 specified (NULL or zero GUID), take the first
5932 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
5933 found in package list.
5934 On output, GUID of the formset found(if not NULL).
5935 @param FormSet FormSet data structure.
5937 @retval EFI_SUCCESS The function completed successfully.
5938 @retval EFI_NOT_FOUND The specified FormSet could not be found.
5943 IN EFI_HII_HANDLE Handle
,
5944 IN OUT EFI_GUID
*FormSetGuid
,
5945 OUT FORM_BROWSER_FORMSET
*FormSet
5949 EFI_HANDLE DriverHandle
;
5951 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
5952 if (EFI_ERROR (Status
)) {
5956 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
5957 FormSet
->HiiHandle
= Handle
;
5958 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
5959 FormSet
->QuestionInited
= FALSE
;
5962 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
5964 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
5965 if (EFI_ERROR (Status
)) {
5968 FormSet
->DriverHandle
= DriverHandle
;
5969 Status
= gBS
->HandleProtocol (
5971 &gEfiHiiConfigAccessProtocolGuid
,
5972 (VOID
**) &FormSet
->ConfigAccess
5974 if (EFI_ERROR (Status
)) {
5976 // Configuration Driver don't attach ConfigAccess protocol to its HII package
5977 // list, then there will be no configuration action required
5979 FormSet
->ConfigAccess
= NULL
;
5983 // Parse the IFR binary OpCodes
5985 Status
= ParseOpCodes (FormSet
);
5992 Save globals used by previous call to SendForm(). SendForm() may be called from
5993 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
5994 So, save globals of previous call to SendForm() and restore them upon exit.
5998 SaveBrowserContext (
6002 BROWSER_CONTEXT
*Context
;
6003 FORM_ENTRY_INFO
*MenuList
;
6004 FORM_BROWSER_FORMSET
*FormSet
;
6006 gBrowserContextCount
++;
6007 if (gBrowserContextCount
== 1) {
6009 // This is not reentry of SendForm(), no context to save
6014 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
6015 ASSERT (Context
!= NULL
);
6017 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
6020 // Save FormBrowser context
6022 Context
->Selection
= gCurrentSelection
;
6023 Context
->ResetRequired
= gResetRequiredFormLevel
;
6024 Context
->FlagReconnect
= gFlagReconnect
;
6025 Context
->CallbackReconnect
= gCallbackReconnect
;
6026 Context
->ExitRequired
= gExitRequired
;
6027 Context
->HiiHandle
= mCurrentHiiHandle
;
6028 Context
->FormId
= mCurrentFormId
;
6029 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
6030 Context
->SystemLevelFormSet
= mSystemLevelFormSet
;
6031 Context
->CurFakeQestId
= mCurFakeQestId
;
6032 Context
->HiiPackageListUpdated
= mHiiPackageListUpdated
;
6033 Context
->FinishRetrieveCall
= mFinishRetrieveCall
;
6036 // Save the menu history data.
6038 InitializeListHead(&Context
->FormHistoryList
);
6039 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
6040 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
6041 RemoveEntryList (&MenuList
->Link
);
6043 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
6047 // Save formset list.
6049 InitializeListHead(&Context
->FormSetList
);
6050 while (!IsListEmpty (&gBrowserFormSetList
)) {
6051 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList
.ForwardLink
);
6052 RemoveEntryList (&FormSet
->Link
);
6054 InsertTailList(&Context
->FormSetList
, &FormSet
->Link
);
6058 // Insert to FormBrowser context list
6060 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
6065 Restore globals used by previous call to SendForm().
6069 RestoreBrowserContext (
6074 BROWSER_CONTEXT
*Context
;
6075 FORM_ENTRY_INFO
*MenuList
;
6076 FORM_BROWSER_FORMSET
*FormSet
;
6078 ASSERT (gBrowserContextCount
!= 0);
6079 gBrowserContextCount
--;
6080 if (gBrowserContextCount
== 0) {
6082 // This is not reentry of SendForm(), no context to restore
6087 ASSERT (!IsListEmpty (&gBrowserContextList
));
6089 Link
= GetFirstNode (&gBrowserContextList
);
6090 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6093 // Restore FormBrowser context
6095 gCurrentSelection
= Context
->Selection
;
6096 gResetRequiredFormLevel
= Context
->ResetRequired
;
6097 gFlagReconnect
= Context
->FlagReconnect
;
6098 gCallbackReconnect
= Context
->CallbackReconnect
;
6099 gExitRequired
= Context
->ExitRequired
;
6100 mCurrentHiiHandle
= Context
->HiiHandle
;
6101 mCurrentFormId
= Context
->FormId
;
6102 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
6103 mSystemLevelFormSet
= Context
->SystemLevelFormSet
;
6104 mCurFakeQestId
= Context
->CurFakeQestId
;
6105 mHiiPackageListUpdated
= Context
->HiiPackageListUpdated
;
6106 mFinishRetrieveCall
= Context
->FinishRetrieveCall
;
6109 // Restore the menu history data.
6111 while (!IsListEmpty (&Context
->FormHistoryList
)) {
6112 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
6113 RemoveEntryList (&MenuList
->Link
);
6115 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
6119 // Restore the Formset data.
6121 while (!IsListEmpty (&Context
->FormSetList
)) {
6122 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Context
->FormSetList
.ForwardLink
);
6123 RemoveEntryList (&FormSet
->Link
);
6125 InsertTailList(&gBrowserFormSetList
, &FormSet
->Link
);
6129 // Remove from FormBrowser context list
6131 RemoveEntryList (&Context
->Link
);
6132 gBS
->FreePool (Context
);
6136 Find the matched FormSet context in the backup maintain list based on HiiHandle.
6138 @param Handle The Hii Handle.
6140 @return the found FormSet context. If no found, NULL will return.
6143 FORM_BROWSER_FORMSET
*
6144 GetFormSetFromHiiHandle (
6145 EFI_HII_HANDLE Handle
6149 FORM_BROWSER_FORMSET
*FormSet
;
6151 Link
= GetFirstNode (&gBrowserFormSetList
);
6152 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6153 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6154 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6155 if (!ValidateFormSet(FormSet
)) {
6158 if (FormSet
->HiiHandle
== Handle
) {
6167 Check whether the input HII handle is the FormSet that is being used.
6169 @param Handle The Hii Handle.
6171 @retval TRUE HII handle is being used.
6172 @retval FALSE HII handle is not being used.
6176 IsHiiHandleInBrowserContext (
6177 EFI_HII_HANDLE Handle
6181 BROWSER_CONTEXT
*Context
;
6184 // HiiHandle is Current FormSet.
6186 if (mCurrentHiiHandle
== Handle
) {
6191 // Check whether HiiHandle is in BrowserContext.
6193 Link
= GetFirstNode (&gBrowserContextList
);
6194 while (!IsNull (&gBrowserContextList
, Link
)) {
6195 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
6196 if (Context
->HiiHandle
== Handle
) {
6198 // HiiHandle is in BrowserContext
6202 Link
= GetNextNode (&gBrowserContextList
, Link
);
6209 Perform Password check.
6210 Passwork may be encrypted by driver that requires the specific check.
6212 @param Form Form where Password Statement is in.
6213 @param Statement Password statement
6214 @param PasswordString Password string to be checked. It may be NULL.
6215 NULL means to restore password.
6216 "" string can be used to checked whether old password does exist.
6218 @return Status Status of Password check.
6223 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
6224 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
6225 IN EFI_STRING PasswordString OPTIONAL
6229 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
6230 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
6231 EFI_IFR_TYPE_VALUE IfrTypeValue
;
6232 FORM_BROWSER_STATEMENT
*Question
;
6234 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
6235 Question
= GetBrowserStatement(Statement
);
6236 ASSERT (Question
!= NULL
);
6238 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
6239 if (ConfigAccess
== NULL
) {
6240 return EFI_UNSUPPORTED
;
6244 // If a password doesn't have the CALLBACK flag, browser will not handle it.
6246 return EFI_UNSUPPORTED
;
6250 // Prepare password string in HII database
6252 if (PasswordString
!= NULL
) {
6253 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
6255 IfrTypeValue
.string
= 0;
6259 // Send password to Configuration Driver for validation
6261 Status
= ConfigAccess
->Callback (
6263 EFI_BROWSER_ACTION_CHANGING
,
6264 Question
->QuestionId
,
6265 Question
->HiiValue
.Type
,
6271 // Remove password string from HII database
6273 if (PasswordString
!= NULL
) {
6274 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
6281 Find the registered HotKey based on KeyData.
6283 @param[in] KeyData A pointer to a buffer that describes the keystroke
6284 information for the hot key.
6286 @return The registered HotKey context. If no found, NULL will return.
6289 GetHotKeyFromRegisterList (
6290 IN EFI_INPUT_KEY
*KeyData
6294 BROWSER_HOT_KEY
*HotKey
;
6296 Link
= GetFirstNode (&gBrowserHotKeyList
);
6297 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
6298 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
6299 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
6302 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
6309 Configure what scope the hot key will impact.
6310 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
6311 If no scope is set, the default scope will be FormSet level.
6312 After all registered hot keys are removed, previous Scope can reset to another level.
6314 @param[in] Scope Scope level to be set.
6316 @retval EFI_SUCCESS Scope is set correctly.
6317 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
6318 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
6324 IN BROWSER_SETTING_SCOPE Scope
6327 if (Scope
>= MaxLevel
) {
6328 return EFI_INVALID_PARAMETER
;
6332 // When no hot key registered in system or on the first setting,
6333 // Scope can be set.
6335 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
6336 gBrowserSettingScope
= Scope
;
6337 mBrowserScopeFirstSet
= FALSE
;
6338 } else if (Scope
!= gBrowserSettingScope
) {
6339 return EFI_UNSUPPORTED
;
6346 Register the hot key with its browser action, or unregistered the hot key.
6347 Only support hot key that is not printable character (control key, function key, etc.).
6348 If the action value is zero, the hot key will be unregistered if it has been registered.
6349 If the same hot key has been registered, the new action and help string will override the previous ones.
6351 @param[in] KeyData A pointer to a buffer that describes the keystroke
6352 information for the hot key. Its type is EFI_INPUT_KEY to
6353 be supported by all ConsoleIn devices.
6354 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
6355 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
6356 @param[in] HelpString Help string that describes the hot key information.
6357 Its value may be NULL for the unregistered hot key.
6359 @retval EFI_SUCCESS Hot key is registered or unregistered.
6360 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
6361 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
6362 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
6363 @retval EFI_ALREADY_STARTED Key already been registered for one hot key.
6368 IN EFI_INPUT_KEY
*KeyData
,
6370 IN UINT16 DefaultId
,
6371 IN EFI_STRING HelpString OPTIONAL
6374 BROWSER_HOT_KEY
*HotKey
;
6377 // Check input parameters.
6379 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
6380 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
6381 return EFI_INVALID_PARAMETER
;
6385 // Check whether the input KeyData is in BrowserHotKeyList.
6387 HotKey
= GetHotKeyFromRegisterList (KeyData
);
6390 // Unregister HotKey
6392 if (Action
== BROWSER_ACTION_UNREGISTER
) {
6393 if (HotKey
!= NULL
) {
6395 // The registered HotKey is found.
6396 // Remove it from List, and free its resource.
6398 RemoveEntryList (&HotKey
->Link
);
6399 FreePool (HotKey
->KeyData
);
6400 FreePool (HotKey
->HelpString
);
6404 // The registered HotKey is not found.
6406 return EFI_NOT_FOUND
;
6410 if (HotKey
!= NULL
) {
6411 return EFI_ALREADY_STARTED
;
6415 // Create new Key, and add it into List.
6417 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
6418 ASSERT (HotKey
!= NULL
);
6419 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
6420 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
6421 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
6424 // Fill HotKey information.
6426 HotKey
->Action
= Action
;
6427 HotKey
->DefaultId
= DefaultId
;
6428 if (HotKey
->HelpString
!= NULL
) {
6429 FreePool (HotKey
->HelpString
);
6431 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
6437 Register Exit handler function.
6438 When more than one handler function is registered, the latter one will override the previous one.
6439 When NULL handler is specified, the previous Exit handler will be unregistered.
6441 @param[in] Handler Pointer to handler function.
6446 RegiserExitHandler (
6447 IN EXIT_HANDLER Handler
6450 ExitHandlerFunction
= Handler
;
6455 Check whether the browser data has been modified.
6457 @retval TRUE Browser data is modified.
6458 @retval FALSE No browser data is modified.
6463 IsBrowserDataModified (
6468 FORM_BROWSER_FORMSET
*FormSet
;
6470 switch (gBrowserSettingScope
) {
6472 if (gCurrentSelection
== NULL
) {
6475 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
6478 if (gCurrentSelection
== NULL
) {
6481 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
6484 Link
= GetFirstNode (&gBrowserFormSetList
);
6485 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6486 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6487 if (!ValidateFormSet(FormSet
)) {
6491 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6494 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6504 Execute the action requested by the Action parameter.
6506 @param[in] Action Execute the request action.
6507 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
6509 @retval EFI_SUCCESS Execute the request action succss.
6510 @retval EFI_INVALID_PARAMETER The input action value is invalid.
6521 FORM_BROWSER_FORMSET
*FormSet
;
6522 FORM_BROWSER_FORM
*Form
;
6524 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
6525 return EFI_NOT_READY
;
6528 Status
= EFI_SUCCESS
;
6531 if (gBrowserSettingScope
< SystemLevel
) {
6532 FormSet
= gCurrentSelection
->FormSet
;
6533 Form
= gCurrentSelection
->Form
;
6537 // Executet the discard action.
6539 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
6540 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6541 if (EFI_ERROR (Status
)) {
6547 // Executet the difault action.
6549 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
6550 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
, FALSE
);
6551 if (EFI_ERROR (Status
)) {
6554 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
6558 // Executet the submit action.
6560 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
6561 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
6562 if (EFI_ERROR (Status
)) {
6568 // Executet the reset action.
6570 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
6571 gResetRequiredFormLevel
= TRUE
;
6572 gResetRequiredSystemLevel
= TRUE
;
6576 // Executet the exit action.
6578 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
6579 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
6580 if (gBrowserSettingScope
== SystemLevel
) {
6581 if (ExitHandlerFunction
!= NULL
) {
6582 ExitHandlerFunction ();
6586 gExitRequired
= TRUE
;
6593 Create reminder to let user to choose save or discard the changed browser data.
6594 Caller can use it to actively check the changed browser data.
6596 @retval BROWSER_NO_CHANGES No browser data is changed.
6597 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
6598 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
6599 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
6609 FORM_BROWSER_FORMSET
*FormSet
;
6610 BOOLEAN IsDataChanged
;
6611 UINT32 DataSavedAction
;
6614 DataSavedAction
= BROWSER_NO_CHANGES
;
6615 IsDataChanged
= FALSE
;
6616 Link
= GetFirstNode (&gBrowserFormSetList
);
6617 while (!IsNull (&gBrowserFormSetList
, Link
)) {
6618 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
6619 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
6620 if (!ValidateFormSet(FormSet
)) {
6623 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
6624 IsDataChanged
= TRUE
;
6630 // No data is changed. No save is required.
6632 if (!IsDataChanged
) {
6633 return DataSavedAction
;
6637 // If data is changed, prompt user to save or discard it.
6640 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
6642 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
6643 SubmitForm (NULL
, NULL
, SystemLevel
);
6644 DataSavedAction
= BROWSER_SAVE_CHANGES
;
6646 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
6647 DiscardForm (NULL
, NULL
, SystemLevel
);
6648 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
6650 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
6651 DataSavedAction
= BROWSER_KEEP_CURRENT
;
6656 return DataSavedAction
;
6660 Check whether the Reset Required for the browser
6662 @retval TRUE Browser required to reset after exit.
6663 @retval FALSE Browser not need to reset after exit.
6672 return gResetRequiredSystemLevel
;