2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2014, 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
);
54 BOOLEAN gResetRequired
;
55 BOOLEAN gExitRequired
;
56 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
57 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
58 EXIT_HANDLER ExitHandlerFunction
= NULL
;
59 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
62 // Browser Global Strings
65 CHAR16
*mUnknownString
= L
"!";
67 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
69 extern EFI_GUID mCurrentFormSetGuid
;
70 extern EFI_HII_HANDLE mCurrentHiiHandle
;
71 extern UINT16 mCurrentFormId
;
72 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
75 Create a menu with specified formset GUID and form ID, and add it as a child
76 of the given parent menu.
78 @param HiiHandle Hii handle related to this formset.
79 @param FormSetGuid The Formset Guid of menu to be added.
80 @param FormId The Form ID of menu to be added.
81 @param QuestionId The question id of this menu to be added.
83 @return A pointer to the newly added menu or NULL if memory is insufficient.
88 IN EFI_HII_HANDLE HiiHandle
,
89 IN EFI_GUID
*FormSetGuid
,
94 FORM_ENTRY_INFO
*MenuList
;
96 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
97 if (MenuList
== NULL
) {
101 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
103 MenuList
->HiiHandle
= HiiHandle
;
104 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
105 MenuList
->FormId
= FormId
;
106 MenuList
->QuestionId
= QuestionId
;
109 // If parent is not specified, it is the root Form of a Formset
111 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
117 Return the form id for the input hiihandle and formset.
119 @param HiiHandle HiiHandle for FormSet.
120 @param FormSetGuid The Formset GUID of the menu to search.
122 @return First form's id for this form set.
127 IN EFI_HII_HANDLE HiiHandle
,
128 IN EFI_GUID
*FormSetGuid
132 FORM_BROWSER_FORM
*Form
;
134 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
141 Search Menu with given FormSetGuid and FormId in all cached menu list.
143 @param HiiHandle HiiHandle for FormSet.
144 @param FormSetGuid The Formset GUID of the menu to search.
145 @param FormId The Form ID of menu to search.
147 @return A pointer to menu found or NULL if not found.
152 IN EFI_HII_HANDLE HiiHandle
,
153 IN EFI_GUID
*FormSetGuid
,
158 FORM_ENTRY_INFO
*MenuList
;
159 FORM_ENTRY_INFO
*RetMenu
;
160 EFI_FORM_ID FirstFormId
;
164 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
165 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
166 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
167 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
170 // If already find the menu, free the menus behind it.
172 if (RetMenu
!= NULL
) {
173 RemoveEntryList (&MenuList
->Link
);
179 // Find the same FromSet.
181 if (MenuList
->HiiHandle
== HiiHandle
) {
182 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
184 // FormSetGuid is not specified.
187 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
188 if (MenuList
->FormId
== FormId
) {
190 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
191 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
192 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
204 Find parent menu for current menu.
206 @param CurrentMenu Current Menu
208 @retval The parent menu for current menu.
212 IN FORM_ENTRY_INFO
*CurrentMenu
215 FORM_ENTRY_INFO
*ParentMenu
;
218 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
219 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
226 Free Menu list linked list.
228 @param MenuListHead One Menu list point in the menu list.
233 LIST_ENTRY
*MenuListHead
236 FORM_ENTRY_INFO
*MenuList
;
238 while (!IsListEmpty (MenuListHead
)) {
239 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
240 RemoveEntryList (&MenuList
->Link
);
247 Load all hii formset to the browser.
255 FORM_BROWSER_FORMSET
*LocalFormSet
;
256 EFI_HII_HANDLE
*HiiHandles
;
260 FORM_BROWSER_FORMSET
*OldFormset
;
262 OldFormset
= mSystemLevelFormSet
;
265 // Get all the Hii handles
267 HiiHandles
= HiiGetHiiHandles (NULL
);
268 ASSERT (HiiHandles
!= NULL
);
271 // Search for formset of each class type
273 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
275 // Check HiiHandles[Index] does exist in global maintain list.
277 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
282 // Initilize FormSet Setting
284 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
285 ASSERT (LocalFormSet
!= NULL
);
286 mSystemLevelFormSet
= LocalFormSet
;
288 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
289 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
290 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
291 DestroyFormSet (LocalFormSet
);
294 InitializeCurrentSetting (LocalFormSet
);
297 // Initilize Questions' Value
299 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
300 if (EFI_ERROR (Status
)) {
301 DestroyFormSet (LocalFormSet
);
307 // Free resources, and restore gOldFormSet and gClassOfVfr
309 FreePool (HiiHandles
);
311 mSystemLevelFormSet
= OldFormset
;
315 Pop up the error info.
317 @param BrowserStatus The input browser status.
318 @param OpCode The opcode use to get the erro info and timeout value.
319 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
324 IN UINT32 BrowserStatus
,
325 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
326 IN CHAR16
*ErrorString
329 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
333 if (OpCode
!= NULL
) {
334 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
335 ASSERT (Statement
!= NULL
);
336 Statement
->OpCode
= OpCode
;
337 gDisplayFormData
.HighLightedStatement
= Statement
;
341 // Used to compatible with old display engine.
342 // New display engine not use this field.
344 gDisplayFormData
.ErrorString
= ErrorString
;
345 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
347 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
349 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
350 gDisplayFormData
.ErrorString
= NULL
;
352 if (OpCode
!= NULL
) {
353 FreePool (Statement
);
358 This is the routine which an external caller uses to direct the browser
359 where to obtain it's information.
362 @param This The Form Browser protocol instanse.
363 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
364 display a list of the formsets for the handles specified.
365 @param HandleCount The number of Handles specified in Handle.
366 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
367 field in the EFI_IFR_FORM_SET op-code for the specified
368 forms-based package. If FormSetGuid is NULL, then this
369 function will display the first found forms package.
370 @param FormId This field specifies which EFI_IFR_FORM to render as the first
371 displayable page. If this field has a value of 0x0000, then
372 the forms browser will render the specified forms in their encoded order.
373 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
375 @param ActionRequest Points to the action recommended by the form.
377 @retval EFI_SUCCESS The function completed successfully.
378 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
379 @retval EFI_NOT_FOUND No valid forms could be found to display.
385 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
386 IN EFI_HII_HANDLE
*Handles
,
387 IN UINTN HandleCount
,
388 IN EFI_GUID
*FormSetGuid
, OPTIONAL
389 IN UINT16 FormId
, OPTIONAL
390 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
391 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
395 UI_MENU_SELECTION
*Selection
;
397 FORM_BROWSER_FORMSET
*FormSet
;
398 FORM_ENTRY_INFO
*MenuList
;
401 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
403 if (mFormDisplay
== NULL
) {
404 return EFI_UNSUPPORTED
;
408 // Save globals used by SendForm()
410 SaveBrowserContext ();
412 gResetRequired
= FALSE
;
413 gExitRequired
= FALSE
;
414 Status
= EFI_SUCCESS
;
416 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
418 for (Index
= 0; Index
< HandleCount
; Index
++) {
419 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
420 ASSERT (Selection
!= NULL
);
422 Selection
->Handle
= Handles
[Index
];
423 if (FormSetGuid
!= NULL
) {
424 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
425 Selection
->FormId
= FormId
;
427 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
431 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
432 ASSERT (FormSet
!= NULL
);
435 // Initialize internal data structures of FormSet
437 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
438 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
439 DestroyFormSet (FormSet
);
442 Selection
->FormSet
= FormSet
;
443 mSystemLevelFormSet
= FormSet
;
446 // Display this formset
448 gCurrentSelection
= Selection
;
450 Status
= SetupBrowser (Selection
);
452 gCurrentSelection
= NULL
;
453 mSystemLevelFormSet
= NULL
;
456 // If no data is changed, don't need to save current FormSet into the maintain list.
458 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
459 CleanBrowserStorage(FormSet
);
460 RemoveEntryList (&FormSet
->Link
);
461 DestroyFormSet (FormSet
);
464 if (EFI_ERROR (Status
)) {
467 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
469 FreePool (Selection
);
472 if (ActionRequest
!= NULL
) {
473 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
474 if (gResetRequired
) {
475 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
479 mFormDisplay
->ExitDisplay();
482 // Clear the menu history data.
484 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
485 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
486 RemoveEntryList (&MenuList
->Link
);
491 // Restore globals used by SendForm()
493 RestoreBrowserContext ();
499 Get or set data to the storage.
501 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
502 @param ResultsData A string returned from an IFR browser or
503 equivalent. The results string will have no
504 routing information in them.
505 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
506 (if RetrieveData = TRUE) data from the uncommitted
507 browser state information or set (if RetrieveData
508 = FALSE) data in the uncommitted browser state
510 @param Storage The pointer to the storage.
512 @retval EFI_SUCCESS The results have been distributed or are awaiting
518 IN OUT UINTN
*ResultsDataSize
,
519 IN OUT EFI_STRING
*ResultsData
,
520 IN BOOLEAN RetrieveData
,
521 IN BROWSER_STORAGE
*Storage
532 // Generate <ConfigResp>
534 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
535 if (EFI_ERROR (Status
)) {
540 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
541 // Also need to consider add "\0" at first time.
543 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
544 BufferSize
= StrSize (StrPtr
);
548 // Copy the data if the input buffer is bigger enough.
550 if (*ResultsDataSize
>= BufferSize
) {
551 StrCpy (*ResultsData
, StrPtr
);
554 *ResultsDataSize
= BufferSize
;
555 FreePool (ConfigResp
);
558 // Prepare <ConfigResp>
560 TmpSize
= StrLen (*ResultsData
);
561 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
562 ConfigResp
= AllocateZeroPool (BufferSize
);
563 ASSERT (ConfigResp
!= NULL
);
565 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
566 StrCat (ConfigResp
, L
"&");
567 StrCat (ConfigResp
, *ResultsData
);
570 // Update Browser uncommited data
572 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
573 FreePool (ConfigResp
);
574 if (EFI_ERROR (Status
)) {
583 This routine called this service in the browser to retrieve or set certain uncommitted
584 state information that resides in the open formsets.
586 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
588 @param ResultsDataSize A pointer to the size of the buffer associated
590 @param ResultsData A string returned from an IFR browser or
591 equivalent. The results string will have no
592 routing information in them.
593 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
594 (if RetrieveData = TRUE) data from the uncommitted
595 browser state information or set (if RetrieveData
596 = FALSE) data in the uncommitted browser state
598 @param VariableGuid An optional field to indicate the target variable
600 @param VariableName An optional field to indicate the target
601 human-readable variable name.
603 @retval EFI_SUCCESS The results have been distributed or are awaiting
605 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
606 contain the results data.
612 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
613 IN OUT UINTN
*ResultsDataSize
,
614 IN OUT EFI_STRING ResultsData
,
615 IN BOOLEAN RetrieveData
,
616 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
617 IN CONST CHAR16
*VariableName OPTIONAL
622 BROWSER_STORAGE
*Storage
;
623 FORMSET_STORAGE
*FormsetStorage
;
627 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
628 return EFI_INVALID_PARAMETER
;
631 TotalSize
= *ResultsDataSize
;
634 Status
= EFI_SUCCESS
;
636 if (VariableGuid
!= NULL
) {
638 // Try to find target storage in the current formset.
640 Link
= GetFirstNode (&gBrowserStorageList
);
641 while (!IsNull (&gBrowserStorageList
, Link
)) {
642 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
643 Link
= GetNextNode (&gBrowserStorageList
, Link
);
645 // Check the current storage.
647 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
651 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
652 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
654 // Buffer storage require both GUID and Name
656 if (VariableName
== NULL
) {
657 return EFI_NOT_FOUND
;
660 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
665 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
666 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
667 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
668 return EFI_NOT_FOUND
;
671 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
676 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
677 if (EFI_ERROR (Status
)) {
681 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
682 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
686 // Different formsets may have same varstore, so here just set the flag
687 // not exit the circle.
694 return EFI_NOT_FOUND
;
698 // GUID/Name is not specified, take the first storage in FormSet
700 if (mSystemLevelFormSet
== NULL
) {
701 return EFI_NOT_READY
;
705 // Generate <ConfigResp>
707 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
708 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
709 return EFI_UNSUPPORTED
;
712 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
714 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
715 if (EFI_ERROR (Status
)) {
721 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
722 *ResultsDataSize
= TotalSize
;
731 Callback function for SimpleTextInEx protocol install events
733 @param Event the event that is signaled.
734 @param Context not used here.
739 FormDisplayCallback (
746 if (mFormDisplay
!= NULL
) {
750 Status
= gBS
->LocateProtocol (
751 &gEdkiiFormDisplayEngineProtocolGuid
,
753 (VOID
**) &mFormDisplay
758 Initialize Setup Browser driver.
760 @param ImageHandle The image handle.
761 @param SystemTable The system table.
763 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
764 @return Other value if failed to initialize the Setup Browser module.
770 IN EFI_HANDLE ImageHandle
,
771 IN EFI_SYSTEM_TABLE
*SystemTable
778 // Locate required Hii relative protocols
780 Status
= gBS
->LocateProtocol (
781 &gEfiHiiDatabaseProtocolGuid
,
783 (VOID
**) &mHiiDatabase
785 ASSERT_EFI_ERROR (Status
);
787 Status
= gBS
->LocateProtocol (
788 &gEfiHiiConfigRoutingProtocolGuid
,
790 (VOID
**) &mHiiConfigRouting
792 ASSERT_EFI_ERROR (Status
);
794 Status
= gBS
->LocateProtocol (
795 &gEfiDevicePathFromTextProtocolGuid
,
797 (VOID
**) &mPathFromText
801 // Install FormBrowser2 protocol
803 mPrivateData
.Handle
= NULL
;
804 Status
= gBS
->InstallProtocolInterface (
805 &mPrivateData
.Handle
,
806 &gEfiFormBrowser2ProtocolGuid
,
807 EFI_NATIVE_INTERFACE
,
808 &mPrivateData
.FormBrowser2
810 ASSERT_EFI_ERROR (Status
);
813 // Install FormBrowserEx2 protocol
815 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
816 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
817 mPrivateData
.Handle
= NULL
;
818 Status
= gBS
->InstallProtocolInterface (
819 &mPrivateData
.Handle
,
820 &gEdkiiFormBrowserEx2ProtocolGuid
,
821 EFI_NATIVE_INTERFACE
,
822 &mPrivateData
.FormBrowserEx2
824 ASSERT_EFI_ERROR (Status
);
826 Status
= gBS
->InstallProtocolInterface (
827 &mPrivateData
.Handle
,
828 &gEfiFormBrowserExProtocolGuid
,
829 EFI_NATIVE_INTERFACE
,
830 &mPrivateData
.FormBrowserEx
832 ASSERT_EFI_ERROR (Status
);
834 InitializeDisplayFormData ();
836 Status
= gBS
->LocateProtocol (
837 &gEdkiiFormDisplayEngineProtocolGuid
,
839 (VOID
**) &mFormDisplay
842 if (EFI_ERROR (Status
)) {
843 EfiCreateProtocolNotifyEvent (
844 &gEdkiiFormDisplayEngineProtocolGuid
,
857 Create a new string in HII Package List.
859 @param String The String to be added
860 @param HiiHandle The package list in the HII database to insert the
863 @return The output string.
869 IN EFI_HII_HANDLE HiiHandle
872 EFI_STRING_ID StringId
;
874 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
875 ASSERT (StringId
!= 0);
882 Delete a string from HII Package List.
884 @param StringId Id of the string in HII database.
885 @param HiiHandle The HII package list handle.
887 @retval EFI_SUCCESS The string was deleted successfully.
892 IN EFI_STRING_ID StringId
,
893 IN EFI_HII_HANDLE HiiHandle
898 NullChar
= CHAR_NULL
;
899 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
905 Get the string based on the StringId and HII Package List Handle.
907 @param Token The String's ID.
908 @param HiiHandle The package list in the HII database to search for
909 the specified string.
911 @return The output string.
916 IN EFI_STRING_ID Token
,
917 IN EFI_HII_HANDLE HiiHandle
922 if (HiiHandle
== NULL
) {
926 String
= HiiGetString (HiiHandle
, Token
, NULL
);
927 if (String
== NULL
) {
928 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
929 ASSERT (String
!= NULL
);
931 return (CHAR16
*) String
;
936 Allocate new memory and then copy the Unicode string Source to Destination.
938 @param Dest Location to copy string
939 @param Src String to copy
944 IN OUT CHAR16
**Dest
,
951 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
952 ASSERT (*Dest
!= NULL
);
957 Allocate new memory and concatinate Source on the end of Destination.
959 @param Dest String to added to the end of.
960 @param Src String to concatinate.
965 IN OUT CHAR16
**Dest
,
973 NewStringCpy (Dest
, Src
);
977 TmpSize
= StrSize (*Dest
);
978 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
979 ASSERT (NewString
!= NULL
);
981 StrCpy (NewString
, *Dest
);
982 StrCat (NewString
, Src
);
989 Get Value for given Name from a NameValue Storage.
991 @param Storage The NameValue Storage.
992 @param Name The Name.
993 @param Value The retured Value.
994 @param GetValueFrom Where to get source value, from EditValue or Value.
996 @retval EFI_SUCCESS Value found for given Name.
997 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1002 IN BROWSER_STORAGE
*Storage
,
1004 IN OUT CHAR16
**Value
,
1005 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1009 NAME_VALUE_NODE
*Node
;
1011 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1012 return EFI_INVALID_PARAMETER
;
1017 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1018 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1019 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1021 if (StrCmp (Name
, Node
->Name
) == 0) {
1022 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1023 NewStringCpy (Value
, Node
->EditValue
);
1025 NewStringCpy (Value
, Node
->Value
);
1030 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1033 return EFI_NOT_FOUND
;
1038 Set Value of given Name in a NameValue Storage.
1040 @param Storage The NameValue Storage.
1041 @param Name The Name.
1042 @param Value The Value to set.
1043 @param SetValueTo Whether update editValue or Value.
1044 @param ReturnNode The node use the input name.
1046 @retval EFI_SUCCESS Value found for given Name.
1047 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1052 IN BROWSER_STORAGE
*Storage
,
1055 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1056 OUT NAME_VALUE_NODE
**ReturnNode
1060 NAME_VALUE_NODE
*Node
;
1063 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1064 return EFI_INVALID_PARAMETER
;
1067 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1068 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1069 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1071 if (StrCmp (Name
, Node
->Name
) == 0) {
1072 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1073 Buffer
= Node
->EditValue
;
1075 Buffer
= Node
->Value
;
1077 if (Buffer
!= NULL
) {
1080 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1081 ASSERT (Buffer
!= NULL
);
1082 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1083 Node
->EditValue
= Buffer
;
1085 Node
->Value
= Buffer
;
1088 if (ReturnNode
!= NULL
) {
1095 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1098 return EFI_NOT_FOUND
;
1103 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1105 @param Storage The Storage to be conveted.
1106 @param ConfigResp The returned <ConfigResp>.
1107 @param ConfigRequest The ConfigRequest string.
1108 @param GetEditBuf Get the data from editbuffer or buffer.
1110 @retval EFI_SUCCESS Convert success.
1111 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1115 StorageToConfigResp (
1116 IN BROWSER_STORAGE
*Storage
,
1117 IN CHAR16
**ConfigResp
,
1118 IN CHAR16
*ConfigRequest
,
1119 IN BOOLEAN GetEditBuf
1123 EFI_STRING Progress
;
1125 NAME_VALUE_NODE
*Node
;
1128 Status
= EFI_SUCCESS
;
1130 switch (Storage
->Type
) {
1131 case EFI_HII_VARSTORE_BUFFER
:
1132 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1133 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1134 Status
= mHiiConfigRouting
->BlockToConfig (
1144 case EFI_HII_VARSTORE_NAME_VALUE
:
1146 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1148 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1149 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1150 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1152 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1153 NewStringCat (ConfigResp
, L
"&");
1154 NewStringCat (ConfigResp
, Node
->Name
);
1155 NewStringCat (ConfigResp
, L
"=");
1157 NewStringCat (ConfigResp
, Node
->EditValue
);
1159 NewStringCat (ConfigResp
, Node
->Value
);
1162 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1166 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1168 Status
= EFI_INVALID_PARAMETER
;
1177 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1179 @param Storage The Storage to receive the settings.
1180 @param ConfigResp The <ConfigResp> to be converted.
1182 @retval EFI_SUCCESS Convert success.
1183 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1187 ConfigRespToStorage (
1188 IN BROWSER_STORAGE
*Storage
,
1189 IN CHAR16
*ConfigResp
1193 EFI_STRING Progress
;
1199 Status
= EFI_SUCCESS
;
1201 switch (Storage
->Type
) {
1202 case EFI_HII_VARSTORE_BUFFER
:
1203 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1204 BufferSize
= Storage
->Size
;
1205 Status
= mHiiConfigRouting
->ConfigToBlock (
1208 Storage
->EditBuffer
,
1214 case EFI_HII_VARSTORE_NAME_VALUE
:
1215 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1216 if (StrPtr
== NULL
) {
1219 StrPtr
= StrStr (ConfigResp
, L
"&");
1220 while (StrPtr
!= NULL
) {
1224 StrPtr
= StrPtr
+ 1;
1226 StrPtr
= StrStr (StrPtr
, L
"=");
1227 if (StrPtr
== NULL
) {
1235 StrPtr
= StrPtr
+ 1;
1237 StrPtr
= StrStr (StrPtr
, L
"&");
1238 if (StrPtr
!= NULL
) {
1241 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1245 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1247 Status
= EFI_INVALID_PARAMETER
;
1256 Get Question's current Value.
1258 @param FormSet FormSet data structure.
1259 @param Form Form data structure.
1260 @param Question Question to be initialized.
1261 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1263 @retval EFI_SUCCESS The function completed successfully.
1268 IN FORM_BROWSER_FORMSET
*FormSet
,
1269 IN FORM_BROWSER_FORM
*Form
,
1270 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1271 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1280 BROWSER_STORAGE
*Storage
;
1281 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1282 CHAR16
*ConfigRequest
;
1290 BOOLEAN IsBufferStorage
;
1295 Status
= EFI_SUCCESS
;
1299 if (GetValueFrom
>= GetSetValueWithMax
) {
1300 return EFI_INVALID_PARAMETER
;
1304 // Question value is provided by an Expression, evaluate it
1306 if (Question
->ValueExpression
!= NULL
) {
1307 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1308 if (!EFI_ERROR (Status
)) {
1309 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1310 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1311 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1312 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1313 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1315 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1316 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1318 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1320 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1321 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1327 // Get question value by read expression.
1329 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1330 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1331 if (!EFI_ERROR (Status
) &&
1332 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1334 // Only update question value to the valid result.
1336 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1337 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1338 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1339 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1340 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1342 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1343 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1345 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1347 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1348 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1354 // Question value is provided by RTC
1356 Storage
= Question
->Storage
;
1357 QuestionValue
= &Question
->HiiValue
.Value
;
1358 if (Storage
== NULL
) {
1360 // It's a Question without storage, or RTC date/time
1362 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1364 // Date and time define the same Flags bit
1366 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1367 case QF_DATE_STORAGE_TIME
:
1368 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1371 case QF_DATE_STORAGE_WAKEUP
:
1372 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1375 case QF_DATE_STORAGE_NORMAL
:
1378 // For date/time without storage
1383 if (EFI_ERROR (Status
)) {
1387 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1388 QuestionValue
->date
.Year
= EfiTime
.Year
;
1389 QuestionValue
->date
.Month
= EfiTime
.Month
;
1390 QuestionValue
->date
.Day
= EfiTime
.Day
;
1392 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1393 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1394 QuestionValue
->time
.Second
= EfiTime
.Second
;
1402 // Question value is provided by EFI variable
1404 StorageWidth
= Question
->StorageWidth
;
1405 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1406 if (Question
->BufferValue
!= NULL
) {
1407 Dst
= Question
->BufferValue
;
1409 Dst
= (UINT8
*) QuestionValue
;
1412 Status
= gRT
->GetVariable (
1413 Question
->VariableName
,
1420 // Always return success, even this EFI variable doesn't exist
1426 // Question Value is provided by Buffer Storage or NameValue Storage
1428 if (Question
->BufferValue
!= NULL
) {
1430 // This Question is password or orderedlist
1432 Dst
= Question
->BufferValue
;
1435 // Other type of Questions
1437 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1440 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1441 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1442 IsBufferStorage
= TRUE
;
1444 IsBufferStorage
= FALSE
;
1446 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1447 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1448 if (IsBufferStorage
) {
1449 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1451 // Copy from storage Edit buffer
1453 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1456 // Copy from storage Edit buffer
1458 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1462 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1463 if (EFI_ERROR (Status
)) {
1467 ASSERT (Value
!= NULL
);
1468 LengthStr
= StrLen (Value
);
1469 Status
= EFI_SUCCESS
;
1472 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1473 // Add string tail char L'\0' into Length
1475 Length
= StorageWidth
+ sizeof (CHAR16
);
1476 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1477 Status
= EFI_BUFFER_TOO_SMALL
;
1479 StringPtr
= (CHAR16
*) Dst
;
1480 ZeroMem (TemStr
, sizeof (TemStr
));
1481 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1482 StrnCpy (TemStr
, Value
+ Index
, 4);
1483 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1486 // Add tailing L'\0' character
1488 StringPtr
[Index
/4] = L
'\0';
1491 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1492 Status
= EFI_BUFFER_TOO_SMALL
;
1494 ZeroMem (TemStr
, sizeof (TemStr
));
1495 for (Index
= 0; Index
< LengthStr
; Index
++) {
1496 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1497 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1498 if ((Index
& 1) == 0) {
1499 Dst
[Index
/2] = DigitUint8
;
1501 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1511 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1512 // <ConfigHdr> + "&" + <VariableName>
1514 if (IsBufferStorage
) {
1515 Length
= StrLen (Storage
->ConfigHdr
);
1516 Length
+= StrLen (Question
->BlockName
);
1518 Length
= StrLen (Storage
->ConfigHdr
);
1519 Length
+= StrLen (Question
->VariableName
) + 1;
1521 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1522 ASSERT (ConfigRequest
!= NULL
);
1524 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1525 if (IsBufferStorage
) {
1526 StrCat (ConfigRequest
, Question
->BlockName
);
1528 StrCat (ConfigRequest
, L
"&");
1529 StrCat (ConfigRequest
, Question
->VariableName
);
1533 // Request current settings from Configuration Driver
1535 Status
= mHiiConfigRouting
->ExtractConfig (
1541 FreePool (ConfigRequest
);
1542 if (EFI_ERROR (Status
)) {
1547 // Skip <ConfigRequest>
1549 if (IsBufferStorage
) {
1550 Value
= StrStr (Result
, L
"&VALUE");
1551 if (Value
== NULL
) {
1553 return EFI_NOT_FOUND
;
1560 Value
= Result
+ Length
;
1562 if (*Value
!= '=') {
1564 return EFI_NOT_FOUND
;
1567 // Skip '=', point to value
1572 // Suppress <AltResp> if any
1575 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1580 LengthStr
= StrLen (Value
);
1581 Status
= EFI_SUCCESS
;
1582 if (!IsBufferStorage
&& IsString
) {
1584 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1585 // Add string tail char L'\0' into Length
1587 Length
= StorageWidth
+ sizeof (CHAR16
);
1588 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1589 Status
= EFI_BUFFER_TOO_SMALL
;
1591 StringPtr
= (CHAR16
*) Dst
;
1592 ZeroMem (TemStr
, sizeof (TemStr
));
1593 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1594 StrnCpy (TemStr
, Value
+ Index
, 4);
1595 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1598 // Add tailing L'\0' character
1600 StringPtr
[Index
/4] = L
'\0';
1603 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1604 Status
= EFI_BUFFER_TOO_SMALL
;
1606 ZeroMem (TemStr
, sizeof (TemStr
));
1607 for (Index
= 0; Index
< LengthStr
; Index
++) {
1608 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1609 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1610 if ((Index
& 1) == 0) {
1611 Dst
[Index
/2] = DigitUint8
;
1613 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1619 if (EFI_ERROR (Status
)) {
1625 // Synchronize Edit Buffer
1627 if (IsBufferStorage
) {
1628 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1630 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1633 if (Result
!= NULL
) {
1643 Save Question Value to edit copy(cached) or Storage(uncached).
1645 @param FormSet FormSet data structure.
1646 @param Form Form data structure.
1647 @param Question Pointer to the Question.
1648 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1650 @retval EFI_SUCCESS The function completed successfully.
1655 IN FORM_BROWSER_FORMSET
*FormSet
,
1656 IN FORM_BROWSER_FORM
*Form
,
1657 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1658 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1668 BROWSER_STORAGE
*Storage
;
1669 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1674 BOOLEAN IsBufferStorage
;
1680 NAME_VALUE_NODE
*Node
;
1682 Status
= EFI_SUCCESS
;
1685 if (SetValueTo
>= GetSetValueWithMax
) {
1686 return EFI_INVALID_PARAMETER
;
1690 // If Question value is provided by an Expression, then it is read only
1692 if (Question
->ValueExpression
!= NULL
) {
1697 // Before set question value, evaluate its write expression.
1699 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1700 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1701 if (EFI_ERROR (Status
)) {
1707 // Question value is provided by RTC
1709 Storage
= Question
->Storage
;
1710 QuestionValue
= &Question
->HiiValue
.Value
;
1711 if (Storage
== NULL
) {
1713 // It's a Question without storage, or RTC date/time
1715 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1717 // Date and time define the same Flags bit
1719 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1720 case QF_DATE_STORAGE_TIME
:
1721 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1724 case QF_DATE_STORAGE_WAKEUP
:
1725 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1728 case QF_DATE_STORAGE_NORMAL
:
1731 // For date/time without storage
1736 if (EFI_ERROR (Status
)) {
1740 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1741 EfiTime
.Year
= QuestionValue
->date
.Year
;
1742 EfiTime
.Month
= QuestionValue
->date
.Month
;
1743 EfiTime
.Day
= QuestionValue
->date
.Day
;
1745 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1746 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1747 EfiTime
.Second
= QuestionValue
->time
.Second
;
1750 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1751 Status
= gRT
->SetTime (&EfiTime
);
1753 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1761 // Question value is provided by EFI variable
1763 StorageWidth
= Question
->StorageWidth
;
1764 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1765 if (Question
->BufferValue
!= NULL
) {
1766 Src
= Question
->BufferValue
;
1768 Src
= (UINT8
*) QuestionValue
;
1771 Status
= gRT
->SetVariable (
1772 Question
->VariableName
,
1774 Storage
->Attributes
,
1782 // Question Value is provided by Buffer Storage or NameValue Storage
1784 if (Question
->BufferValue
!= NULL
) {
1785 Src
= Question
->BufferValue
;
1787 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1790 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1791 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1792 IsBufferStorage
= TRUE
;
1794 IsBufferStorage
= FALSE
;
1796 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1798 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1799 if (IsBufferStorage
) {
1800 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1802 // Copy to storage edit buffer
1804 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1805 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1807 // Copy to storage edit buffer
1809 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1814 // Allocate enough string buffer.
1817 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1818 Value
= AllocateZeroPool (BufferLen
);
1819 ASSERT (Value
!= NULL
);
1821 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1823 TemName
= (CHAR16
*) Src
;
1825 for (; *TemName
!= L
'\0'; TemName
++) {
1826 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1829 BufferLen
= StorageWidth
* 2 + 1;
1830 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1831 ASSERT (Value
!= NULL
);
1833 // Convert Buffer to Hex String
1835 TemBuffer
= Src
+ StorageWidth
- 1;
1837 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1838 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1842 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1844 if (EFI_ERROR (Status
)) {
1848 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1850 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1851 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1853 if (IsBufferStorage
) {
1854 Length
= StrLen (Question
->BlockName
) + 7;
1856 Length
= StrLen (Question
->VariableName
) + 2;
1858 if (!IsBufferStorage
&& IsString
) {
1859 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1861 Length
+= (StorageWidth
* 2);
1863 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1864 ASSERT (ConfigResp
!= NULL
);
1866 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1867 if (IsBufferStorage
) {
1868 StrCat (ConfigResp
, Question
->BlockName
);
1869 StrCat (ConfigResp
, L
"&VALUE=");
1871 StrCat (ConfigResp
, L
"&");
1872 StrCat (ConfigResp
, Question
->VariableName
);
1873 StrCat (ConfigResp
, L
"=");
1876 Value
= ConfigResp
+ StrLen (ConfigResp
);
1878 if (!IsBufferStorage
&& IsString
) {
1880 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1882 TemName
= (CHAR16
*) Src
;
1884 for (; *TemName
!= L
'\0'; TemName
++) {
1885 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1889 // Convert Buffer to Hex String
1891 TemBuffer
= Src
+ StorageWidth
- 1;
1893 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1894 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1899 // Convert to lower char.
1901 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1902 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1903 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1908 // Submit Question Value to Configuration Driver
1910 Status
= mHiiConfigRouting
->RouteConfig (
1915 if (EFI_ERROR (Status
)) {
1916 FreePool (ConfigResp
);
1919 FreePool (ConfigResp
);
1922 // Sync storage, from editbuffer to buffer.
1924 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1932 Perform nosubmitif check for a Form.
1934 @param FormSet FormSet data structure.
1935 @param Form Form data structure.
1936 @param Question The Question to be validated.
1937 @param Type Validation type: NoSubmit
1939 @retval EFI_SUCCESS Form validation pass.
1940 @retval other Form validation failed.
1945 IN FORM_BROWSER_FORMSET
*FormSet
,
1946 IN FORM_BROWSER_FORM
*Form
,
1947 IN FORM_BROWSER_STATEMENT
*Question
,
1953 LIST_ENTRY
*ListHead
;
1954 FORM_EXPRESSION
*Expression
;
1955 UINT32 BrowserStatus
;
1958 BrowserStatus
= BROWSER_SUCCESS
;
1962 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1963 ListHead
= &Question
->InconsistentListHead
;
1966 case EFI_HII_EXPRESSION_WARNING_IF
:
1967 ListHead
= &Question
->WarningListHead
;
1970 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
1971 ListHead
= &Question
->NoSubmitListHead
;
1976 return EFI_UNSUPPORTED
;
1979 Link
= GetFirstNode (ListHead
);
1980 while (!IsNull (ListHead
, Link
)) {
1981 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1984 // Evaluate the expression
1986 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1987 if (EFI_ERROR (Status
)) {
1991 if (IsTrue (&Expression
->Result
)) {
1993 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1994 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
1997 case EFI_HII_EXPRESSION_WARNING_IF
:
1998 BrowserStatus
= BROWSER_WARNING_IF
;
2001 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
2002 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2004 // This code only used to compatible with old display engine,
2005 // New display engine will not use this field.
2007 if (Expression
->Error
!= 0) {
2008 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2017 PopupErrorMessage(BrowserStatus
, Expression
->OpCode
, ErrorStr
);
2019 if (ErrorStr
!= NULL
) {
2020 FreePool (ErrorStr
);
2023 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2026 return EFI_NOT_READY
;
2030 Link
= GetNextNode (ListHead
, Link
);
2037 Perform question check.
2039 If one question has more than one check, process form high priority to low.
2040 Only one error info will be popup.
2042 @param FormSet FormSet data structure.
2043 @param Form Form data structure.
2044 @param Question The Question to be validated.
2046 @retval EFI_SUCCESS Form validation pass.
2047 @retval other Form validation failed.
2051 ValueChangedValidation (
2052 IN FORM_BROWSER_FORMSET
*FormSet
,
2053 IN FORM_BROWSER_FORM
*Form
,
2054 IN FORM_BROWSER_STATEMENT
*Question
2059 Status
= EFI_SUCCESS
;
2062 // Do the inconsistentif check.
2064 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2065 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2066 if (EFI_ERROR (Status
)) {
2072 // Do the warningif check.
2074 if (!IsListEmpty (&Question
->WarningListHead
)) {
2075 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2082 Perform NoSubmit check for each Form in FormSet.
2084 @param FormSet FormSet data structure.
2085 @param CurrentForm Current input form data structure.
2087 @retval EFI_SUCCESS Form validation pass.
2088 @retval other Form validation failed.
2093 IN FORM_BROWSER_FORMSET
*FormSet
,
2094 IN FORM_BROWSER_FORM
*CurrentForm
2099 FORM_BROWSER_STATEMENT
*Question
;
2100 FORM_BROWSER_FORM
*Form
;
2101 LIST_ENTRY
*LinkForm
;
2103 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2104 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2105 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2106 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2108 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2112 Link
= GetFirstNode (&Form
->StatementListHead
);
2113 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2114 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2116 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2117 if (EFI_ERROR (Status
)) {
2121 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2129 Fill storage's edit copy with settings requested from Configuration Driver.
2131 @param FormSet FormSet data structure.
2132 @param Storage The storage which need to sync.
2133 @param ConfigRequest The config request string which used to sync storage.
2134 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2135 editbuffer to buffer
2136 if TRUE, copy the editbuffer to the buffer.
2137 if FALSE, copy the buffer to the editbuffer.
2139 @retval EFI_SUCCESS The function completed successfully.
2143 SynchronizeStorage (
2144 IN FORM_BROWSER_FORMSET
*FormSet
,
2145 OUT BROWSER_STORAGE
*Storage
,
2146 IN CHAR16
*ConfigRequest
,
2147 IN BOOLEAN SyncOrRestore
2151 EFI_STRING Progress
;
2155 NAME_VALUE_NODE
*Node
;
2159 Status
= EFI_SUCCESS
;
2162 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2163 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2164 BufferSize
= Storage
->Size
;
2166 if (SyncOrRestore
) {
2167 Src
= Storage
->EditBuffer
;
2168 Dst
= Storage
->Buffer
;
2170 Src
= Storage
->Buffer
;
2171 Dst
= Storage
->EditBuffer
;
2174 if (ConfigRequest
!= NULL
) {
2175 Status
= mHiiConfigRouting
->BlockToConfig(
2183 if (EFI_ERROR (Status
)) {
2187 Status
= mHiiConfigRouting
->ConfigToBlock (
2194 if (Result
!= NULL
) {
2198 CopyMem (Dst
, Src
, BufferSize
);
2200 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2201 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2202 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2203 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2205 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2206 (ConfigRequest
== NULL
)) {
2207 if (SyncOrRestore
) {
2208 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2210 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2214 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2222 When discard the question value, call the callback function with Changed type
2223 to inform the hii driver.
2225 @param FormSet FormSet data structure.
2226 @param Form Form data structure.
2230 SendDiscardInfoToDriver (
2231 IN FORM_BROWSER_FORMSET
*FormSet
,
2232 IN FORM_BROWSER_FORM
*Form
2236 FORM_BROWSER_STATEMENT
*Question
;
2237 EFI_IFR_TYPE_VALUE
*TypeValue
;
2238 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2240 if (FormSet
->ConfigAccess
== NULL
) {
2244 Link
= GetFirstNode (&Form
->StatementListHead
);
2245 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2246 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2247 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2249 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2253 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2257 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2261 if (!Question
->ValueChanged
) {
2265 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2266 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2268 TypeValue
= &Question
->HiiValue
.Value
;
2271 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2272 FormSet
->ConfigAccess
->Callback (
2273 FormSet
->ConfigAccess
,
2274 EFI_BROWSER_ACTION_CHANGED
,
2275 Question
->QuestionId
,
2276 Question
->HiiValue
.Type
,
2284 Validate the FormSet. If the formset is not validate, remove it from the list.
2286 @param FormSet The input FormSet which need to validate.
2288 @retval TRUE The handle is validate.
2289 @retval FALSE The handle is invalidate.
2294 FORM_BROWSER_FORMSET
*FormSet
2297 EFI_HII_HANDLE
*HiiHandles
;
2301 ASSERT (FormSet
!= NULL
);
2304 // Get all the Hii handles
2306 HiiHandles
= HiiGetHiiHandles (NULL
);
2307 ASSERT (HiiHandles
!= NULL
);
2310 // Search for formset of each class type
2312 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2313 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2320 CleanBrowserStorage(FormSet
);
2321 RemoveEntryList (&FormSet
->Link
);
2322 DestroyFormSet (FormSet
);
2325 FreePool (HiiHandles
);
2330 Check whether need to enable the reset flag in form level.
2331 Also clean all ValueChanged flag in question.
2333 @param SetFlag Whether need to set the Reset Flag.
2334 @param Form Form data structure.
2340 IN FORM_BROWSER_FORM
*Form
2344 FORM_BROWSER_STATEMENT
*Question
;
2348 Link
= GetFirstNode (&Form
->StatementListHead
);
2349 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2350 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2352 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2353 gResetRequired
= TRUE
;
2356 if (Question
->ValueChanged
) {
2357 Question
->ValueChanged
= FALSE
;
2360 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2365 Check whether need to enable the reset flag.
2366 Also clean ValueChanged flag for all statements.
2368 Form level or formset level, only one.
2370 @param SetFlag Whether need to set the Reset Flag.
2371 @param FormSet FormSet data structure.
2372 @param Form Form data structure.
2376 ValueChangeResetFlagUpdate (
2378 IN FORM_BROWSER_FORMSET
*FormSet
,
2379 IN FORM_BROWSER_FORM
*Form
2382 FORM_BROWSER_FORM
*CurrentForm
;
2386 // Form != NULL means only check form level.
2389 UpdateFlagForForm(SetFlag
, Form
);
2393 Link
= GetFirstNode (&FormSet
->FormListHead
);
2394 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2395 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2396 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2398 UpdateFlagForForm(SetFlag
, CurrentForm
);
2403 Discard data based on the input setting scope (Form, FormSet or System).
2405 @param FormSet FormSet data structure.
2406 @param Form Form data structure.
2407 @param SettingScope Setting Scope for Discard action.
2409 @retval EFI_SUCCESS The function completed successfully.
2410 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2415 IN FORM_BROWSER_FORMSET
*FormSet
,
2416 IN FORM_BROWSER_FORM
*Form
,
2417 IN BROWSER_SETTING_SCOPE SettingScope
2421 FORMSET_STORAGE
*Storage
;
2422 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2423 FORM_BROWSER_FORMSET
*LocalFormSet
;
2424 FORM_BROWSER_FORMSET
*OldFormSet
;
2427 // Check the supported setting level.
2429 if (SettingScope
>= MaxLevel
) {
2430 return EFI_UNSUPPORTED
;
2433 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2435 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2436 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2437 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2438 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2440 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2445 // Skip if there is no RequestElement
2447 if (ConfigInfo
->ElementCount
== 0) {
2452 // Prepare <ConfigResp>
2454 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2457 // Call callback with Changed type to inform the driver.
2459 SendDiscardInfoToDriver (FormSet
, Form
);
2462 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2463 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2466 // Discard Buffer storage or Name/Value storage
2468 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2469 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2470 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2471 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2473 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2478 // Skip if there is no RequestElement
2480 if (Storage
->ElementCount
== 0) {
2484 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2487 Link
= GetFirstNode (&FormSet
->FormListHead
);
2488 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2489 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2490 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2493 // Call callback with Changed type to inform the driver.
2495 SendDiscardInfoToDriver (FormSet
, Form
);
2498 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2499 } else if (SettingScope
== SystemLevel
) {
2501 // System Level Discard.
2503 OldFormSet
= mSystemLevelFormSet
;
2506 // Discard changed value for each FormSet in the maintain list.
2508 Link
= GetFirstNode (&gBrowserFormSetList
);
2509 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2510 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2511 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2512 if (!ValidateFormSet(LocalFormSet
)) {
2516 mSystemLevelFormSet
= LocalFormSet
;
2518 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2519 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2521 // Remove maintain backup list after discard except for the current using FormSet.
2523 CleanBrowserStorage(LocalFormSet
);
2524 RemoveEntryList (&LocalFormSet
->Link
);
2525 DestroyFormSet (LocalFormSet
);
2529 mSystemLevelFormSet
= OldFormSet
;
2536 Submit data based on the input Setting level (Form, FormSet or System).
2538 @param FormSet FormSet data structure.
2539 @param Form Form data structure.
2540 @param SettingScope Setting Scope for Submit action.
2542 @retval EFI_SUCCESS The function completed successfully.
2543 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2548 IN FORM_BROWSER_FORMSET
*FormSet
,
2549 IN FORM_BROWSER_FORM
*Form
,
2550 IN BROWSER_SETTING_SCOPE SettingScope
2555 EFI_STRING ConfigResp
;
2556 EFI_STRING Progress
;
2557 BROWSER_STORAGE
*Storage
;
2558 FORMSET_STORAGE
*FormSetStorage
;
2559 FORM_BROWSER_FORMSET
*LocalFormSet
;
2560 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2563 // Check the supported setting level.
2565 if (SettingScope
>= MaxLevel
) {
2566 return EFI_UNSUPPORTED
;
2570 // Validate the Form by NoSubmit check
2572 Status
= EFI_SUCCESS
;
2573 if (SettingScope
== FormLevel
) {
2574 Status
= NoSubmitCheck (FormSet
, Form
);
2575 } else if (SettingScope
== FormSetLevel
) {
2576 Status
= NoSubmitCheck (FormSet
, NULL
);
2578 if (EFI_ERROR (Status
)) {
2582 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2584 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2585 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2586 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2587 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2589 Storage
= ConfigInfo
->Storage
;
2590 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2595 // Skip if there is no RequestElement
2597 if (ConfigInfo
->ElementCount
== 0) {
2602 // 1. Prepare <ConfigResp>
2604 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2605 if (EFI_ERROR (Status
)) {
2610 // 2. Set value to hii config routine protocol.
2612 Status
= mHiiConfigRouting
->RouteConfig (
2617 if (EFI_ERROR (Status
)) {
2618 FreePool (ConfigResp
);
2622 FreePool (ConfigResp
);
2624 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2626 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2630 // 4. Update the NV flag.
2632 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2633 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2635 // Submit Buffer storage or Name/Value storage
2637 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2638 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2639 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2640 Storage
= FormSetStorage
->BrowserStorage
;
2641 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2643 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2648 // Skip if there is no RequestElement
2650 if (FormSetStorage
->ElementCount
== 0) {
2655 // 1. Prepare <ConfigResp>
2657 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2658 if (EFI_ERROR (Status
)) {
2663 // 2. Send <ConfigResp> to Routine config Protocol.
2665 Status
= mHiiConfigRouting
->RouteConfig (
2670 if (EFI_ERROR (Status
)) {
2671 FreePool (ConfigResp
);
2675 FreePool (ConfigResp
);
2677 // 3. Config success, update storage shadow Buffer
2679 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2683 // 4. Update the NV flag.
2685 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2686 } else if (SettingScope
== SystemLevel
) {
2688 // System Level Save.
2692 // Save changed value for each FormSet in the maintain list.
2694 Link
= GetFirstNode (&gBrowserFormSetList
);
2695 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2696 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2697 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2698 if (!ValidateFormSet(LocalFormSet
)) {
2701 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2702 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2704 // Remove maintain backup list after save except for the current using FormSet.
2706 CleanBrowserStorage(LocalFormSet
);
2707 RemoveEntryList (&LocalFormSet
->Link
);
2708 DestroyFormSet (LocalFormSet
);
2717 Get Question default value from AltCfg string.
2719 @param FormSet The form set.
2720 @param Question The question.
2721 @param DefaultId The default Id.
2723 @retval EFI_SUCCESS Question is reset to default value.
2727 GetDefaultValueFromAltCfg (
2728 IN FORM_BROWSER_FORMSET
*FormSet
,
2729 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2733 BOOLEAN IsBufferStorage
;
2736 BROWSER_STORAGE
*Storage
;
2737 CHAR16
*ConfigRequest
;
2750 Status
= EFI_NOT_FOUND
;
2753 ConfigRequest
= NULL
;
2757 Storage
= Question
->Storage
;
2759 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2764 // Question Value is provided by Buffer Storage or NameValue Storage
2766 if (Question
->BufferValue
!= NULL
) {
2768 // This Question is password or orderedlist
2770 Dst
= Question
->BufferValue
;
2773 // Other type of Questions
2775 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2778 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2779 IsBufferStorage
= TRUE
;
2781 IsBufferStorage
= FALSE
;
2783 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2786 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2787 // <ConfigHdr> + "&" + <VariableName>
2789 if (IsBufferStorage
) {
2790 Length
= StrLen (Storage
->ConfigHdr
);
2791 Length
+= StrLen (Question
->BlockName
);
2793 Length
= StrLen (Storage
->ConfigHdr
);
2794 Length
+= StrLen (Question
->VariableName
) + 1;
2796 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2797 ASSERT (ConfigRequest
!= NULL
);
2799 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2800 if (IsBufferStorage
) {
2801 StrCat (ConfigRequest
, Question
->BlockName
);
2803 StrCat (ConfigRequest
, L
"&");
2804 StrCat (ConfigRequest
, Question
->VariableName
);
2807 Status
= mHiiConfigRouting
->ExtractConfig (
2813 if (EFI_ERROR (Status
)) {
2818 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2819 // Get the default configuration string according to the default ID.
2821 Status
= mHiiConfigRouting
->GetAltConfig (
2827 &DefaultId
, // it can be NULL to get the current setting.
2832 // The required setting can't be found. So, it is not required to be validated and set.
2834 if (EFI_ERROR (Status
)) {
2838 if (ConfigResp
== NULL
) {
2839 Status
= EFI_NOT_FOUND
;
2844 // Skip <ConfigRequest>
2846 if (IsBufferStorage
) {
2847 Value
= StrStr (ConfigResp
, L
"&VALUE");
2848 ASSERT (Value
!= NULL
);
2854 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2855 ASSERT (Value
!= NULL
);
2857 Value
= Value
+ StrLen (Question
->VariableName
);
2859 if (*Value
!= '=') {
2860 Status
= EFI_NOT_FOUND
;
2864 // Skip '=', point to value
2869 // Suppress <AltResp> if any
2872 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2877 LengthStr
= StrLen (Value
);
2878 if (!IsBufferStorage
&& IsString
) {
2879 StringPtr
= (CHAR16
*) Dst
;
2880 ZeroMem (TemStr
, sizeof (TemStr
));
2881 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2882 StrnCpy (TemStr
, Value
+ Index
, 4);
2883 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2886 // Add tailing L'\0' character
2888 StringPtr
[Index
/4] = L
'\0';
2890 ZeroMem (TemStr
, sizeof (TemStr
));
2891 for (Index
= 0; Index
< LengthStr
; Index
++) {
2892 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2893 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2894 if ((Index
& 1) == 0) {
2895 Dst
[Index
/2] = DigitUint8
;
2897 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2903 if (ConfigRequest
!= NULL
){
2904 FreePool (ConfigRequest
);
2907 if (ConfigResp
!= NULL
) {
2908 FreePool (ConfigResp
);
2911 if (Result
!= NULL
) {
2919 Get default Id value used for browser.
2921 @param DefaultId The default id value used by hii.
2923 @retval Browser used default value.
2927 GetDefaultIdForCallBack (
2931 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2932 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2933 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2934 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2935 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2936 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2937 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2938 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2939 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2940 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2941 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2942 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2951 Return data element in an Array by its Index.
2953 @param Array The data array.
2954 @param Type Type of the data in this array.
2955 @param Index Zero based index for data in this array.
2957 @retval Value The data to be returned
2969 ASSERT (Array
!= NULL
);
2973 case EFI_IFR_TYPE_NUM_SIZE_8
:
2974 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2977 case EFI_IFR_TYPE_NUM_SIZE_16
:
2978 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2981 case EFI_IFR_TYPE_NUM_SIZE_32
:
2982 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2985 case EFI_IFR_TYPE_NUM_SIZE_64
:
2986 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
2998 Set value of a data element in an Array by its Index.
3000 @param Array The data array.
3001 @param Type Type of the data in this array.
3002 @param Index Zero based index for data in this array.
3003 @param Value The value to be set.
3015 ASSERT (Array
!= NULL
);
3018 case EFI_IFR_TYPE_NUM_SIZE_8
:
3019 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3022 case EFI_IFR_TYPE_NUM_SIZE_16
:
3023 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3026 case EFI_IFR_TYPE_NUM_SIZE_32
:
3027 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3030 case EFI_IFR_TYPE_NUM_SIZE_64
:
3031 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3040 Search an Option of a Question by its value.
3042 @param Question The Question
3043 @param OptionValue Value for Option to be searched.
3045 @retval Pointer Pointer to the found Option.
3046 @retval NULL Option not found.
3051 IN FORM_BROWSER_STATEMENT
*Question
,
3052 IN EFI_HII_VALUE
*OptionValue
3056 QUESTION_OPTION
*Option
;
3059 Link
= GetFirstNode (&Question
->OptionListHead
);
3060 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3061 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3063 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3065 // Check the suppressif condition, only a valid option can be return.
3067 if ((Option
->SuppressExpression
== NULL
) ||
3068 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3073 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3081 Reset Question to its default value.
3083 @param FormSet The form set.
3084 @param Form The form.
3085 @param Question The question.
3086 @param DefaultId The Class of the default.
3088 @retval EFI_SUCCESS Question is reset to default value.
3092 GetQuestionDefault (
3093 IN FORM_BROWSER_FORMSET
*FormSet
,
3094 IN FORM_BROWSER_FORM
*Form
,
3095 IN FORM_BROWSER_STATEMENT
*Question
,
3101 QUESTION_DEFAULT
*Default
;
3102 QUESTION_OPTION
*Option
;
3103 EFI_HII_VALUE
*HiiValue
;
3105 EFI_STRING StrValue
;
3106 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3107 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3111 Status
= EFI_NOT_FOUND
;
3115 // Statement don't have storage, skip them
3117 if (Question
->QuestionId
== 0) {
3122 // There are Five ways to specify default value for a Question:
3123 // 1, use call back function (highest priority)
3124 // 2, use ExtractConfig function
3125 // 3, use nested EFI_IFR_DEFAULT
3126 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3127 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3129 HiiValue
= &Question
->HiiValue
;
3132 // Get Question defaut value from call back function.
3134 ConfigAccess
= FormSet
->ConfigAccess
;
3135 Action
= GetDefaultIdForCallBack (DefaultId
);
3136 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3137 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3138 Status
= ConfigAccess
->Callback (
3141 Question
->QuestionId
,
3146 if (!EFI_ERROR (Status
)) {
3147 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3148 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3149 ASSERT (NewString
!= NULL
);
3151 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3152 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3153 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3155 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3158 FreePool (NewString
);
3165 // Get default value from altcfg string.
3167 if (ConfigAccess
!= NULL
) {
3168 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3169 if (!EFI_ERROR (Status
)) {
3175 // EFI_IFR_DEFAULT has highest priority
3177 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3178 Link
= GetFirstNode (&Question
->DefaultListHead
);
3179 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3180 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3182 if (Default
->DefaultId
== DefaultId
) {
3183 if (Default
->ValueExpression
!= NULL
) {
3185 // Default is provided by an Expression, evaluate it
3187 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3188 if (EFI_ERROR (Status
)) {
3192 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3193 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3194 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3195 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3196 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3198 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3199 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3201 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3203 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3204 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3207 // Default value is embedded in EFI_IFR_DEFAULT
3209 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3212 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3213 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3214 if (StrValue
== NULL
) {
3215 return EFI_NOT_FOUND
;
3217 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3218 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3220 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3227 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3232 // EFI_ONE_OF_OPTION
3234 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3235 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3237 // OneOfOption could only provide Standard and Manufacturing default
3239 Link
= GetFirstNode (&Question
->OptionListHead
);
3240 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3241 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3242 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3244 if ((Option
->SuppressExpression
!= NULL
) &&
3245 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3249 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3250 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3252 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3261 // EFI_IFR_CHECKBOX - lowest priority
3263 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3264 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3266 // Checkbox could only provide Standard and Manufacturing default
3268 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3269 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3271 HiiValue
->Value
.b
= TRUE
;
3273 HiiValue
->Value
.b
= FALSE
;
3281 // For Questions without default
3283 Status
= EFI_NOT_FOUND
;
3284 switch (Question
->Operand
) {
3285 case EFI_IFR_NUMERIC_OP
:
3287 // Take minimum value as numeric default value
3289 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3290 HiiValue
->Value
.u64
= Question
->Minimum
;
3291 Status
= EFI_SUCCESS
;
3295 case EFI_IFR_ONE_OF_OP
:
3297 // Take first oneof option as oneof's default value
3299 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3300 Link
= GetFirstNode (&Question
->OptionListHead
);
3301 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3302 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3303 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3305 if ((Option
->SuppressExpression
!= NULL
) &&
3306 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3310 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3311 Status
= EFI_SUCCESS
;
3317 case EFI_IFR_ORDERED_LIST_OP
:
3319 // Take option sequence in IFR as ordered list's default value
3322 Link
= GetFirstNode (&Question
->OptionListHead
);
3323 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3324 Status
= EFI_SUCCESS
;
3325 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3326 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3328 if ((Option
->SuppressExpression
!= NULL
) &&
3329 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3333 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3336 if (Index
>= Question
->MaxContainers
) {
3351 Reset Questions to their initial value or default value in a Form, Formset or System.
3353 GetDefaultValueScope parameter decides which questions will reset
3354 to its default value.
3356 @param FormSet FormSet data structure.
3357 @param Form Form data structure.
3358 @param DefaultId The Class of the default.
3359 @param SettingScope Setting Scope for Default action.
3360 @param GetDefaultValueScope Get default value scope.
3361 @param Storage Get default value only for this storage.
3362 @param RetrieveValueFirst Whether call the retrieve call back to
3363 get the initial value before get default
3366 @retval EFI_SUCCESS The function completed successfully.
3367 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3372 IN FORM_BROWSER_FORMSET
*FormSet
,
3373 IN FORM_BROWSER_FORM
*Form
,
3374 IN UINT16 DefaultId
,
3375 IN BROWSER_SETTING_SCOPE SettingScope
,
3376 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3377 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3378 IN BOOLEAN RetrieveValueFirst
3382 LIST_ENTRY
*FormLink
;
3384 FORM_BROWSER_STATEMENT
*Question
;
3385 FORM_BROWSER_FORMSET
*LocalFormSet
;
3386 FORM_BROWSER_FORMSET
*OldFormSet
;
3388 Status
= EFI_SUCCESS
;
3391 // Check the supported setting level.
3393 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3394 return EFI_UNSUPPORTED
;
3397 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3398 return EFI_UNSUPPORTED
;
3401 if (SettingScope
== FormLevel
) {
3403 // Extract Form default
3405 Link
= GetFirstNode (&Form
->StatementListHead
);
3406 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3407 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3408 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3411 // If get default value only for this storage, check the storage first.
3413 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3418 // If get default value only for no storage question, just skip the question which has storage.
3420 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3425 // If Question is disabled, don't reset it to default
3427 if (Question
->Expression
!= NULL
) {
3428 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3433 if (RetrieveValueFirst
) {
3435 // Call the Retrieve call back to get the initial question value.
3437 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
3441 // If not request to get the initial value or get initial value fail, then get default value.
3443 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3444 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3445 if (EFI_ERROR (Status
)) {
3451 // Synchronize Buffer storage's Edit buffer
3453 if ((Question
->Storage
!= NULL
) &&
3454 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3455 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3458 } else if (SettingScope
== FormSetLevel
) {
3459 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3460 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3461 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3462 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3463 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3465 } else if (SettingScope
== SystemLevel
) {
3467 // Preload all Hii formset.
3469 LoadAllHiiFormset();
3471 OldFormSet
= mSystemLevelFormSet
;
3474 // Set Default Value for each FormSet in the maintain list.
3476 Link
= GetFirstNode (&gBrowserFormSetList
);
3477 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3478 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3479 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3480 if (!ValidateFormSet(LocalFormSet
)) {
3484 mSystemLevelFormSet
= LocalFormSet
;
3486 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3489 mSystemLevelFormSet
= OldFormSet
;
3497 Validate whether this question's value has changed.
3499 @param FormSet FormSet data structure.
3500 @param Form Form data structure.
3501 @param Question Question to be initialized.
3502 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3504 @retval TRUE Question's value has changed.
3505 @retval FALSE Question's value has not changed
3509 IsQuestionValueChanged (
3510 IN FORM_BROWSER_FORMSET
*FormSet
,
3511 IN FORM_BROWSER_FORM
*Form
,
3512 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3513 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3516 EFI_HII_VALUE BackUpValue
;
3517 CHAR8
*BackUpBuffer
;
3519 BOOLEAN ValueChanged
;
3523 // For quetion without storage, always mark it as data not changed.
3525 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3529 BackUpBuffer
= NULL
;
3530 ValueChanged
= FALSE
;
3532 switch (Question
->Operand
) {
3533 case EFI_IFR_ORDERED_LIST_OP
:
3534 BufferWidth
= Question
->StorageWidth
;
3535 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3536 ASSERT (BackUpBuffer
!= NULL
);
3539 case EFI_IFR_STRING_OP
:
3540 case EFI_IFR_PASSWORD_OP
:
3541 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3542 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3543 ASSERT (BackUpBuffer
!= NULL
);
3550 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3552 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3553 ASSERT_EFI_ERROR(Status
);
3555 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3556 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3557 ValueChanged
= TRUE
;
3560 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3561 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3563 if (BackUpBuffer
!= NULL
) {
3564 FreePool (BackUpBuffer
);
3567 Question
->ValueChanged
= ValueChanged
;
3569 return ValueChanged
;
3573 Initialize Question's Edit copy from Storage.
3575 @param Selection Selection contains the information about
3576 the Selection, form and formset to be displayed.
3577 Selection action may be updated in retrieve callback.
3578 If Selection is NULL, only initialize Question value.
3579 @param FormSet FormSet data structure.
3580 @param Form Form data structure.
3582 @retval EFI_SUCCESS The function completed successfully.
3587 IN OUT UI_MENU_SELECTION
*Selection
,
3588 IN FORM_BROWSER_FORMSET
*FormSet
,
3589 IN FORM_BROWSER_FORM
*Form
3594 FORM_BROWSER_STATEMENT
*Question
;
3596 Link
= GetFirstNode (&Form
->StatementListHead
);
3597 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3598 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3601 // Initialize local copy of Value for each Question
3603 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3604 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3606 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3608 if (EFI_ERROR (Status
)) {
3612 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3613 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3616 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3623 Initialize Question's Edit copy from Storage for the whole Formset.
3625 @param Selection Selection contains the information about
3626 the Selection, form and formset to be displayed.
3627 Selection action may be updated in retrieve callback.
3628 If Selection is NULL, only initialize Question value.
3629 @param FormSet FormSet data structure.
3631 @retval EFI_SUCCESS The function completed successfully.
3636 IN OUT UI_MENU_SELECTION
*Selection
,
3637 IN FORM_BROWSER_FORMSET
*FormSet
3642 FORM_BROWSER_FORM
*Form
;
3644 Link
= GetFirstNode (&FormSet
->FormListHead
);
3645 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3646 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3649 // Initialize local copy of Value for each Form
3651 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3652 if (EFI_ERROR (Status
)) {
3656 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3660 // Finished question initialization.
3662 FormSet
->QuestionInited
= TRUE
;
3668 Remove the Request element from the Config Request.
3670 @param Storage Pointer to the browser storage.
3671 @param RequestElement The pointer to the Request element.
3676 IN OUT BROWSER_STORAGE
*Storage
,
3677 IN CHAR16
*RequestElement
3683 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3685 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3687 if (NewStr
== NULL
) {
3692 // Remove this element from this ConfigRequest.
3695 NewStr
+= StrLen (RequestElement
);
3696 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3698 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3702 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3704 @param Storage Pointer to the browser storage.
3705 @param ConfigRequest The pointer to the Request element.
3709 RemoveConfigRequest (
3710 BROWSER_STORAGE
*Storage
,
3711 CHAR16
*ConfigRequest
3714 CHAR16
*RequestElement
;
3715 CHAR16
*NextRequestElement
;
3719 // No request element in it, just return.
3721 if (ConfigRequest
== NULL
) {
3725 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3727 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3732 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3734 SearchKey
= L
"&OFFSET";
3738 // Find SearchKey storage
3740 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3741 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3742 ASSERT (RequestElement
!= NULL
);
3743 RequestElement
= StrStr (RequestElement
, SearchKey
);
3745 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3748 while (RequestElement
!= NULL
) {
3750 // +1 to avoid find header itself.
3752 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3755 // The last Request element in configRequest string.
3757 if (NextRequestElement
!= NULL
) {
3759 // Replace "&" with '\0'.
3761 *NextRequestElement
= L
'\0';
3764 RemoveElement (Storage
, RequestElement
);
3766 if (NextRequestElement
!= NULL
) {
3768 // Restore '&' with '\0' for later used.
3770 *NextRequestElement
= L
'&';
3773 RequestElement
= NextRequestElement
;
3777 // If no request element remain, just remove the ConfigRequest string.
3779 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3780 FreePool (Storage
->ConfigRequest
);
3781 Storage
->ConfigRequest
= NULL
;
3782 Storage
->SpareStrLen
= 0;
3787 Base on the current formset info, clean the ConfigRequest string in browser storage.
3789 @param FormSet Pointer of the FormSet
3793 CleanBrowserStorage (
3794 IN OUT FORM_BROWSER_FORMSET
*FormSet
3798 FORMSET_STORAGE
*Storage
;
3800 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3801 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3802 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3803 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3805 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3806 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3810 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
3811 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3812 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3813 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3814 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3815 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
3817 Storage
->BrowserStorage
->Initialized
= FALSE
;
3823 Check whether current element in the ConfigReqeust string.
3825 @param BrowserStorage Storage which includes ConfigReqeust.
3826 @param RequestElement New element need to check.
3828 @retval TRUE The Element is in the ConfigReqeust string.
3829 @retval FALSE The Element not in the configReqeust String.
3834 BROWSER_STORAGE
*BrowserStorage
,
3835 CHAR16
*RequestElement
3838 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3842 Append the Request element to the Config Request.
3844 @param ConfigRequest Current ConfigRequest info.
3845 @param SpareStrLen Current remain free buffer for config reqeust.
3846 @param RequestElement New Request element.
3850 AppendConfigRequest (
3851 IN OUT CHAR16
**ConfigRequest
,
3852 IN OUT UINTN
*SpareStrLen
,
3853 IN CHAR16
*RequestElement
3860 StrLength
= StrLen (RequestElement
);
3863 // Append <RequestElement> to <ConfigRequest>
3865 if (StrLength
> *SpareStrLen
) {
3867 // Old String buffer is not sufficient for RequestElement, allocate a new one
3869 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3870 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3871 ASSERT (NewStr
!= NULL
);
3873 if (*ConfigRequest
!= NULL
) {
3874 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3875 FreePool (*ConfigRequest
);
3877 *ConfigRequest
= NewStr
;
3878 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3881 StrCat (*ConfigRequest
, RequestElement
);
3882 *SpareStrLen
-= StrLength
;
3886 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3888 @param Storage Form set Storage.
3889 @param Request The input request string.
3890 @param RespString Whether the input is ConfigRequest or ConfigResp format.
3892 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3893 @retval FALSE All elements covered by current used elements.
3897 ConfigRequestAdjust (
3898 IN BROWSER_STORAGE
*Storage
,
3900 IN BOOLEAN RespString
3903 CHAR16
*RequestElement
;
3904 CHAR16
*NextRequestElement
;
3905 CHAR16
*NextElementBakup
;
3910 CHAR16
*ConfigRequest
;
3914 NextElementBakup
= NULL
;
3917 if (Request
!= NULL
) {
3918 ConfigRequest
= Request
;
3920 ConfigRequest
= Storage
->ConfigRequest
;
3923 if (Storage
->ConfigRequest
== NULL
) {
3924 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3928 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3930 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3935 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3937 SearchKey
= L
"&OFFSET";
3938 ValueKey
= L
"&VALUE";
3942 // Find SearchKey storage
3944 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3945 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3946 ASSERT (RequestElement
!= NULL
);
3947 RequestElement
= StrStr (RequestElement
, SearchKey
);
3949 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3952 while (RequestElement
!= NULL
) {
3955 // +1 to avoid find header itself.
3957 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3960 // The last Request element in configRequest string.
3962 if (NextRequestElement
!= NULL
) {
3963 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3964 NextElementBakup
= NextRequestElement
;
3965 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3966 ASSERT (NextRequestElement
!= NULL
);
3969 // Replace "&" with '\0'.
3971 *NextRequestElement
= L
'\0';
3973 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3974 NextElementBakup
= NextRequestElement
;
3975 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3976 ASSERT (NextRequestElement
!= NULL
);
3978 // Replace "&" with '\0'.
3980 *NextRequestElement
= L
'\0';
3984 if (!ElementValidation (Storage
, RequestElement
)) {
3986 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3988 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
3992 if (NextRequestElement
!= NULL
) {
3994 // Restore '&' with '\0' for later used.
3996 *NextRequestElement
= L
'&';
3999 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4000 RequestElement
= NextElementBakup
;
4002 RequestElement
= NextRequestElement
;
4011 Base on ConfigRequest info to get default value for current formset.
4013 ConfigRequest info include the info about which questions in current formset need to
4014 get default value. This function only get these questions default value.
4016 @param FormSet FormSet data structure.
4017 @param Storage Storage need to update value.
4018 @param ConfigRequest The config request string.
4022 GetDefaultForFormset (
4023 IN FORM_BROWSER_FORMSET
*FormSet
,
4024 IN BROWSER_STORAGE
*Storage
,
4025 IN CHAR16
*ConfigRequest
4030 LIST_ENTRY BackUpList
;
4031 NAME_VALUE_NODE
*Node
;
4033 LIST_ENTRY
*NodeLink
;
4034 NAME_VALUE_NODE
*TmpNode
;
4036 EFI_STRING Progress
;
4040 InitializeListHead(&BackUpList
);
4043 // Back update the edit buffer.
4045 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4046 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4047 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4048 ASSERT (BackUpBuf
!= NULL
);
4049 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4050 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4051 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4052 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4053 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4056 // Only back Node belong to this formset.
4058 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4062 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4063 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4064 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4066 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4071 // Get default value.
4073 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4076 // Update the question value based on the input ConfigRequest.
4078 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4079 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4080 ASSERT (BackUpBuf
!= NULL
);
4081 BufferSize
= Storage
->Size
;
4082 Status
= mHiiConfigRouting
->BlockToConfig(
4085 Storage
->EditBuffer
,
4090 ASSERT_EFI_ERROR (Status
);
4092 Status
= mHiiConfigRouting
->ConfigToBlock (
4099 ASSERT_EFI_ERROR (Status
);
4101 if (Result
!= NULL
) {
4105 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4106 FreePool (BackUpBuf
);
4107 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4109 // Update question value, only element in ConfigReqeust will be update.
4111 Link
= GetFirstNode (&BackUpList
);
4112 while (!IsNull (&BackUpList
, Link
)) {
4113 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4114 Link
= GetNextNode (&BackUpList
, Link
);
4116 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4120 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4121 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4122 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4123 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4125 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4129 FreePool (TmpNode
->EditValue
);
4130 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4132 RemoveEntryList (&Node
->Link
);
4133 FreePool (Node
->EditValue
);
4134 FreePool (Node
->Name
);
4140 // Restore the Name/Value node.
4142 Link
= GetFirstNode (&BackUpList
);
4143 while (!IsNull (&BackUpList
, Link
)) {
4144 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4145 Link
= GetNextNode (&BackUpList
, Link
);
4150 RemoveEntryList (&Node
->Link
);
4151 FreePool (Node
->EditValue
);
4152 FreePool (Node
->Name
);
4159 Fill storage's edit copy with settings requested from Configuration Driver.
4161 @param FormSet FormSet data structure.
4162 @param Storage Buffer Storage.
4167 IN FORM_BROWSER_FORMSET
*FormSet
,
4168 IN FORMSET_STORAGE
*Storage
4172 EFI_STRING Progress
;
4175 EFI_STRING ConfigRequest
;
4178 ConfigRequest
= NULL
;
4180 switch (Storage
->BrowserStorage
->Type
) {
4181 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4184 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4185 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4186 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4191 case EFI_HII_VARSTORE_BUFFER
:
4192 case EFI_HII_VARSTORE_NAME_VALUE
:
4194 // Skip if there is no RequestElement.
4196 if (Storage
->ElementCount
== 0) {
4201 // Just update the ConfigRequest, if storage already initialized.
4203 if (Storage
->BrowserStorage
->Initialized
) {
4204 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4208 Storage
->BrowserStorage
->Initialized
= TRUE
;
4215 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4217 // Create the config request string to get all fields for this storage.
4218 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4219 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4221 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4222 ConfigRequest
= AllocateZeroPool (StrLen
);
4223 ASSERT (ConfigRequest
!= NULL
);
4227 L
"%s&OFFSET=0&WIDTH=%04x",
4228 Storage
->BrowserStorage
->ConfigHdr
,
4229 Storage
->BrowserStorage
->Size
);
4231 ConfigRequest
= Storage
->ConfigRequest
;
4235 // Request current settings from Configuration Driver
4237 Status
= mHiiConfigRouting
->ExtractConfig (
4245 // If get value fail, extract default from IFR binary
4247 if (EFI_ERROR (Status
)) {
4248 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4251 // Convert Result from <ConfigAltResp> to <ConfigResp>
4253 StrPtr
= StrStr (Result
, L
"&GUID=");
4254 if (StrPtr
!= NULL
) {
4258 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4262 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4265 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4267 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4269 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4270 if (ConfigRequest
!= NULL
) {
4271 FreePool (ConfigRequest
);
4277 Get Value changed status from old question.
4279 @param NewFormSet FormSet data structure.
4280 @param OldQuestion Old question which has value changed.
4284 SyncStatusForQuestion (
4285 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4286 IN FORM_BROWSER_STATEMENT
*OldQuestion
4290 LIST_ENTRY
*QuestionLink
;
4291 FORM_BROWSER_FORM
*Form
;
4292 FORM_BROWSER_STATEMENT
*Question
;
4295 // For each form in one formset.
4297 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4298 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4299 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4300 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4303 // for each question in one form.
4305 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4306 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4307 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4308 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4310 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4311 Question
->ValueChanged
= TRUE
;
4319 Get Value changed status from old formset.
4321 @param NewFormSet FormSet data structure.
4322 @param OldFormSet FormSet data structure.
4326 SyncStatusForFormSet (
4327 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4328 IN FORM_BROWSER_FORMSET
*OldFormSet
4332 LIST_ENTRY
*QuestionLink
;
4333 FORM_BROWSER_FORM
*Form
;
4334 FORM_BROWSER_STATEMENT
*Question
;
4337 // For each form in one formset.
4339 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4340 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4341 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4342 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4345 // for each question in one form.
4347 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4348 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4349 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4350 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4352 if (!Question
->ValueChanged
) {
4357 // Find the same question in new formset and update the value changed flag.
4359 SyncStatusForQuestion (NewFormSet
, Question
);
4365 Get current setting of Questions.
4367 @param FormSet FormSet data structure.
4371 InitializeCurrentSetting (
4372 IN OUT FORM_BROWSER_FORMSET
*FormSet
4376 FORMSET_STORAGE
*Storage
;
4377 FORM_BROWSER_FORMSET
*OldFormSet
;
4380 // Try to find pre FormSet in the maintain backup list.
4381 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4383 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4384 if (OldFormSet
!= NULL
) {
4385 SyncStatusForFormSet (FormSet
, OldFormSet
);
4386 RemoveEntryList (&OldFormSet
->Link
);
4387 DestroyFormSet (OldFormSet
);
4389 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4392 // Extract default from IFR binary for no storage questions.
4394 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4397 // Request current settings from Configuration Driver
4399 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4400 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4401 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4403 LoadStorage (FormSet
, Storage
);
4405 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4411 Fetch the Ifr binary data of a FormSet.
4413 @param Handle PackageList Handle
4414 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4415 specified (NULL or zero GUID), take the first
4416 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4417 found in package list.
4418 On output, GUID of the formset found(if not NULL).
4419 @param BinaryLength The length of the FormSet IFR binary.
4420 @param BinaryData The buffer designed to receive the FormSet.
4422 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4423 BufferLength was updated.
4424 @retval EFI_INVALID_PARAMETER The handle is unknown.
4425 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4426 be found with the requested FormId.
4431 IN EFI_HII_HANDLE Handle
,
4432 IN OUT EFI_GUID
*FormSetGuid
,
4433 OUT UINTN
*BinaryLength
,
4434 OUT UINT8
**BinaryData
4438 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4444 UINT32 PackageListLength
;
4445 EFI_HII_PACKAGE_HEADER PackageHeader
;
4447 UINT8 NumberOfClassGuid
;
4448 BOOLEAN ClassGuidMatch
;
4449 EFI_GUID
*ClassGuid
;
4450 EFI_GUID
*ComparingGuid
;
4454 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4457 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4459 if (FormSetGuid
== NULL
) {
4460 ComparingGuid
= &gZeroGuid
;
4462 ComparingGuid
= FormSetGuid
;
4466 // Get HII PackageList
4469 HiiPackageList
= NULL
;
4470 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4471 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4472 HiiPackageList
= AllocatePool (BufferSize
);
4473 ASSERT (HiiPackageList
!= NULL
);
4475 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4477 if (EFI_ERROR (Status
)) {
4480 ASSERT (HiiPackageList
!= NULL
);
4483 // Get Form package from this HII package List
4485 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4487 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4489 ClassGuidMatch
= FALSE
;
4490 while (Offset
< PackageListLength
) {
4491 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4492 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4494 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4496 // Search FormSet in this Form Package
4498 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4499 while (Offset2
< PackageHeader
.Length
) {
4500 OpCodeData
= Package
+ Offset2
;
4502 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4504 // Try to compare against formset GUID
4506 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4507 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4511 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4513 // Try to compare against formset class GUID
4515 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4516 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4517 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4518 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4519 ClassGuidMatch
= TRUE
;
4523 if (ClassGuidMatch
) {
4526 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4527 ClassGuidMatch
= TRUE
;
4532 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4535 if (Offset2
< PackageHeader
.Length
) {
4537 // Target formset found
4543 Offset
+= PackageHeader
.Length
;
4546 if (Offset
>= PackageListLength
) {
4548 // Form package not found in this Package List
4550 FreePool (HiiPackageList
);
4551 return EFI_NOT_FOUND
;
4554 if (FormSetGuid
!= NULL
) {
4556 // Return the FormSet GUID
4558 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4562 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4563 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4564 // of the Form Package.
4566 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4567 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4569 FreePool (HiiPackageList
);
4571 if (*BinaryData
== NULL
) {
4572 return EFI_OUT_OF_RESOURCES
;
4580 Initialize the internal data structure of a FormSet.
4582 @param Handle PackageList Handle
4583 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4584 specified (NULL or zero GUID), take the first
4585 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4586 found in package list.
4587 On output, GUID of the formset found(if not NULL).
4588 @param FormSet FormSet data structure.
4590 @retval EFI_SUCCESS The function completed successfully.
4591 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4596 IN EFI_HII_HANDLE Handle
,
4597 IN OUT EFI_GUID
*FormSetGuid
,
4598 OUT FORM_BROWSER_FORMSET
*FormSet
4602 EFI_HANDLE DriverHandle
;
4604 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4605 if (EFI_ERROR (Status
)) {
4609 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4610 FormSet
->HiiHandle
= Handle
;
4611 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4612 FormSet
->QuestionInited
= FALSE
;
4615 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4617 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4618 if (EFI_ERROR (Status
)) {
4621 FormSet
->DriverHandle
= DriverHandle
;
4622 Status
= gBS
->HandleProtocol (
4624 &gEfiHiiConfigAccessProtocolGuid
,
4625 (VOID
**) &FormSet
->ConfigAccess
4627 if (EFI_ERROR (Status
)) {
4629 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4630 // list, then there will be no configuration action required
4632 FormSet
->ConfigAccess
= NULL
;
4636 // Parse the IFR binary OpCodes
4638 Status
= ParseOpCodes (FormSet
);
4645 Save globals used by previous call to SendForm(). SendForm() may be called from
4646 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4647 So, save globals of previous call to SendForm() and restore them upon exit.
4651 SaveBrowserContext (
4655 BROWSER_CONTEXT
*Context
;
4656 FORM_ENTRY_INFO
*MenuList
;
4658 gBrowserContextCount
++;
4659 if (gBrowserContextCount
== 1) {
4661 // This is not reentry of SendForm(), no context to save
4666 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4667 ASSERT (Context
!= NULL
);
4669 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4672 // Save FormBrowser context
4674 Context
->Selection
= gCurrentSelection
;
4675 Context
->ResetRequired
= gResetRequired
;
4676 Context
->ExitRequired
= gExitRequired
;
4677 Context
->HiiHandle
= mCurrentHiiHandle
;
4678 Context
->FormId
= mCurrentFormId
;
4679 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4682 // Save the menu history data.
4684 InitializeListHead(&Context
->FormHistoryList
);
4685 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4686 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4687 RemoveEntryList (&MenuList
->Link
);
4689 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4693 // Insert to FormBrowser context list
4695 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4700 Restore globals used by previous call to SendForm().
4704 RestoreBrowserContext (
4709 BROWSER_CONTEXT
*Context
;
4710 FORM_ENTRY_INFO
*MenuList
;
4712 ASSERT (gBrowserContextCount
!= 0);
4713 gBrowserContextCount
--;
4714 if (gBrowserContextCount
== 0) {
4716 // This is not reentry of SendForm(), no context to restore
4721 ASSERT (!IsListEmpty (&gBrowserContextList
));
4723 Link
= GetFirstNode (&gBrowserContextList
);
4724 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4727 // Restore FormBrowser context
4729 gCurrentSelection
= Context
->Selection
;
4730 gResetRequired
= Context
->ResetRequired
;
4731 gExitRequired
= Context
->ExitRequired
;
4732 mCurrentHiiHandle
= Context
->HiiHandle
;
4733 mCurrentFormId
= Context
->FormId
;
4734 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4737 // Restore the menu history data.
4739 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4740 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4741 RemoveEntryList (&MenuList
->Link
);
4743 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4747 // Remove from FormBrowser context list
4749 RemoveEntryList (&Context
->Link
);
4750 gBS
->FreePool (Context
);
4754 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4756 @param Handle The Hii Handle.
4758 @return the found FormSet context. If no found, NULL will return.
4761 FORM_BROWSER_FORMSET
*
4762 GetFormSetFromHiiHandle (
4763 EFI_HII_HANDLE Handle
4767 FORM_BROWSER_FORMSET
*FormSet
;
4769 Link
= GetFirstNode (&gBrowserFormSetList
);
4770 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4771 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4772 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4773 if (!ValidateFormSet(FormSet
)) {
4776 if (FormSet
->HiiHandle
== Handle
) {
4785 Check whether the input HII handle is the FormSet that is being used.
4787 @param Handle The Hii Handle.
4789 @retval TRUE HII handle is being used.
4790 @retval FALSE HII handle is not being used.
4794 IsHiiHandleInBrowserContext (
4795 EFI_HII_HANDLE Handle
4799 BROWSER_CONTEXT
*Context
;
4802 // HiiHandle is Current FormSet.
4804 if (mCurrentHiiHandle
== Handle
) {
4809 // Check whether HiiHandle is in BrowserContext.
4811 Link
= GetFirstNode (&gBrowserContextList
);
4812 while (!IsNull (&gBrowserContextList
, Link
)) {
4813 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4814 if (Context
->HiiHandle
== Handle
) {
4816 // HiiHandle is in BrowserContext
4820 Link
= GetNextNode (&gBrowserContextList
, Link
);
4827 Perform Password check.
4828 Passwork may be encrypted by driver that requires the specific check.
4830 @param Form Form where Password Statement is in.
4831 @param Statement Password statement
4832 @param PasswordString Password string to be checked. It may be NULL.
4833 NULL means to restore password.
4834 "" string can be used to checked whether old password does exist.
4836 @return Status Status of Password check.
4841 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4842 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4843 IN EFI_STRING PasswordString OPTIONAL
4847 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4848 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4849 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4850 FORM_BROWSER_STATEMENT
*Question
;
4852 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4853 Question
= GetBrowserStatement(Statement
);
4854 ASSERT (Question
!= NULL
);
4856 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4857 if (ConfigAccess
== NULL
) {
4858 return EFI_UNSUPPORTED
;
4861 if (PasswordString
== NULL
) {
4866 // Check whether has preexisted password.
4868 if (PasswordString
[0] == 0) {
4869 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
4872 return EFI_NOT_READY
;
4877 // Check whether the input password is same as preexisted password.
4879 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4882 return EFI_NOT_READY
;
4887 // Prepare password string in HII database
4889 if (PasswordString
!= NULL
) {
4890 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4892 IfrTypeValue
.string
= 0;
4896 // Send password to Configuration Driver for validation
4898 Status
= ConfigAccess
->Callback (
4900 EFI_BROWSER_ACTION_CHANGING
,
4901 Question
->QuestionId
,
4902 Question
->HiiValue
.Type
,
4908 // Remove password string from HII database
4910 if (PasswordString
!= NULL
) {
4911 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4918 Find the registered HotKey based on KeyData.
4920 @param[in] KeyData A pointer to a buffer that describes the keystroke
4921 information for the hot key.
4923 @return The registered HotKey context. If no found, NULL will return.
4926 GetHotKeyFromRegisterList (
4927 IN EFI_INPUT_KEY
*KeyData
4931 BROWSER_HOT_KEY
*HotKey
;
4933 Link
= GetFirstNode (&gBrowserHotKeyList
);
4934 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4935 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4936 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4939 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4946 Configure what scope the hot key will impact.
4947 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4948 If no scope is set, the default scope will be FormSet level.
4949 After all registered hot keys are removed, previous Scope can reset to another level.
4951 @param[in] Scope Scope level to be set.
4953 @retval EFI_SUCCESS Scope is set correctly.
4954 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4955 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4961 IN BROWSER_SETTING_SCOPE Scope
4964 if (Scope
>= MaxLevel
) {
4965 return EFI_INVALID_PARAMETER
;
4969 // When no hot key registered in system or on the first setting,
4970 // Scope can be set.
4972 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4973 gBrowserSettingScope
= Scope
;
4974 mBrowserScopeFirstSet
= FALSE
;
4975 } else if (Scope
!= gBrowserSettingScope
) {
4976 return EFI_UNSUPPORTED
;
4983 Register the hot key with its browser action, or unregistered the hot key.
4984 Only support hot key that is not printable character (control key, function key, etc.).
4985 If the action value is zero, the hot key will be unregistered if it has been registered.
4986 If the same hot key has been registered, the new action and help string will override the previous ones.
4988 @param[in] KeyData A pointer to a buffer that describes the keystroke
4989 information for the hot key. Its type is EFI_INPUT_KEY to
4990 be supported by all ConsoleIn devices.
4991 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4992 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4993 @param[in] HelpString Help string that describes the hot key information.
4994 Its value may be NULL for the unregistered hot key.
4996 @retval EFI_SUCCESS Hot key is registered or unregistered.
4997 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4998 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4999 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5004 IN EFI_INPUT_KEY
*KeyData
,
5006 IN UINT16 DefaultId
,
5007 IN EFI_STRING HelpString OPTIONAL
5010 BROWSER_HOT_KEY
*HotKey
;
5013 // Check input parameters.
5015 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5016 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5017 return EFI_INVALID_PARAMETER
;
5021 // Check whether the input KeyData is in BrowserHotKeyList.
5023 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5026 // Unregister HotKey
5028 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5029 if (HotKey
!= NULL
) {
5031 // The registered HotKey is found.
5032 // Remove it from List, and free its resource.
5034 RemoveEntryList (&HotKey
->Link
);
5035 FreePool (HotKey
->KeyData
);
5036 FreePool (HotKey
->HelpString
);
5040 // The registered HotKey is not found.
5042 return EFI_NOT_FOUND
;
5047 // Register HotKey into List.
5049 if (HotKey
== NULL
) {
5051 // Create new Key, and add it into List.
5053 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5054 ASSERT (HotKey
!= NULL
);
5055 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5056 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5057 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5061 // Fill HotKey information.
5063 HotKey
->Action
= Action
;
5064 HotKey
->DefaultId
= DefaultId
;
5065 if (HotKey
->HelpString
!= NULL
) {
5066 FreePool (HotKey
->HelpString
);
5068 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5074 Register Exit handler function.
5075 When more than one handler function is registered, the latter one will override the previous one.
5076 When NULL handler is specified, the previous Exit handler will be unregistered.
5078 @param[in] Handler Pointer to handler function.
5083 RegiserExitHandler (
5084 IN EXIT_HANDLER Handler
5087 ExitHandlerFunction
= Handler
;
5092 Check whether the browser data has been modified.
5094 @retval TRUE Browser data is modified.
5095 @retval FALSE No browser data is modified.
5100 IsBrowserDataModified (
5105 FORM_BROWSER_FORMSET
*FormSet
;
5107 switch (gBrowserSettingScope
) {
5109 if (gCurrentSelection
== NULL
) {
5112 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5115 if (gCurrentSelection
== NULL
) {
5118 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5121 Link
= GetFirstNode (&gBrowserFormSetList
);
5122 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5123 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5124 if (!ValidateFormSet(FormSet
)) {
5128 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5131 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5141 Execute the action requested by the Action parameter.
5143 @param[in] Action Execute the request action.
5144 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5146 @retval EFI_SUCCESS Execute the request action succss.
5147 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5158 FORM_BROWSER_FORMSET
*FormSet
;
5159 FORM_BROWSER_FORM
*Form
;
5161 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5162 return EFI_NOT_READY
;
5165 Status
= EFI_SUCCESS
;
5168 if (gBrowserSettingScope
< SystemLevel
) {
5169 FormSet
= gCurrentSelection
->FormSet
;
5170 Form
= gCurrentSelection
->Form
;
5174 // Executet the discard action.
5176 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5177 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5178 if (EFI_ERROR (Status
)) {
5184 // Executet the difault action.
5186 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5187 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5188 if (EFI_ERROR (Status
)) {
5191 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5195 // Executet the submit action.
5197 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5198 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5199 if (EFI_ERROR (Status
)) {
5205 // Executet the reset action.
5207 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5208 gResetRequired
= TRUE
;
5212 // Executet the exit action.
5214 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5215 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5216 if (gBrowserSettingScope
== SystemLevel
) {
5217 if (ExitHandlerFunction
!= NULL
) {
5218 ExitHandlerFunction ();
5222 gExitRequired
= TRUE
;
5229 Create reminder to let user to choose save or discard the changed browser data.
5230 Caller can use it to actively check the changed browser data.
5232 @retval BROWSER_NO_CHANGES No browser data is changed.
5233 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5234 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5235 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5245 FORM_BROWSER_FORMSET
*FormSet
;
5246 BOOLEAN IsDataChanged
;
5247 UINT32 DataSavedAction
;
5250 DataSavedAction
= BROWSER_NO_CHANGES
;
5251 IsDataChanged
= FALSE
;
5252 Link
= GetFirstNode (&gBrowserFormSetList
);
5253 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5254 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5255 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5256 if (!ValidateFormSet(FormSet
)) {
5259 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5260 IsDataChanged
= TRUE
;
5266 // No data is changed. No save is required.
5268 if (!IsDataChanged
) {
5269 return DataSavedAction
;
5273 // If data is changed, prompt user to save or discard it.
5276 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5278 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5279 SubmitForm (NULL
, NULL
, SystemLevel
);
5280 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5282 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5283 DiscardForm (NULL
, NULL
, SystemLevel
);
5284 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5286 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5287 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5292 return DataSavedAction
;
5296 Check whether the Reset Required for the browser
5298 @retval TRUE Browser required to reset after exit.
5299 @retval FALSE Browser not need to reset after exit.
5308 return gResetRequired
;