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
,
35 IsBrowserDataModified
,
40 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
41 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
42 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
43 EDKII_FORM_DISPLAY_ENGINE_PROTOCOL
*mFormDisplay
;
45 UINTN gBrowserContextCount
= 0;
46 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
47 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
48 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
49 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
51 BOOLEAN gResetRequired
;
52 BOOLEAN gExitRequired
;
53 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
54 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
55 EXIT_HANDLER ExitHandlerFunction
= NULL
;
56 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
59 // Browser Global Strings
62 CHAR16
*mUnknownString
= L
"!";
64 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
66 extern EFI_GUID mCurrentFormSetGuid
;
67 extern EFI_HII_HANDLE mCurrentHiiHandle
;
68 extern UINT16 mCurrentFormId
;
69 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
72 Create a menu with specified formset GUID and form ID, and add it as a child
73 of the given parent menu.
75 @param HiiHandle Hii handle related to this formset.
76 @param FormSetGuid The Formset Guid of menu to be added.
77 @param FormId The Form ID of menu to be added.
78 @param QuestionId The question id of this menu to be added.
80 @return A pointer to the newly added menu or NULL if memory is insufficient.
85 IN EFI_HII_HANDLE HiiHandle
,
86 IN EFI_GUID
*FormSetGuid
,
91 FORM_ENTRY_INFO
*MenuList
;
93 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
94 if (MenuList
== NULL
) {
98 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
100 MenuList
->HiiHandle
= HiiHandle
;
101 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
102 MenuList
->FormId
= FormId
;
103 MenuList
->QuestionId
= QuestionId
;
106 // If parent is not specified, it is the root Form of a Formset
108 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
114 Return the form id for the input hiihandle and formset.
116 @param HiiHandle HiiHandle for FormSet.
117 @param FormSetGuid The Formset GUID of the menu to search.
119 @return First form's id for this form set.
124 IN EFI_HII_HANDLE HiiHandle
,
125 IN EFI_GUID
*FormSetGuid
129 FORM_BROWSER_FORM
*Form
;
131 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
132 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
138 Search Menu with given FormSetGuid and FormId in all cached menu list.
140 @param HiiHandle HiiHandle for FormSet.
141 @param FormSetGuid The Formset GUID of the menu to search.
142 @param FormId The Form ID of menu to search.
144 @return A pointer to menu found or NULL if not found.
149 IN EFI_HII_HANDLE HiiHandle
,
150 IN EFI_GUID
*FormSetGuid
,
155 FORM_ENTRY_INFO
*MenuList
;
156 FORM_ENTRY_INFO
*RetMenu
;
157 EFI_FORM_ID FirstFormId
;
161 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
162 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
163 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
164 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
167 // If already find the menu, free the menus behind it.
169 if (RetMenu
!= NULL
) {
170 RemoveEntryList (&MenuList
->Link
);
176 // Find the same FromSet.
178 if (MenuList
->HiiHandle
== HiiHandle
) {
179 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
181 // FormSetGuid is not specified.
184 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
185 if (MenuList
->FormId
== FormId
) {
187 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
188 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
189 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
201 Find parent menu for current menu.
203 @param CurrentMenu Current Menu
205 @retval The parent menu for current menu.
209 IN FORM_ENTRY_INFO
*CurrentMenu
212 FORM_ENTRY_INFO
*ParentMenu
;
215 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
216 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
223 Free Menu list linked list.
225 @param MenuListHead One Menu list point in the menu list.
230 LIST_ENTRY
*MenuListHead
233 FORM_ENTRY_INFO
*MenuList
;
235 while (!IsListEmpty (MenuListHead
)) {
236 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
237 RemoveEntryList (&MenuList
->Link
);
244 Load all hii formset to the browser.
252 FORM_BROWSER_FORMSET
*LocalFormSet
;
253 EFI_HII_HANDLE
*HiiHandles
;
257 FORM_BROWSER_FORMSET
*OldFormset
;
259 OldFormset
= mSystemLevelFormSet
;
262 // Get all the Hii handles
264 HiiHandles
= HiiGetHiiHandles (NULL
);
265 ASSERT (HiiHandles
!= NULL
);
268 // Search for formset of each class type
270 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
272 // Check HiiHandles[Index] does exist in global maintain list.
274 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
279 // Initilize FormSet Setting
281 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
282 ASSERT (LocalFormSet
!= NULL
);
283 mSystemLevelFormSet
= LocalFormSet
;
285 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
286 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
287 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
288 DestroyFormSet (LocalFormSet
);
291 InitializeCurrentSetting (LocalFormSet
);
294 // Initilize Questions' Value
296 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
297 if (EFI_ERROR (Status
)) {
298 DestroyFormSet (LocalFormSet
);
304 // Free resources, and restore gOldFormSet and gClassOfVfr
306 FreePool (HiiHandles
);
308 mSystemLevelFormSet
= OldFormset
;
312 Pop up the error info.
314 @param BrowserStatus The input browser status.
315 @param OpCode The opcode use to get the erro info and timeout value.
316 @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF.
321 IN UINT32 BrowserStatus
,
322 IN EFI_IFR_OP_HEADER
*OpCode
, OPTIONAL
323 IN CHAR16
*ErrorString
326 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
330 if (OpCode
!= NULL
) {
331 Statement
= AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT
));
332 ASSERT (Statement
!= NULL
);
333 Statement
->OpCode
= OpCode
;
334 gDisplayFormData
.HighLightedStatement
= Statement
;
338 // Used to compatible with old display engine.
339 // New display engine not use this field.
341 gDisplayFormData
.ErrorString
= ErrorString
;
342 gDisplayFormData
.BrowserStatus
= BrowserStatus
;
344 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
346 gDisplayFormData
.BrowserStatus
= BROWSER_SUCCESS
;
347 gDisplayFormData
.ErrorString
= NULL
;
349 if (OpCode
!= NULL
) {
350 FreePool (Statement
);
355 This is the routine which an external caller uses to direct the browser
356 where to obtain it's information.
359 @param This The Form Browser protocol instanse.
360 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
361 display a list of the formsets for the handles specified.
362 @param HandleCount The number of Handles specified in Handle.
363 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
364 field in the EFI_IFR_FORM_SET op-code for the specified
365 forms-based package. If FormSetGuid is NULL, then this
366 function will display the first found forms package.
367 @param FormId This field specifies which EFI_IFR_FORM to render as the first
368 displayable page. If this field has a value of 0x0000, then
369 the forms browser will render the specified forms in their encoded order.
370 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
372 @param ActionRequest Points to the action recommended by the form.
374 @retval EFI_SUCCESS The function completed successfully.
375 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
376 @retval EFI_NOT_FOUND No valid forms could be found to display.
382 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
383 IN EFI_HII_HANDLE
*Handles
,
384 IN UINTN HandleCount
,
385 IN EFI_GUID
*FormSetGuid
, OPTIONAL
386 IN UINT16 FormId
, OPTIONAL
387 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
388 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
392 UI_MENU_SELECTION
*Selection
;
394 FORM_BROWSER_FORMSET
*FormSet
;
395 FORM_ENTRY_INFO
*MenuList
;
398 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
400 if (mFormDisplay
== NULL
) {
401 return EFI_UNSUPPORTED
;
405 // Save globals used by SendForm()
407 SaveBrowserContext ();
409 gResetRequired
= FALSE
;
410 gExitRequired
= FALSE
;
411 Status
= EFI_SUCCESS
;
413 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
415 for (Index
= 0; Index
< HandleCount
; Index
++) {
416 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
417 ASSERT (Selection
!= NULL
);
419 Selection
->Handle
= Handles
[Index
];
420 if (FormSetGuid
!= NULL
) {
421 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
422 Selection
->FormId
= FormId
;
424 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
428 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
429 ASSERT (FormSet
!= NULL
);
432 // Initialize internal data structures of FormSet
434 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
435 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
436 DestroyFormSet (FormSet
);
439 Selection
->FormSet
= FormSet
;
440 mSystemLevelFormSet
= FormSet
;
443 // Display this formset
445 gCurrentSelection
= Selection
;
447 Status
= SetupBrowser (Selection
);
449 gCurrentSelection
= NULL
;
450 mSystemLevelFormSet
= NULL
;
453 // If no data is changed, don't need to save current FormSet into the maintain list.
455 if (!IsNvUpdateRequiredForFormSet (FormSet
)) {
456 CleanBrowserStorage(FormSet
);
457 RemoveEntryList (&FormSet
->Link
);
458 DestroyFormSet (FormSet
);
461 if (EFI_ERROR (Status
)) {
464 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
466 FreePool (Selection
);
469 if (ActionRequest
!= NULL
) {
470 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
471 if (gResetRequired
) {
472 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
476 mFormDisplay
->ExitDisplay();
479 // Clear the menu history data.
481 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
482 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
483 RemoveEntryList (&MenuList
->Link
);
488 // Restore globals used by SendForm()
490 RestoreBrowserContext ();
496 Get or set data to the storage.
498 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
499 @param ResultsData A string returned from an IFR browser or
500 equivalent. The results string will have no
501 routing information in them.
502 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
503 (if RetrieveData = TRUE) data from the uncommitted
504 browser state information or set (if RetrieveData
505 = FALSE) data in the uncommitted browser state
507 @param Storage The pointer to the storage.
509 @retval EFI_SUCCESS The results have been distributed or are awaiting
515 IN OUT UINTN
*ResultsDataSize
,
516 IN OUT EFI_STRING
*ResultsData
,
517 IN BOOLEAN RetrieveData
,
518 IN BROWSER_STORAGE
*Storage
529 // Generate <ConfigResp>
531 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
532 if (EFI_ERROR (Status
)) {
537 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
538 // Also need to consider add "\0" at first time.
540 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
541 BufferSize
= StrSize (StrPtr
);
545 // Copy the data if the input buffer is bigger enough.
547 if (*ResultsDataSize
>= BufferSize
) {
548 StrCpy (*ResultsData
, StrPtr
);
551 *ResultsDataSize
= BufferSize
;
552 FreePool (ConfigResp
);
555 // Prepare <ConfigResp>
557 TmpSize
= StrLen (*ResultsData
);
558 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
559 ConfigResp
= AllocateZeroPool (BufferSize
);
560 ASSERT (ConfigResp
!= NULL
);
562 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
563 StrCat (ConfigResp
, L
"&");
564 StrCat (ConfigResp
, *ResultsData
);
567 // Update Browser uncommited data
569 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
570 FreePool (ConfigResp
);
571 if (EFI_ERROR (Status
)) {
580 This routine called this service in the browser to retrieve or set certain uncommitted
581 state information that resides in the open formsets.
583 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
585 @param ResultsDataSize A pointer to the size of the buffer associated
587 @param ResultsData A string returned from an IFR browser or
588 equivalent. The results string will have no
589 routing information in them.
590 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
591 (if RetrieveData = TRUE) data from the uncommitted
592 browser state information or set (if RetrieveData
593 = FALSE) data in the uncommitted browser state
595 @param VariableGuid An optional field to indicate the target variable
597 @param VariableName An optional field to indicate the target
598 human-readable variable name.
600 @retval EFI_SUCCESS The results have been distributed or are awaiting
602 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
603 contain the results data.
609 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
610 IN OUT UINTN
*ResultsDataSize
,
611 IN OUT EFI_STRING ResultsData
,
612 IN BOOLEAN RetrieveData
,
613 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
614 IN CONST CHAR16
*VariableName OPTIONAL
619 BROWSER_STORAGE
*Storage
;
620 FORMSET_STORAGE
*FormsetStorage
;
624 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
628 TotalSize
= *ResultsDataSize
;
631 Status
= EFI_SUCCESS
;
633 if (VariableGuid
!= NULL
) {
635 // Try to find target storage in the current formset.
637 Link
= GetFirstNode (&gBrowserStorageList
);
638 while (!IsNull (&gBrowserStorageList
, Link
)) {
639 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
640 Link
= GetNextNode (&gBrowserStorageList
, Link
);
642 // Check the current storage.
644 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
648 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
649 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
651 // Buffer storage require both GUID and Name
653 if (VariableName
== NULL
) {
654 return EFI_NOT_FOUND
;
657 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
662 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
663 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
664 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
665 return EFI_NOT_FOUND
;
668 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
673 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
674 if (EFI_ERROR (Status
)) {
678 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
679 ConfigRequestAdjust (Storage
, ResultsData
, TRUE
);
683 // Different formsets may have same varstore, so here just set the flag
684 // not exit the circle.
691 return EFI_NOT_FOUND
;
695 // GUID/Name is not specified, take the first storage in FormSet
697 if (mSystemLevelFormSet
== NULL
) {
698 return EFI_NOT_READY
;
702 // Generate <ConfigResp>
704 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
705 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
706 return EFI_UNSUPPORTED
;
709 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
711 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
712 if (EFI_ERROR (Status
)) {
718 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
719 *ResultsDataSize
= TotalSize
;
728 Callback function for SimpleTextInEx protocol install events
730 @param Event the event that is signaled.
731 @param Context not used here.
736 FormDisplayCallback (
743 if (mFormDisplay
!= NULL
) {
747 Status
= gBS
->LocateProtocol (
748 &gEdkiiFormDisplayEngineProtocolGuid
,
750 (VOID
**) &mFormDisplay
755 Initialize Setup Browser driver.
757 @param ImageHandle The image handle.
758 @param SystemTable The system table.
760 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
761 @return Other value if failed to initialize the Setup Browser module.
767 IN EFI_HANDLE ImageHandle
,
768 IN EFI_SYSTEM_TABLE
*SystemTable
775 // Locate required Hii relative protocols
777 Status
= gBS
->LocateProtocol (
778 &gEfiHiiDatabaseProtocolGuid
,
780 (VOID
**) &mHiiDatabase
782 ASSERT_EFI_ERROR (Status
);
784 Status
= gBS
->LocateProtocol (
785 &gEfiHiiConfigRoutingProtocolGuid
,
787 (VOID
**) &mHiiConfigRouting
789 ASSERT_EFI_ERROR (Status
);
791 Status
= gBS
->LocateProtocol (
792 &gEfiDevicePathFromTextProtocolGuid
,
794 (VOID
**) &mPathFromText
798 // Install FormBrowser2 protocol
800 mPrivateData
.Handle
= NULL
;
801 Status
= gBS
->InstallProtocolInterface (
802 &mPrivateData
.Handle
,
803 &gEfiFormBrowser2ProtocolGuid
,
804 EFI_NATIVE_INTERFACE
,
805 &mPrivateData
.FormBrowser2
807 ASSERT_EFI_ERROR (Status
);
810 // Install FormBrowserEx2 protocol
812 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
813 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
814 mPrivateData
.Handle
= NULL
;
815 Status
= gBS
->InstallProtocolInterface (
816 &mPrivateData
.Handle
,
817 &gEdkiiFormBrowserEx2ProtocolGuid
,
818 EFI_NATIVE_INTERFACE
,
819 &mPrivateData
.FormBrowserEx2
821 ASSERT_EFI_ERROR (Status
);
823 Status
= gBS
->InstallProtocolInterface (
824 &mPrivateData
.Handle
,
825 &gEfiFormBrowserExProtocolGuid
,
826 EFI_NATIVE_INTERFACE
,
827 &mPrivateData
.FormBrowserEx
829 ASSERT_EFI_ERROR (Status
);
831 InitializeDisplayFormData ();
833 Status
= gBS
->LocateProtocol (
834 &gEdkiiFormDisplayEngineProtocolGuid
,
836 (VOID
**) &mFormDisplay
839 if (EFI_ERROR (Status
)) {
840 EfiCreateProtocolNotifyEvent (
841 &gEdkiiFormDisplayEngineProtocolGuid
,
854 Create a new string in HII Package List.
856 @param String The String to be added
857 @param HiiHandle The package list in the HII database to insert the
860 @return The output string.
866 IN EFI_HII_HANDLE HiiHandle
869 EFI_STRING_ID StringId
;
871 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
872 ASSERT (StringId
!= 0);
879 Delete a string from HII Package List.
881 @param StringId Id of the string in HII database.
882 @param HiiHandle The HII package list handle.
884 @retval EFI_SUCCESS The string was deleted successfully.
889 IN EFI_STRING_ID StringId
,
890 IN EFI_HII_HANDLE HiiHandle
895 NullChar
= CHAR_NULL
;
896 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
902 Get the string based on the StringId and HII Package List Handle.
904 @param Token The String's ID.
905 @param HiiHandle The package list in the HII database to search for
906 the specified string.
908 @return The output string.
913 IN EFI_STRING_ID Token
,
914 IN EFI_HII_HANDLE HiiHandle
919 if (HiiHandle
== NULL
) {
923 String
= HiiGetString (HiiHandle
, Token
, NULL
);
924 if (String
== NULL
) {
925 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
926 ASSERT (String
!= NULL
);
928 return (CHAR16
*) String
;
933 Allocate new memory and then copy the Unicode string Source to Destination.
935 @param Dest Location to copy string
936 @param Src String to copy
941 IN OUT CHAR16
**Dest
,
948 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
949 ASSERT (*Dest
!= NULL
);
954 Allocate new memory and concatinate Source on the end of Destination.
956 @param Dest String to added to the end of.
957 @param Src String to concatinate.
962 IN OUT CHAR16
**Dest
,
970 NewStringCpy (Dest
, Src
);
974 TmpSize
= StrSize (*Dest
);
975 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
976 ASSERT (NewString
!= NULL
);
978 StrCpy (NewString
, *Dest
);
979 StrCat (NewString
, Src
);
986 Get Value for given Name from a NameValue Storage.
988 @param Storage The NameValue Storage.
989 @param Name The Name.
990 @param Value The retured Value.
991 @param GetValueFrom Where to get source value, from EditValue or Value.
993 @retval EFI_SUCCESS Value found for given Name.
994 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
999 IN BROWSER_STORAGE
*Storage
,
1001 IN OUT CHAR16
**Value
,
1002 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1006 NAME_VALUE_NODE
*Node
;
1008 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
1009 return EFI_INVALID_PARAMETER
;
1014 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1015 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1016 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1018 if (StrCmp (Name
, Node
->Name
) == 0) {
1019 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1020 NewStringCpy (Value
, Node
->EditValue
);
1022 NewStringCpy (Value
, Node
->Value
);
1027 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1030 return EFI_NOT_FOUND
;
1035 Set Value of given Name in a NameValue Storage.
1037 @param Storage The NameValue Storage.
1038 @param Name The Name.
1039 @param Value The Value to set.
1040 @param SetValueTo Whether update editValue or Value.
1041 @param ReturnNode The node use the input name.
1043 @retval EFI_SUCCESS Value found for given Name.
1044 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1049 IN BROWSER_STORAGE
*Storage
,
1052 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1053 OUT NAME_VALUE_NODE
**ReturnNode
1057 NAME_VALUE_NODE
*Node
;
1060 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1061 return EFI_INVALID_PARAMETER
;
1064 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1065 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1066 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1068 if (StrCmp (Name
, Node
->Name
) == 0) {
1069 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1070 Buffer
= Node
->EditValue
;
1072 Buffer
= Node
->Value
;
1074 if (Buffer
!= NULL
) {
1077 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1078 ASSERT (Buffer
!= NULL
);
1079 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1080 Node
->EditValue
= Buffer
;
1082 Node
->Value
= Buffer
;
1085 if (ReturnNode
!= NULL
) {
1092 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1095 return EFI_NOT_FOUND
;
1100 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1102 @param Storage The Storage to be conveted.
1103 @param ConfigResp The returned <ConfigResp>.
1104 @param ConfigRequest The ConfigRequest string.
1105 @param GetEditBuf Get the data from editbuffer or buffer.
1107 @retval EFI_SUCCESS Convert success.
1108 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1112 StorageToConfigResp (
1113 IN BROWSER_STORAGE
*Storage
,
1114 IN CHAR16
**ConfigResp
,
1115 IN CHAR16
*ConfigRequest
,
1116 IN BOOLEAN GetEditBuf
1120 EFI_STRING Progress
;
1122 NAME_VALUE_NODE
*Node
;
1125 Status
= EFI_SUCCESS
;
1127 switch (Storage
->Type
) {
1128 case EFI_HII_VARSTORE_BUFFER
:
1129 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1130 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1131 Status
= mHiiConfigRouting
->BlockToConfig (
1141 case EFI_HII_VARSTORE_NAME_VALUE
:
1143 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1145 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1146 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1147 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1149 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1150 NewStringCat (ConfigResp
, L
"&");
1151 NewStringCat (ConfigResp
, Node
->Name
);
1152 NewStringCat (ConfigResp
, L
"=");
1154 NewStringCat (ConfigResp
, Node
->EditValue
);
1156 NewStringCat (ConfigResp
, Node
->Value
);
1159 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1163 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1165 Status
= EFI_INVALID_PARAMETER
;
1174 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1176 @param Storage The Storage to receive the settings.
1177 @param ConfigResp The <ConfigResp> to be converted.
1179 @retval EFI_SUCCESS Convert success.
1180 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1184 ConfigRespToStorage (
1185 IN BROWSER_STORAGE
*Storage
,
1186 IN CHAR16
*ConfigResp
1190 EFI_STRING Progress
;
1196 Status
= EFI_SUCCESS
;
1198 switch (Storage
->Type
) {
1199 case EFI_HII_VARSTORE_BUFFER
:
1200 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1201 BufferSize
= Storage
->Size
;
1202 Status
= mHiiConfigRouting
->ConfigToBlock (
1205 Storage
->EditBuffer
,
1211 case EFI_HII_VARSTORE_NAME_VALUE
:
1212 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1213 if (StrPtr
== NULL
) {
1216 StrPtr
= StrStr (ConfigResp
, L
"&");
1217 while (StrPtr
!= NULL
) {
1221 StrPtr
= StrPtr
+ 1;
1223 StrPtr
= StrStr (StrPtr
, L
"=");
1224 if (StrPtr
== NULL
) {
1232 StrPtr
= StrPtr
+ 1;
1234 StrPtr
= StrStr (StrPtr
, L
"&");
1235 if (StrPtr
!= NULL
) {
1238 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1242 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1244 Status
= EFI_INVALID_PARAMETER
;
1253 Get Question's current Value.
1255 @param FormSet FormSet data structure.
1256 @param Form Form data structure.
1257 @param Question Question to be initialized.
1258 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1260 @retval EFI_SUCCESS The function completed successfully.
1265 IN FORM_BROWSER_FORMSET
*FormSet
,
1266 IN FORM_BROWSER_FORM
*Form
,
1267 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1268 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1277 BROWSER_STORAGE
*Storage
;
1278 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1279 CHAR16
*ConfigRequest
;
1287 BOOLEAN IsBufferStorage
;
1292 Status
= EFI_SUCCESS
;
1296 if (GetValueFrom
>= GetSetValueWithMax
) {
1297 return EFI_INVALID_PARAMETER
;
1301 // Question value is provided by an Expression, evaluate it
1303 if (Question
->ValueExpression
!= NULL
) {
1304 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1305 if (!EFI_ERROR (Status
)) {
1306 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1307 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1308 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1309 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1310 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1312 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1313 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1315 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1317 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1318 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1324 // Get question value by read expression.
1326 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1327 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1328 if (!EFI_ERROR (Status
) &&
1329 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1331 // Only update question value to the valid result.
1333 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1334 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1335 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1336 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1337 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1339 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1340 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1342 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1344 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1345 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1351 // Question value is provided by RTC
1353 Storage
= Question
->Storage
;
1354 QuestionValue
= &Question
->HiiValue
.Value
;
1355 if (Storage
== NULL
) {
1357 // It's a Question without storage, or RTC date/time
1359 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1361 // Date and time define the same Flags bit
1363 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1364 case QF_DATE_STORAGE_TIME
:
1365 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1368 case QF_DATE_STORAGE_WAKEUP
:
1369 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1372 case QF_DATE_STORAGE_NORMAL
:
1375 // For date/time without storage
1380 if (EFI_ERROR (Status
)) {
1384 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1385 QuestionValue
->date
.Year
= EfiTime
.Year
;
1386 QuestionValue
->date
.Month
= EfiTime
.Month
;
1387 QuestionValue
->date
.Day
= EfiTime
.Day
;
1389 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1390 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1391 QuestionValue
->time
.Second
= EfiTime
.Second
;
1399 // Question value is provided by EFI variable
1401 StorageWidth
= Question
->StorageWidth
;
1402 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1403 if (Question
->BufferValue
!= NULL
) {
1404 Dst
= Question
->BufferValue
;
1406 Dst
= (UINT8
*) QuestionValue
;
1409 Status
= gRT
->GetVariable (
1410 Question
->VariableName
,
1417 // Always return success, even this EFI variable doesn't exist
1423 // Question Value is provided by Buffer Storage or NameValue Storage
1425 if (Question
->BufferValue
!= NULL
) {
1427 // This Question is password or orderedlist
1429 Dst
= Question
->BufferValue
;
1432 // Other type of Questions
1434 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1437 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1438 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1439 IsBufferStorage
= TRUE
;
1441 IsBufferStorage
= FALSE
;
1443 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1444 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1445 if (IsBufferStorage
) {
1446 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1448 // Copy from storage Edit buffer
1450 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1453 // Copy from storage Edit buffer
1455 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1459 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1460 if (EFI_ERROR (Status
)) {
1464 ASSERT (Value
!= NULL
);
1465 LengthStr
= StrLen (Value
);
1466 Status
= EFI_SUCCESS
;
1469 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1470 // Add string tail char L'\0' into Length
1472 Length
= StorageWidth
+ sizeof (CHAR16
);
1473 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1474 Status
= EFI_BUFFER_TOO_SMALL
;
1476 StringPtr
= (CHAR16
*) Dst
;
1477 ZeroMem (TemStr
, sizeof (TemStr
));
1478 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1479 StrnCpy (TemStr
, Value
+ Index
, 4);
1480 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1483 // Add tailing L'\0' character
1485 StringPtr
[Index
/4] = L
'\0';
1488 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1489 Status
= EFI_BUFFER_TOO_SMALL
;
1491 ZeroMem (TemStr
, sizeof (TemStr
));
1492 for (Index
= 0; Index
< LengthStr
; Index
++) {
1493 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1494 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1495 if ((Index
& 1) == 0) {
1496 Dst
[Index
/2] = DigitUint8
;
1498 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1508 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1509 // <ConfigHdr> + "&" + <VariableName>
1511 if (IsBufferStorage
) {
1512 Length
= StrLen (Storage
->ConfigHdr
);
1513 Length
+= StrLen (Question
->BlockName
);
1515 Length
= StrLen (Storage
->ConfigHdr
);
1516 Length
+= StrLen (Question
->VariableName
) + 1;
1518 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1519 ASSERT (ConfigRequest
!= NULL
);
1521 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1522 if (IsBufferStorage
) {
1523 StrCat (ConfigRequest
, Question
->BlockName
);
1525 StrCat (ConfigRequest
, L
"&");
1526 StrCat (ConfigRequest
, Question
->VariableName
);
1530 // Request current settings from Configuration Driver
1532 Status
= mHiiConfigRouting
->ExtractConfig (
1538 FreePool (ConfigRequest
);
1539 if (EFI_ERROR (Status
)) {
1544 // Skip <ConfigRequest>
1546 if (IsBufferStorage
) {
1547 Value
= StrStr (Result
, L
"&VALUE");
1548 if (Value
== NULL
) {
1550 return EFI_NOT_FOUND
;
1557 Value
= Result
+ Length
;
1559 if (*Value
!= '=') {
1561 return EFI_NOT_FOUND
;
1564 // Skip '=', point to value
1569 // Suppress <AltResp> if any
1572 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1577 LengthStr
= StrLen (Value
);
1578 Status
= EFI_SUCCESS
;
1579 if (!IsBufferStorage
&& IsString
) {
1581 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1582 // Add string tail char L'\0' into Length
1584 Length
= StorageWidth
+ sizeof (CHAR16
);
1585 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1586 Status
= EFI_BUFFER_TOO_SMALL
;
1588 StringPtr
= (CHAR16
*) Dst
;
1589 ZeroMem (TemStr
, sizeof (TemStr
));
1590 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1591 StrnCpy (TemStr
, Value
+ Index
, 4);
1592 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1595 // Add tailing L'\0' character
1597 StringPtr
[Index
/4] = L
'\0';
1600 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1601 Status
= EFI_BUFFER_TOO_SMALL
;
1603 ZeroMem (TemStr
, sizeof (TemStr
));
1604 for (Index
= 0; Index
< LengthStr
; Index
++) {
1605 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1606 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1607 if ((Index
& 1) == 0) {
1608 Dst
[Index
/2] = DigitUint8
;
1610 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1616 if (EFI_ERROR (Status
)) {
1622 // Synchronize Edit Buffer
1624 if (IsBufferStorage
) {
1625 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1627 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1630 if (Result
!= NULL
) {
1640 Save Question Value to edit copy(cached) or Storage(uncached).
1642 @param FormSet FormSet data structure.
1643 @param Form Form data structure.
1644 @param Question Pointer to the Question.
1645 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1647 @retval EFI_SUCCESS The function completed successfully.
1652 IN FORM_BROWSER_FORMSET
*FormSet
,
1653 IN FORM_BROWSER_FORM
*Form
,
1654 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1655 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1665 BROWSER_STORAGE
*Storage
;
1666 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1671 BOOLEAN IsBufferStorage
;
1677 NAME_VALUE_NODE
*Node
;
1679 Status
= EFI_SUCCESS
;
1682 if (SetValueTo
>= GetSetValueWithMax
) {
1683 return EFI_INVALID_PARAMETER
;
1687 // If Question value is provided by an Expression, then it is read only
1689 if (Question
->ValueExpression
!= NULL
) {
1694 // Before set question value, evaluate its write expression.
1696 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1697 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1698 if (EFI_ERROR (Status
)) {
1704 // Question value is provided by RTC
1706 Storage
= Question
->Storage
;
1707 QuestionValue
= &Question
->HiiValue
.Value
;
1708 if (Storage
== NULL
) {
1710 // It's a Question without storage, or RTC date/time
1712 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1714 // Date and time define the same Flags bit
1716 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1717 case QF_DATE_STORAGE_TIME
:
1718 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1721 case QF_DATE_STORAGE_WAKEUP
:
1722 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1725 case QF_DATE_STORAGE_NORMAL
:
1728 // For date/time without storage
1733 if (EFI_ERROR (Status
)) {
1737 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1738 EfiTime
.Year
= QuestionValue
->date
.Year
;
1739 EfiTime
.Month
= QuestionValue
->date
.Month
;
1740 EfiTime
.Day
= QuestionValue
->date
.Day
;
1742 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1743 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1744 EfiTime
.Second
= QuestionValue
->time
.Second
;
1747 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1748 Status
= gRT
->SetTime (&EfiTime
);
1750 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1758 // Question value is provided by EFI variable
1760 StorageWidth
= Question
->StorageWidth
;
1761 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1762 if (Question
->BufferValue
!= NULL
) {
1763 Src
= Question
->BufferValue
;
1765 Src
= (UINT8
*) QuestionValue
;
1768 Status
= gRT
->SetVariable (
1769 Question
->VariableName
,
1771 Storage
->Attributes
,
1779 // Question Value is provided by Buffer Storage or NameValue Storage
1781 if (Question
->BufferValue
!= NULL
) {
1782 Src
= Question
->BufferValue
;
1784 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1787 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1788 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1789 IsBufferStorage
= TRUE
;
1791 IsBufferStorage
= FALSE
;
1793 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1795 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1796 if (IsBufferStorage
) {
1797 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1799 // Copy to storage edit buffer
1801 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1802 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1804 // Copy to storage edit buffer
1806 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1811 // Allocate enough string buffer.
1814 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1815 Value
= AllocateZeroPool (BufferLen
);
1816 ASSERT (Value
!= NULL
);
1818 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1820 TemName
= (CHAR16
*) Src
;
1822 for (; *TemName
!= L
'\0'; TemName
++) {
1823 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1826 BufferLen
= StorageWidth
* 2 + 1;
1827 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1828 ASSERT (Value
!= NULL
);
1830 // Convert Buffer to Hex String
1832 TemBuffer
= Src
+ StorageWidth
- 1;
1834 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1835 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1839 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1841 if (EFI_ERROR (Status
)) {
1845 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1847 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1848 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1850 if (IsBufferStorage
) {
1851 Length
= StrLen (Question
->BlockName
) + 7;
1853 Length
= StrLen (Question
->VariableName
) + 2;
1855 if (!IsBufferStorage
&& IsString
) {
1856 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1858 Length
+= (StorageWidth
* 2);
1860 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1861 ASSERT (ConfigResp
!= NULL
);
1863 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1864 if (IsBufferStorage
) {
1865 StrCat (ConfigResp
, Question
->BlockName
);
1866 StrCat (ConfigResp
, L
"&VALUE=");
1868 StrCat (ConfigResp
, L
"&");
1869 StrCat (ConfigResp
, Question
->VariableName
);
1870 StrCat (ConfigResp
, L
"=");
1873 Value
= ConfigResp
+ StrLen (ConfigResp
);
1875 if (!IsBufferStorage
&& IsString
) {
1877 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1879 TemName
= (CHAR16
*) Src
;
1881 for (; *TemName
!= L
'\0'; TemName
++) {
1882 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1886 // Convert Buffer to Hex String
1888 TemBuffer
= Src
+ StorageWidth
- 1;
1890 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1891 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1896 // Convert to lower char.
1898 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1899 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1900 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1905 // Submit Question Value to Configuration Driver
1907 Status
= mHiiConfigRouting
->RouteConfig (
1912 if (EFI_ERROR (Status
)) {
1913 FreePool (ConfigResp
);
1916 FreePool (ConfigResp
);
1919 // Sync storage, from editbuffer to buffer.
1921 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1929 Perform nosubmitif check for a Form.
1931 @param FormSet FormSet data structure.
1932 @param Form Form data structure.
1933 @param Question The Question to be validated.
1934 @param Type Validation type: NoSubmit
1936 @retval EFI_SUCCESS Form validation pass.
1937 @retval other Form validation failed.
1942 IN FORM_BROWSER_FORMSET
*FormSet
,
1943 IN FORM_BROWSER_FORM
*Form
,
1944 IN FORM_BROWSER_STATEMENT
*Question
,
1950 LIST_ENTRY
*ListHead
;
1951 FORM_EXPRESSION
*Expression
;
1952 UINT32 BrowserStatus
;
1955 BrowserStatus
= BROWSER_SUCCESS
;
1959 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1960 ListHead
= &Question
->InconsistentListHead
;
1963 case EFI_HII_EXPRESSION_WARNING_IF
:
1964 ListHead
= &Question
->WarningListHead
;
1967 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
1968 ListHead
= &Question
->NoSubmitListHead
;
1973 return EFI_UNSUPPORTED
;
1976 Link
= GetFirstNode (ListHead
);
1977 while (!IsNull (ListHead
, Link
)) {
1978 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1981 // Evaluate the expression
1983 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1984 if (EFI_ERROR (Status
)) {
1988 if (IsTrue (&Expression
->Result
)) {
1990 case EFI_HII_EXPRESSION_INCONSISTENT_IF
:
1991 BrowserStatus
= BROWSER_INCONSISTENT_IF
;
1994 case EFI_HII_EXPRESSION_WARNING_IF
:
1995 BrowserStatus
= BROWSER_WARNING_IF
;
1998 case EFI_HII_EXPRESSION_NO_SUBMIT_IF
:
1999 BrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2001 // This code only used to compatible with old display engine,
2002 // New display engine will not use this field.
2004 if (Expression
->Error
!= 0) {
2005 ErrorStr
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2014 PopupErrorMessage(BrowserStatus
, Expression
->OpCode
, ErrorStr
);
2016 if (ErrorStr
!= NULL
) {
2017 FreePool (ErrorStr
);
2020 if (Type
== EFI_HII_EXPRESSION_WARNING_IF
) {
2023 return EFI_NOT_READY
;
2027 Link
= GetNextNode (ListHead
, Link
);
2034 Perform question check.
2036 If one question has more than one check, process form high priority to low.
2037 Only one error info will be popup.
2039 @param FormSet FormSet data structure.
2040 @param Form Form data structure.
2041 @param Question The Question to be validated.
2043 @retval EFI_SUCCESS Form validation pass.
2044 @retval other Form validation failed.
2048 ValueChangedValidation (
2049 IN FORM_BROWSER_FORMSET
*FormSet
,
2050 IN FORM_BROWSER_FORM
*Form
,
2051 IN FORM_BROWSER_STATEMENT
*Question
2056 Status
= EFI_SUCCESS
;
2059 // Do the inconsistentif check.
2061 if (!IsListEmpty (&Question
->InconsistentListHead
)) {
2062 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_INCONSISTENT_IF
);
2063 if (EFI_ERROR (Status
)) {
2069 // Do the warningif check.
2071 if (!IsListEmpty (&Question
->WarningListHead
)) {
2072 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_WARNING_IF
);
2079 Perform NoSubmit check for each Form in FormSet.
2081 @param FormSet FormSet data structure.
2082 @param CurrentForm Current input form data structure.
2084 @retval EFI_SUCCESS Form validation pass.
2085 @retval other Form validation failed.
2090 IN FORM_BROWSER_FORMSET
*FormSet
,
2091 IN FORM_BROWSER_FORM
*CurrentForm
2096 FORM_BROWSER_STATEMENT
*Question
;
2097 FORM_BROWSER_FORM
*Form
;
2098 LIST_ENTRY
*LinkForm
;
2100 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2101 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2102 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2103 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2105 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2109 Link
= GetFirstNode (&Form
->StatementListHead
);
2110 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2111 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2113 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2114 if (EFI_ERROR (Status
)) {
2118 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2126 Fill storage's edit copy with settings requested from Configuration Driver.
2128 @param FormSet FormSet data structure.
2129 @param Storage The storage which need to sync.
2130 @param ConfigRequest The config request string which used to sync storage.
2131 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2132 editbuffer to buffer
2133 if TRUE, copy the editbuffer to the buffer.
2134 if FALSE, copy the buffer to the editbuffer.
2136 @retval EFI_SUCCESS The function completed successfully.
2140 SynchronizeStorage (
2141 IN FORM_BROWSER_FORMSET
*FormSet
,
2142 OUT BROWSER_STORAGE
*Storage
,
2143 IN CHAR16
*ConfigRequest
,
2144 IN BOOLEAN SyncOrRestore
2148 EFI_STRING Progress
;
2152 NAME_VALUE_NODE
*Node
;
2156 Status
= EFI_SUCCESS
;
2159 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2160 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2161 BufferSize
= Storage
->Size
;
2163 if (SyncOrRestore
) {
2164 Src
= Storage
->EditBuffer
;
2165 Dst
= Storage
->Buffer
;
2167 Src
= Storage
->Buffer
;
2168 Dst
= Storage
->EditBuffer
;
2171 if (ConfigRequest
!= NULL
) {
2172 Status
= mHiiConfigRouting
->BlockToConfig(
2180 if (EFI_ERROR (Status
)) {
2184 Status
= mHiiConfigRouting
->ConfigToBlock (
2191 if (Result
!= NULL
) {
2195 CopyMem (Dst
, Src
, BufferSize
);
2197 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2198 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2199 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2200 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2202 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2203 (ConfigRequest
== NULL
)) {
2204 if (SyncOrRestore
) {
2205 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2207 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2211 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2219 When discard the question value, call the callback function with Changed type
2220 to inform the hii driver.
2222 @param FormSet FormSet data structure.
2223 @param Form Form data structure.
2227 SendDiscardInfoToDriver (
2228 IN FORM_BROWSER_FORMSET
*FormSet
,
2229 IN FORM_BROWSER_FORM
*Form
2233 FORM_BROWSER_STATEMENT
*Question
;
2234 EFI_IFR_TYPE_VALUE
*TypeValue
;
2235 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2237 if (FormSet
->ConfigAccess
== NULL
) {
2241 Link
= GetFirstNode (&Form
->StatementListHead
);
2242 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2243 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2244 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2246 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2250 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != EFI_IFR_FLAG_CALLBACK
) {
2254 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2258 if (!Question
->ValueChanged
) {
2262 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2263 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2265 TypeValue
= &Question
->HiiValue
.Value
;
2268 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2269 FormSet
->ConfigAccess
->Callback (
2270 FormSet
->ConfigAccess
,
2271 EFI_BROWSER_ACTION_CHANGED
,
2272 Question
->QuestionId
,
2273 Question
->HiiValue
.Type
,
2281 Validate the FormSet. If the formset is not validate, remove it from the list.
2283 @param FormSet The input FormSet which need to validate.
2285 @retval TRUE The handle is validate.
2286 @retval FALSE The handle is invalidate.
2291 FORM_BROWSER_FORMSET
*FormSet
2294 EFI_HII_HANDLE
*HiiHandles
;
2298 ASSERT (FormSet
!= NULL
);
2301 // Get all the Hii handles
2303 HiiHandles
= HiiGetHiiHandles (NULL
);
2304 ASSERT (HiiHandles
!= NULL
);
2307 // Search for formset of each class type
2309 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2310 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2317 CleanBrowserStorage(FormSet
);
2318 RemoveEntryList (&FormSet
->Link
);
2319 DestroyFormSet (FormSet
);
2322 FreePool (HiiHandles
);
2327 Check whether need to enable the reset flag in form level.
2328 Also clean all ValueChanged flag in question.
2330 @param SetFlag Whether need to set the Reset Flag.
2331 @param Form Form data structure.
2337 IN FORM_BROWSER_FORM
*Form
2341 FORM_BROWSER_STATEMENT
*Question
;
2345 Link
= GetFirstNode (&Form
->StatementListHead
);
2346 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2347 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2349 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2350 gResetRequired
= TRUE
;
2353 if (Question
->ValueChanged
) {
2354 Question
->ValueChanged
= FALSE
;
2357 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2362 Check whether need to enable the reset flag.
2363 Also clean ValueChanged flag for all statements.
2365 Form level or formset level, only one.
2367 @param SetFlag Whether need to set the Reset Flag.
2368 @param FormSet FormSet data structure.
2369 @param Form Form data structure.
2373 ValueChangeResetFlagUpdate (
2375 IN FORM_BROWSER_FORMSET
*FormSet
,
2376 IN FORM_BROWSER_FORM
*Form
2379 FORM_BROWSER_FORM
*CurrentForm
;
2383 // Form != NULL means only check form level.
2386 UpdateFlagForForm(SetFlag
, Form
);
2390 Link
= GetFirstNode (&FormSet
->FormListHead
);
2391 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2392 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2393 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2395 UpdateFlagForForm(SetFlag
, CurrentForm
);
2400 Discard data based on the input setting scope (Form, FormSet or System).
2402 @param FormSet FormSet data structure.
2403 @param Form Form data structure.
2404 @param SettingScope Setting Scope for Discard action.
2406 @retval EFI_SUCCESS The function completed successfully.
2407 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2412 IN FORM_BROWSER_FORMSET
*FormSet
,
2413 IN FORM_BROWSER_FORM
*Form
,
2414 IN BROWSER_SETTING_SCOPE SettingScope
2418 FORMSET_STORAGE
*Storage
;
2419 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2420 FORM_BROWSER_FORMSET
*LocalFormSet
;
2421 FORM_BROWSER_FORMSET
*OldFormSet
;
2424 // Check the supported setting level.
2426 if (SettingScope
>= MaxLevel
) {
2427 return EFI_UNSUPPORTED
;
2430 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2432 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2433 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2434 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2435 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2437 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2442 // Skip if there is no RequestElement
2444 if (ConfigInfo
->ElementCount
== 0) {
2449 // Prepare <ConfigResp>
2451 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2454 // Call callback with Changed type to inform the driver.
2456 SendDiscardInfoToDriver (FormSet
, Form
);
2459 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2460 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2463 // Discard Buffer storage or Name/Value storage
2465 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2466 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2467 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2468 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2470 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2475 // Skip if there is no RequestElement
2477 if (Storage
->ElementCount
== 0) {
2481 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2484 Link
= GetFirstNode (&FormSet
->FormListHead
);
2485 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2486 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2487 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2490 // Call callback with Changed type to inform the driver.
2492 SendDiscardInfoToDriver (FormSet
, Form
);
2495 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2496 } else if (SettingScope
== SystemLevel
) {
2498 // System Level Discard.
2500 OldFormSet
= mSystemLevelFormSet
;
2503 // Discard changed value for each FormSet in the maintain list.
2505 Link
= GetFirstNode (&gBrowserFormSetList
);
2506 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2507 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2508 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2509 if (!ValidateFormSet(LocalFormSet
)) {
2513 mSystemLevelFormSet
= LocalFormSet
;
2515 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2516 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2518 // Remove maintain backup list after discard except for the current using FormSet.
2520 CleanBrowserStorage(LocalFormSet
);
2521 RemoveEntryList (&LocalFormSet
->Link
);
2522 DestroyFormSet (LocalFormSet
);
2526 mSystemLevelFormSet
= OldFormSet
;
2533 Submit data based on the input Setting level (Form, FormSet or System).
2535 @param FormSet FormSet data structure.
2536 @param Form Form data structure.
2537 @param SettingScope Setting Scope for Submit action.
2539 @retval EFI_SUCCESS The function completed successfully.
2540 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2545 IN FORM_BROWSER_FORMSET
*FormSet
,
2546 IN FORM_BROWSER_FORM
*Form
,
2547 IN BROWSER_SETTING_SCOPE SettingScope
2552 EFI_STRING ConfigResp
;
2553 EFI_STRING Progress
;
2554 BROWSER_STORAGE
*Storage
;
2555 FORMSET_STORAGE
*FormSetStorage
;
2556 FORM_BROWSER_FORMSET
*LocalFormSet
;
2557 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2560 // Check the supported setting level.
2562 if (SettingScope
>= MaxLevel
) {
2563 return EFI_UNSUPPORTED
;
2567 // Validate the Form by NoSubmit check
2569 Status
= EFI_SUCCESS
;
2570 if (SettingScope
== FormLevel
) {
2571 Status
= NoSubmitCheck (FormSet
, Form
);
2572 } else if (SettingScope
== FormSetLevel
) {
2573 Status
= NoSubmitCheck (FormSet
, NULL
);
2575 if (EFI_ERROR (Status
)) {
2579 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2581 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2582 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2583 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2584 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2586 Storage
= ConfigInfo
->Storage
;
2587 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2592 // Skip if there is no RequestElement
2594 if (ConfigInfo
->ElementCount
== 0) {
2599 // 1. Prepare <ConfigResp>
2601 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2602 if (EFI_ERROR (Status
)) {
2607 // 2. Set value to hii config routine protocol.
2609 Status
= mHiiConfigRouting
->RouteConfig (
2614 if (EFI_ERROR (Status
)) {
2615 FreePool (ConfigResp
);
2619 FreePool (ConfigResp
);
2621 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2623 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2627 // 4. Update the NV flag.
2629 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2630 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2632 // Submit Buffer storage or Name/Value storage
2634 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2635 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2636 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2637 Storage
= FormSetStorage
->BrowserStorage
;
2638 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2640 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2645 // Skip if there is no RequestElement
2647 if (FormSetStorage
->ElementCount
== 0) {
2652 // 1. Prepare <ConfigResp>
2654 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2655 if (EFI_ERROR (Status
)) {
2660 // 2. Send <ConfigResp> to Routine config Protocol.
2662 Status
= mHiiConfigRouting
->RouteConfig (
2667 if (EFI_ERROR (Status
)) {
2668 FreePool (ConfigResp
);
2672 FreePool (ConfigResp
);
2674 // 3. Config success, update storage shadow Buffer
2676 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2680 // 4. Update the NV flag.
2682 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2683 } else if (SettingScope
== SystemLevel
) {
2685 // System Level Save.
2689 // Save changed value for each FormSet in the maintain list.
2691 Link
= GetFirstNode (&gBrowserFormSetList
);
2692 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2693 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2694 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2695 if (!ValidateFormSet(LocalFormSet
)) {
2698 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2699 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2701 // Remove maintain backup list after save except for the current using FormSet.
2703 CleanBrowserStorage(LocalFormSet
);
2704 RemoveEntryList (&LocalFormSet
->Link
);
2705 DestroyFormSet (LocalFormSet
);
2714 Get Question default value from AltCfg string.
2716 @param FormSet The form set.
2717 @param Question The question.
2718 @param DefaultId The default Id.
2720 @retval EFI_SUCCESS Question is reset to default value.
2724 GetDefaultValueFromAltCfg (
2725 IN FORM_BROWSER_FORMSET
*FormSet
,
2726 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2730 BOOLEAN IsBufferStorage
;
2733 BROWSER_STORAGE
*Storage
;
2734 CHAR16
*ConfigRequest
;
2747 Status
= EFI_NOT_FOUND
;
2750 ConfigRequest
= NULL
;
2754 Storage
= Question
->Storage
;
2756 if ((Storage
== NULL
) || (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
2761 // Question Value is provided by Buffer Storage or NameValue Storage
2763 if (Question
->BufferValue
!= NULL
) {
2765 // This Question is password or orderedlist
2767 Dst
= Question
->BufferValue
;
2770 // Other type of Questions
2772 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2775 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2776 IsBufferStorage
= TRUE
;
2778 IsBufferStorage
= FALSE
;
2780 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2783 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2784 // <ConfigHdr> + "&" + <VariableName>
2786 if (IsBufferStorage
) {
2787 Length
= StrLen (Storage
->ConfigHdr
);
2788 Length
+= StrLen (Question
->BlockName
);
2790 Length
= StrLen (Storage
->ConfigHdr
);
2791 Length
+= StrLen (Question
->VariableName
) + 1;
2793 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2794 ASSERT (ConfigRequest
!= NULL
);
2796 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2797 if (IsBufferStorage
) {
2798 StrCat (ConfigRequest
, Question
->BlockName
);
2800 StrCat (ConfigRequest
, L
"&");
2801 StrCat (ConfigRequest
, Question
->VariableName
);
2804 Status
= mHiiConfigRouting
->ExtractConfig (
2810 if (EFI_ERROR (Status
)) {
2815 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2816 // Get the default configuration string according to the default ID.
2818 Status
= mHiiConfigRouting
->GetAltConfig (
2824 &DefaultId
, // it can be NULL to get the current setting.
2829 // The required setting can't be found. So, it is not required to be validated and set.
2831 if (EFI_ERROR (Status
)) {
2835 if (ConfigResp
== NULL
) {
2836 Status
= EFI_NOT_FOUND
;
2841 // Skip <ConfigRequest>
2843 if (IsBufferStorage
) {
2844 Value
= StrStr (ConfigResp
, L
"&VALUE");
2845 ASSERT (Value
!= NULL
);
2851 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2852 ASSERT (Value
!= NULL
);
2854 Value
= Value
+ StrLen (Question
->VariableName
);
2856 if (*Value
!= '=') {
2857 Status
= EFI_NOT_FOUND
;
2861 // Skip '=', point to value
2866 // Suppress <AltResp> if any
2869 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2874 LengthStr
= StrLen (Value
);
2875 if (!IsBufferStorage
&& IsString
) {
2876 StringPtr
= (CHAR16
*) Dst
;
2877 ZeroMem (TemStr
, sizeof (TemStr
));
2878 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2879 StrnCpy (TemStr
, Value
+ Index
, 4);
2880 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2883 // Add tailing L'\0' character
2885 StringPtr
[Index
/4] = L
'\0';
2887 ZeroMem (TemStr
, sizeof (TemStr
));
2888 for (Index
= 0; Index
< LengthStr
; Index
++) {
2889 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2890 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2891 if ((Index
& 1) == 0) {
2892 Dst
[Index
/2] = DigitUint8
;
2894 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2900 if (ConfigRequest
!= NULL
){
2901 FreePool (ConfigRequest
);
2904 if (ConfigResp
!= NULL
) {
2905 FreePool (ConfigResp
);
2908 if (Result
!= NULL
) {
2916 Get default Id value used for browser.
2918 @param DefaultId The default id value used by hii.
2920 @retval Browser used default value.
2924 GetDefaultIdForCallBack (
2928 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2929 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2930 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2931 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2932 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2933 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2934 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2935 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2936 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2937 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2938 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2939 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2948 Return data element in an Array by its Index.
2950 @param Array The data array.
2951 @param Type Type of the data in this array.
2952 @param Index Zero based index for data in this array.
2954 @retval Value The data to be returned
2966 ASSERT (Array
!= NULL
);
2970 case EFI_IFR_TYPE_NUM_SIZE_8
:
2971 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
2974 case EFI_IFR_TYPE_NUM_SIZE_16
:
2975 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
2978 case EFI_IFR_TYPE_NUM_SIZE_32
:
2979 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
2982 case EFI_IFR_TYPE_NUM_SIZE_64
:
2983 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
2995 Set value of a data element in an Array by its Index.
2997 @param Array The data array.
2998 @param Type Type of the data in this array.
2999 @param Index Zero based index for data in this array.
3000 @param Value The value to be set.
3012 ASSERT (Array
!= NULL
);
3015 case EFI_IFR_TYPE_NUM_SIZE_8
:
3016 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3019 case EFI_IFR_TYPE_NUM_SIZE_16
:
3020 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3023 case EFI_IFR_TYPE_NUM_SIZE_32
:
3024 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3027 case EFI_IFR_TYPE_NUM_SIZE_64
:
3028 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3037 Search an Option of a Question by its value.
3039 @param Question The Question
3040 @param OptionValue Value for Option to be searched.
3042 @retval Pointer Pointer to the found Option.
3043 @retval NULL Option not found.
3048 IN FORM_BROWSER_STATEMENT
*Question
,
3049 IN EFI_HII_VALUE
*OptionValue
3053 QUESTION_OPTION
*Option
;
3056 Link
= GetFirstNode (&Question
->OptionListHead
);
3057 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3058 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3060 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3062 // Check the suppressif condition, only a valid option can be return.
3064 if ((Option
->SuppressExpression
== NULL
) ||
3065 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3070 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3078 Reset Question to its default value.
3080 @param FormSet The form set.
3081 @param Form The form.
3082 @param Question The question.
3083 @param DefaultId The Class of the default.
3085 @retval EFI_SUCCESS Question is reset to default value.
3089 GetQuestionDefault (
3090 IN FORM_BROWSER_FORMSET
*FormSet
,
3091 IN FORM_BROWSER_FORM
*Form
,
3092 IN FORM_BROWSER_STATEMENT
*Question
,
3098 QUESTION_DEFAULT
*Default
;
3099 QUESTION_OPTION
*Option
;
3100 EFI_HII_VALUE
*HiiValue
;
3102 EFI_STRING StrValue
;
3103 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3104 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3108 Status
= EFI_NOT_FOUND
;
3112 // Statement don't have storage, skip them
3114 if (Question
->QuestionId
== 0) {
3119 // There are Five ways to specify default value for a Question:
3120 // 1, use call back function (highest priority)
3121 // 2, use ExtractConfig function
3122 // 3, use nested EFI_IFR_DEFAULT
3123 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3124 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3126 HiiValue
= &Question
->HiiValue
;
3129 // Get Question defaut value from call back function.
3131 ConfigAccess
= FormSet
->ConfigAccess
;
3132 Action
= GetDefaultIdForCallBack (DefaultId
);
3133 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3134 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3135 Status
= ConfigAccess
->Callback (
3138 Question
->QuestionId
,
3143 if (!EFI_ERROR (Status
)) {
3144 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3145 NewString
= GetToken (Question
->HiiValue
.Value
.string
, FormSet
->HiiHandle
);
3146 ASSERT (NewString
!= NULL
);
3148 ASSERT (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
);
3149 if (StrLen (NewString
) * sizeof (CHAR16
) <= Question
->StorageWidth
) {
3150 CopyMem (Question
->BufferValue
, NewString
, StrSize (NewString
));
3152 CopyMem (Question
->BufferValue
, NewString
, Question
->StorageWidth
);
3155 FreePool (NewString
);
3162 // Get default value from altcfg string.
3164 if (ConfigAccess
!= NULL
) {
3165 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3166 if (!EFI_ERROR (Status
)) {
3172 // EFI_IFR_DEFAULT has highest priority
3174 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3175 Link
= GetFirstNode (&Question
->DefaultListHead
);
3176 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3177 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3179 if (Default
->DefaultId
== DefaultId
) {
3180 if (Default
->ValueExpression
!= NULL
) {
3182 // Default is provided by an Expression, evaluate it
3184 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3185 if (EFI_ERROR (Status
)) {
3189 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3190 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3191 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3192 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3193 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3195 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3196 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3198 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3200 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3201 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3204 // Default value is embedded in EFI_IFR_DEFAULT
3206 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3209 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3210 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3211 if (StrValue
== NULL
) {
3212 return EFI_NOT_FOUND
;
3214 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3215 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3217 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3224 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3229 // EFI_ONE_OF_OPTION
3231 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3232 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3234 // OneOfOption could only provide Standard and Manufacturing default
3236 Link
= GetFirstNode (&Question
->OptionListHead
);
3237 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3238 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3239 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3241 if ((Option
->SuppressExpression
!= NULL
) &&
3242 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3246 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3247 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3249 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3258 // EFI_IFR_CHECKBOX - lowest priority
3260 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3261 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3263 // Checkbox could only provide Standard and Manufacturing default
3265 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3266 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3268 HiiValue
->Value
.b
= TRUE
;
3270 HiiValue
->Value
.b
= FALSE
;
3278 // For Questions without default
3280 Status
= EFI_NOT_FOUND
;
3281 switch (Question
->Operand
) {
3282 case EFI_IFR_NUMERIC_OP
:
3284 // Take minimum value as numeric default value
3286 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3287 HiiValue
->Value
.u64
= Question
->Minimum
;
3288 Status
= EFI_SUCCESS
;
3292 case EFI_IFR_ONE_OF_OP
:
3294 // Take first oneof option as oneof's default value
3296 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3297 Link
= GetFirstNode (&Question
->OptionListHead
);
3298 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3299 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3300 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3302 if ((Option
->SuppressExpression
!= NULL
) &&
3303 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3307 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3308 Status
= EFI_SUCCESS
;
3314 case EFI_IFR_ORDERED_LIST_OP
:
3316 // Take option sequence in IFR as ordered list's default value
3319 Link
= GetFirstNode (&Question
->OptionListHead
);
3320 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3321 Status
= EFI_SUCCESS
;
3322 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3323 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3325 if ((Option
->SuppressExpression
!= NULL
) &&
3326 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3330 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3333 if (Index
>= Question
->MaxContainers
) {
3348 Reset Questions to their initial value or default value in a Form, Formset or System.
3350 GetDefaultValueScope parameter decides which questions will reset
3351 to its default value.
3353 @param FormSet FormSet data structure.
3354 @param Form Form data structure.
3355 @param DefaultId The Class of the default.
3356 @param SettingScope Setting Scope for Default action.
3357 @param GetDefaultValueScope Get default value scope.
3358 @param Storage Get default value only for this storage.
3359 @param RetrieveValueFirst Whether call the retrieve call back to
3360 get the initial value before get default
3363 @retval EFI_SUCCESS The function completed successfully.
3364 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3369 IN FORM_BROWSER_FORMSET
*FormSet
,
3370 IN FORM_BROWSER_FORM
*Form
,
3371 IN UINT16 DefaultId
,
3372 IN BROWSER_SETTING_SCOPE SettingScope
,
3373 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3374 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3375 IN BOOLEAN RetrieveValueFirst
3379 LIST_ENTRY
*FormLink
;
3381 FORM_BROWSER_STATEMENT
*Question
;
3382 FORM_BROWSER_FORMSET
*LocalFormSet
;
3383 FORM_BROWSER_FORMSET
*OldFormSet
;
3385 Status
= EFI_SUCCESS
;
3388 // Check the supported setting level.
3390 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3391 return EFI_UNSUPPORTED
;
3394 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3395 return EFI_UNSUPPORTED
;
3398 if (SettingScope
== FormLevel
) {
3400 // Extract Form default
3402 Link
= GetFirstNode (&Form
->StatementListHead
);
3403 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3404 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3405 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3408 // If get default value only for this storage, check the storage first.
3410 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3415 // If get default value only for no storage question, just skip the question which has storage.
3417 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3422 // If Question is disabled, don't reset it to default
3424 if (Question
->Expression
!= NULL
) {
3425 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3430 if (RetrieveValueFirst
) {
3432 // Call the Retrieve call back to get the initial question value.
3434 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
, FormSet
);
3438 // If not request to get the initial value or get initial value fail, then get default value.
3440 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3441 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3442 if (EFI_ERROR (Status
)) {
3448 // Synchronize Buffer storage's Edit buffer
3450 if ((Question
->Storage
!= NULL
) &&
3451 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3452 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3455 } else if (SettingScope
== FormSetLevel
) {
3456 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3457 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3458 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3459 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3460 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3462 } else if (SettingScope
== SystemLevel
) {
3464 // Preload all Hii formset.
3466 LoadAllHiiFormset();
3468 OldFormSet
= mSystemLevelFormSet
;
3471 // Set Default Value for each FormSet in the maintain list.
3473 Link
= GetFirstNode (&gBrowserFormSetList
);
3474 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3475 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3476 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3477 if (!ValidateFormSet(LocalFormSet
)) {
3481 mSystemLevelFormSet
= LocalFormSet
;
3483 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3486 mSystemLevelFormSet
= OldFormSet
;
3494 Validate whether this question's value has changed.
3496 @param FormSet FormSet data structure.
3497 @param Form Form data structure.
3498 @param Question Question to be initialized.
3499 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3501 @retval TRUE Question's value has changed.
3502 @retval FALSE Question's value has not changed
3506 IsQuestionValueChanged (
3507 IN FORM_BROWSER_FORMSET
*FormSet
,
3508 IN FORM_BROWSER_FORM
*Form
,
3509 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3510 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3513 EFI_HII_VALUE BackUpValue
;
3514 CHAR8
*BackUpBuffer
;
3516 BOOLEAN ValueChanged
;
3520 // For quetion without storage, always mark it as data not changed.
3522 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3526 BackUpBuffer
= NULL
;
3527 ValueChanged
= FALSE
;
3529 switch (Question
->Operand
) {
3530 case EFI_IFR_ORDERED_LIST_OP
:
3531 BufferWidth
= Question
->StorageWidth
;
3532 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3533 ASSERT (BackUpBuffer
!= NULL
);
3536 case EFI_IFR_STRING_OP
:
3537 case EFI_IFR_PASSWORD_OP
:
3538 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3539 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3540 ASSERT (BackUpBuffer
!= NULL
);
3547 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3549 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3550 ASSERT_EFI_ERROR(Status
);
3552 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3553 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3554 ValueChanged
= TRUE
;
3557 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3558 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3560 if (BackUpBuffer
!= NULL
) {
3561 FreePool (BackUpBuffer
);
3564 Question
->ValueChanged
= ValueChanged
;
3566 return ValueChanged
;
3570 Initialize Question's Edit copy from Storage.
3572 @param Selection Selection contains the information about
3573 the Selection, form and formset to be displayed.
3574 Selection action may be updated in retrieve callback.
3575 If Selection is NULL, only initialize Question value.
3576 @param FormSet FormSet data structure.
3577 @param Form Form data structure.
3579 @retval EFI_SUCCESS The function completed successfully.
3584 IN OUT UI_MENU_SELECTION
*Selection
,
3585 IN FORM_BROWSER_FORMSET
*FormSet
,
3586 IN FORM_BROWSER_FORM
*Form
3591 FORM_BROWSER_STATEMENT
*Question
;
3593 Link
= GetFirstNode (&Form
->StatementListHead
);
3594 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3595 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3598 // Initialize local copy of Value for each Question
3600 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3601 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3603 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3605 if (EFI_ERROR (Status
)) {
3609 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3610 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3613 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3620 Initialize Question's Edit copy from Storage for the whole Formset.
3622 @param Selection Selection contains the information about
3623 the Selection, form and formset to be displayed.
3624 Selection action may be updated in retrieve callback.
3625 If Selection is NULL, only initialize Question value.
3626 @param FormSet FormSet data structure.
3628 @retval EFI_SUCCESS The function completed successfully.
3633 IN OUT UI_MENU_SELECTION
*Selection
,
3634 IN FORM_BROWSER_FORMSET
*FormSet
3639 FORM_BROWSER_FORM
*Form
;
3641 Link
= GetFirstNode (&FormSet
->FormListHead
);
3642 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3643 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3646 // Initialize local copy of Value for each Form
3648 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3649 if (EFI_ERROR (Status
)) {
3653 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3657 // Finished question initialization.
3659 FormSet
->QuestionInited
= TRUE
;
3665 Remove the Request element from the Config Request.
3667 @param Storage Pointer to the browser storage.
3668 @param RequestElement The pointer to the Request element.
3673 IN OUT BROWSER_STORAGE
*Storage
,
3674 IN CHAR16
*RequestElement
3680 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3682 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3684 if (NewStr
== NULL
) {
3689 // Remove this element from this ConfigRequest.
3692 NewStr
+= StrLen (RequestElement
);
3693 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3695 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3699 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3701 @param Storage Pointer to the browser storage.
3702 @param ConfigRequest The pointer to the Request element.
3706 RemoveConfigRequest (
3707 BROWSER_STORAGE
*Storage
,
3708 CHAR16
*ConfigRequest
3711 CHAR16
*RequestElement
;
3712 CHAR16
*NextRequestElement
;
3716 // No request element in it, just return.
3718 if (ConfigRequest
== NULL
) {
3722 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3724 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3729 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3731 SearchKey
= L
"&OFFSET";
3735 // Find SearchKey storage
3737 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3738 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3739 ASSERT (RequestElement
!= NULL
);
3740 RequestElement
= StrStr (RequestElement
, SearchKey
);
3742 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3745 while (RequestElement
!= NULL
) {
3747 // +1 to avoid find header itself.
3749 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3752 // The last Request element in configRequest string.
3754 if (NextRequestElement
!= NULL
) {
3756 // Replace "&" with '\0'.
3758 *NextRequestElement
= L
'\0';
3761 RemoveElement (Storage
, RequestElement
);
3763 if (NextRequestElement
!= NULL
) {
3765 // Restore '&' with '\0' for later used.
3767 *NextRequestElement
= L
'&';
3770 RequestElement
= NextRequestElement
;
3774 // If no request element remain, just remove the ConfigRequest string.
3776 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3777 FreePool (Storage
->ConfigRequest
);
3778 Storage
->ConfigRequest
= NULL
;
3779 Storage
->SpareStrLen
= 0;
3784 Base on the current formset info, clean the ConfigRequest string in browser storage.
3786 @param FormSet Pointer of the FormSet
3790 CleanBrowserStorage (
3791 IN OUT FORM_BROWSER_FORMSET
*FormSet
3795 FORMSET_STORAGE
*Storage
;
3797 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3798 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3799 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3800 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3802 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3803 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3807 RemoveConfigRequest (Storage
->BrowserStorage
, Storage
->ConfigRequest
);
3808 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3809 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3810 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3811 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3812 Storage
->BrowserStorage
->ConfigRequest
= NULL
;
3814 Storage
->BrowserStorage
->Initialized
= FALSE
;
3820 Check whether current element in the ConfigReqeust string.
3822 @param BrowserStorage Storage which includes ConfigReqeust.
3823 @param RequestElement New element need to check.
3825 @retval TRUE The Element is in the ConfigReqeust string.
3826 @retval FALSE The Element not in the configReqeust String.
3831 BROWSER_STORAGE
*BrowserStorage
,
3832 CHAR16
*RequestElement
3835 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3839 Append the Request element to the Config Request.
3841 @param ConfigRequest Current ConfigRequest info.
3842 @param SpareStrLen Current remain free buffer for config reqeust.
3843 @param RequestElement New Request element.
3847 AppendConfigRequest (
3848 IN OUT CHAR16
**ConfigRequest
,
3849 IN OUT UINTN
*SpareStrLen
,
3850 IN CHAR16
*RequestElement
3857 StrLength
= StrLen (RequestElement
);
3860 // Append <RequestElement> to <ConfigRequest>
3862 if (StrLength
> *SpareStrLen
) {
3864 // Old String buffer is not sufficient for RequestElement, allocate a new one
3866 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3867 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3868 ASSERT (NewStr
!= NULL
);
3870 if (*ConfigRequest
!= NULL
) {
3871 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3872 FreePool (*ConfigRequest
);
3874 *ConfigRequest
= NewStr
;
3875 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3878 StrCat (*ConfigRequest
, RequestElement
);
3879 *SpareStrLen
-= StrLength
;
3883 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3885 @param Storage Form set Storage.
3886 @param Request The input request string.
3887 @param RespString Whether the input is ConfigRequest or ConfigResp format.
3889 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3890 @retval FALSE All elements covered by current used elements.
3894 ConfigRequestAdjust (
3895 IN BROWSER_STORAGE
*Storage
,
3897 IN BOOLEAN RespString
3900 CHAR16
*RequestElement
;
3901 CHAR16
*NextRequestElement
;
3902 CHAR16
*NextElementBakup
;
3907 CHAR16
*ConfigRequest
;
3911 NextElementBakup
= NULL
;
3914 if (Request
!= NULL
) {
3915 ConfigRequest
= Request
;
3917 ConfigRequest
= Storage
->ConfigRequest
;
3920 if (Storage
->ConfigRequest
== NULL
) {
3921 Storage
->ConfigRequest
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3925 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3927 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3932 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3934 SearchKey
= L
"&OFFSET";
3935 ValueKey
= L
"&VALUE";
3939 // Find SearchKey storage
3941 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3942 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3943 ASSERT (RequestElement
!= NULL
);
3944 RequestElement
= StrStr (RequestElement
, SearchKey
);
3946 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3949 while (RequestElement
!= NULL
) {
3952 // +1 to avoid find header itself.
3954 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3957 // The last Request element in configRequest string.
3959 if (NextRequestElement
!= NULL
) {
3960 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3961 NextElementBakup
= NextRequestElement
;
3962 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3963 ASSERT (NextRequestElement
!= NULL
);
3966 // Replace "&" with '\0'.
3968 *NextRequestElement
= L
'\0';
3970 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3971 NextElementBakup
= NextRequestElement
;
3972 NextRequestElement
= StrStr (RequestElement
, ValueKey
);
3973 ASSERT (NextRequestElement
!= NULL
);
3975 // Replace "&" with '\0'.
3977 *NextRequestElement
= L
'\0';
3981 if (!ElementValidation (Storage
, RequestElement
)) {
3983 // Add this element to the Storage->BrowserStorage->AllRequestElement.
3985 AppendConfigRequest(&Storage
->ConfigRequest
, &Storage
->SpareStrLen
, RequestElement
);
3989 if (NextRequestElement
!= NULL
) {
3991 // Restore '&' with '\0' for later used.
3993 *NextRequestElement
= L
'&';
3996 if (RespString
&& (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
3997 RequestElement
= NextElementBakup
;
3999 RequestElement
= NextRequestElement
;
4008 Base on ConfigRequest info to get default value for current formset.
4010 ConfigRequest info include the info about which questions in current formset need to
4011 get default value. This function only get these questions default value.
4013 @param FormSet FormSet data structure.
4014 @param Storage Storage need to update value.
4015 @param ConfigRequest The config request string.
4019 GetDefaultForFormset (
4020 IN FORM_BROWSER_FORMSET
*FormSet
,
4021 IN BROWSER_STORAGE
*Storage
,
4022 IN CHAR16
*ConfigRequest
4027 LIST_ENTRY BackUpList
;
4028 NAME_VALUE_NODE
*Node
;
4030 LIST_ENTRY
*NodeLink
;
4031 NAME_VALUE_NODE
*TmpNode
;
4033 EFI_STRING Progress
;
4037 InitializeListHead(&BackUpList
);
4040 // Back update the edit buffer.
4042 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4043 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4044 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4045 ASSERT (BackUpBuf
!= NULL
);
4046 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4047 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4048 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4049 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4050 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4053 // Only back Node belong to this formset.
4055 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4059 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4060 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4061 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4063 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4068 // Get default value.
4070 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4073 // Update the question value based on the input ConfigRequest.
4075 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4076 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4077 ASSERT (BackUpBuf
!= NULL
);
4078 BufferSize
= Storage
->Size
;
4079 Status
= mHiiConfigRouting
->BlockToConfig(
4082 Storage
->EditBuffer
,
4087 ASSERT_EFI_ERROR (Status
);
4089 Status
= mHiiConfigRouting
->ConfigToBlock (
4096 ASSERT_EFI_ERROR (Status
);
4098 if (Result
!= NULL
) {
4102 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4103 FreePool (BackUpBuf
);
4104 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4106 // Update question value, only element in ConfigReqeust will be update.
4108 Link
= GetFirstNode (&BackUpList
);
4109 while (!IsNull (&BackUpList
, Link
)) {
4110 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4111 Link
= GetNextNode (&BackUpList
, Link
);
4113 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4117 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4118 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4119 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4120 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4122 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4126 FreePool (TmpNode
->EditValue
);
4127 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4129 RemoveEntryList (&Node
->Link
);
4130 FreePool (Node
->EditValue
);
4131 FreePool (Node
->Name
);
4137 // Restore the Name/Value node.
4139 Link
= GetFirstNode (&BackUpList
);
4140 while (!IsNull (&BackUpList
, Link
)) {
4141 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4142 Link
= GetNextNode (&BackUpList
, Link
);
4147 RemoveEntryList (&Node
->Link
);
4148 FreePool (Node
->EditValue
);
4149 FreePool (Node
->Name
);
4156 Fill storage's edit copy with settings requested from Configuration Driver.
4158 @param FormSet FormSet data structure.
4159 @param Storage Buffer Storage.
4164 IN FORM_BROWSER_FORMSET
*FormSet
,
4165 IN FORMSET_STORAGE
*Storage
4169 EFI_STRING Progress
;
4172 EFI_STRING ConfigRequest
;
4175 ConfigRequest
= NULL
;
4177 switch (Storage
->BrowserStorage
->Type
) {
4178 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4181 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4182 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4183 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4188 case EFI_HII_VARSTORE_BUFFER
:
4189 case EFI_HII_VARSTORE_NAME_VALUE
:
4191 // Skip if there is no RequestElement.
4193 if (Storage
->ElementCount
== 0) {
4198 // Just update the ConfigRequest, if storage already initialized.
4200 if (Storage
->BrowserStorage
->Initialized
) {
4201 ConfigRequestAdjust(Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
4205 Storage
->BrowserStorage
->Initialized
= TRUE
;
4212 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4214 // Create the config request string to get all fields for this storage.
4215 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
4216 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
4218 StrLen
= StrSize (Storage
->BrowserStorage
->ConfigHdr
) + 20 * sizeof (CHAR16
);
4219 ConfigRequest
= AllocateZeroPool (StrLen
);
4220 ASSERT (ConfigRequest
!= NULL
);
4224 L
"%s&OFFSET=0&WIDTH=%04x",
4225 Storage
->BrowserStorage
->ConfigHdr
,
4226 Storage
->BrowserStorage
->Size
);
4228 ConfigRequest
= Storage
->ConfigRequest
;
4232 // Request current settings from Configuration Driver
4234 Status
= mHiiConfigRouting
->ExtractConfig (
4242 // If get value fail, extract default from IFR binary
4244 if (EFI_ERROR (Status
)) {
4245 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4248 // Convert Result from <ConfigAltResp> to <ConfigResp>
4250 StrPtr
= StrStr (Result
, L
"&GUID=");
4251 if (StrPtr
!= NULL
) {
4255 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4259 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4262 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4264 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4266 if (Storage
->BrowserStorage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
4267 if (ConfigRequest
!= NULL
) {
4268 FreePool (ConfigRequest
);
4274 Get Value changed status from old question.
4276 @param NewFormSet FormSet data structure.
4277 @param OldQuestion Old question which has value changed.
4281 SyncStatusForQuestion (
4282 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4283 IN FORM_BROWSER_STATEMENT
*OldQuestion
4287 LIST_ENTRY
*QuestionLink
;
4288 FORM_BROWSER_FORM
*Form
;
4289 FORM_BROWSER_STATEMENT
*Question
;
4292 // For each form in one formset.
4294 Link
= GetFirstNode (&NewFormSet
->FormListHead
);
4295 while (!IsNull (&NewFormSet
->FormListHead
, Link
)) {
4296 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4297 Link
= GetNextNode (&NewFormSet
->FormListHead
, Link
);
4300 // for each question in one form.
4302 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4303 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4304 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4305 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4307 if (Question
->QuestionId
== OldQuestion
->QuestionId
) {
4308 Question
->ValueChanged
= TRUE
;
4316 Get Value changed status from old formset.
4318 @param NewFormSet FormSet data structure.
4319 @param OldFormSet FormSet data structure.
4323 SyncStatusForFormSet (
4324 IN OUT FORM_BROWSER_FORMSET
*NewFormSet
,
4325 IN FORM_BROWSER_FORMSET
*OldFormSet
4329 LIST_ENTRY
*QuestionLink
;
4330 FORM_BROWSER_FORM
*Form
;
4331 FORM_BROWSER_STATEMENT
*Question
;
4334 // For each form in one formset.
4336 Link
= GetFirstNode (&OldFormSet
->FormListHead
);
4337 while (!IsNull (&OldFormSet
->FormListHead
, Link
)) {
4338 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
4339 Link
= GetNextNode (&OldFormSet
->FormListHead
, Link
);
4342 // for each question in one form.
4344 QuestionLink
= GetFirstNode (&Form
->StatementListHead
);
4345 while (!IsNull (&Form
->StatementListHead
, QuestionLink
)) {
4346 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink
);
4347 QuestionLink
= GetNextNode (&Form
->StatementListHead
, QuestionLink
);
4349 if (!Question
->ValueChanged
) {
4354 // Find the same question in new formset and update the value changed flag.
4356 SyncStatusForQuestion (NewFormSet
, Question
);
4362 Get current setting of Questions.
4364 @param FormSet FormSet data structure.
4368 InitializeCurrentSetting (
4369 IN OUT FORM_BROWSER_FORMSET
*FormSet
4373 FORMSET_STORAGE
*Storage
;
4374 FORM_BROWSER_FORMSET
*OldFormSet
;
4377 // Try to find pre FormSet in the maintain backup list.
4378 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4380 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4381 if (OldFormSet
!= NULL
) {
4382 SyncStatusForFormSet (FormSet
, OldFormSet
);
4383 RemoveEntryList (&OldFormSet
->Link
);
4384 DestroyFormSet (OldFormSet
);
4386 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4389 // Extract default from IFR binary for no storage questions.
4391 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4394 // Request current settings from Configuration Driver
4396 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4397 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4398 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4400 LoadStorage (FormSet
, Storage
);
4402 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4408 Fetch the Ifr binary data of a FormSet.
4410 @param Handle PackageList Handle
4411 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4412 specified (NULL or zero GUID), take the first
4413 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4414 found in package list.
4415 On output, GUID of the formset found(if not NULL).
4416 @param BinaryLength The length of the FormSet IFR binary.
4417 @param BinaryData The buffer designed to receive the FormSet.
4419 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4420 BufferLength was updated.
4421 @retval EFI_INVALID_PARAMETER The handle is unknown.
4422 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4423 be found with the requested FormId.
4428 IN EFI_HII_HANDLE Handle
,
4429 IN OUT EFI_GUID
*FormSetGuid
,
4430 OUT UINTN
*BinaryLength
,
4431 OUT UINT8
**BinaryData
4435 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4441 UINT32 PackageListLength
;
4442 EFI_HII_PACKAGE_HEADER PackageHeader
;
4444 UINT8 NumberOfClassGuid
;
4445 BOOLEAN ClassGuidMatch
;
4446 EFI_GUID
*ClassGuid
;
4447 EFI_GUID
*ComparingGuid
;
4451 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4454 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4456 if (FormSetGuid
== NULL
) {
4457 ComparingGuid
= &gZeroGuid
;
4459 ComparingGuid
= FormSetGuid
;
4463 // Get HII PackageList
4466 HiiPackageList
= NULL
;
4467 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4468 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4469 HiiPackageList
= AllocatePool (BufferSize
);
4470 ASSERT (HiiPackageList
!= NULL
);
4472 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4474 if (EFI_ERROR (Status
)) {
4477 ASSERT (HiiPackageList
!= NULL
);
4480 // Get Form package from this HII package List
4482 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4484 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4486 ClassGuidMatch
= FALSE
;
4487 while (Offset
< PackageListLength
) {
4488 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4489 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4491 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4493 // Search FormSet in this Form Package
4495 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4496 while (Offset2
< PackageHeader
.Length
) {
4497 OpCodeData
= Package
+ Offset2
;
4499 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4501 // Try to compare against formset GUID
4503 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4504 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4508 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4510 // Try to compare against formset class GUID
4512 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4513 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4514 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4515 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4516 ClassGuidMatch
= TRUE
;
4520 if (ClassGuidMatch
) {
4523 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4524 ClassGuidMatch
= TRUE
;
4529 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4532 if (Offset2
< PackageHeader
.Length
) {
4534 // Target formset found
4540 Offset
+= PackageHeader
.Length
;
4543 if (Offset
>= PackageListLength
) {
4545 // Form package not found in this Package List
4547 FreePool (HiiPackageList
);
4548 return EFI_NOT_FOUND
;
4551 if (FormSetGuid
!= NULL
) {
4553 // Return the FormSet GUID
4555 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4559 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4560 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4561 // of the Form Package.
4563 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4564 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4566 FreePool (HiiPackageList
);
4568 if (*BinaryData
== NULL
) {
4569 return EFI_OUT_OF_RESOURCES
;
4577 Initialize the internal data structure of a FormSet.
4579 @param Handle PackageList Handle
4580 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4581 specified (NULL or zero GUID), take the first
4582 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4583 found in package list.
4584 On output, GUID of the formset found(if not NULL).
4585 @param FormSet FormSet data structure.
4587 @retval EFI_SUCCESS The function completed successfully.
4588 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4593 IN EFI_HII_HANDLE Handle
,
4594 IN OUT EFI_GUID
*FormSetGuid
,
4595 OUT FORM_BROWSER_FORMSET
*FormSet
4599 EFI_HANDLE DriverHandle
;
4601 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4602 if (EFI_ERROR (Status
)) {
4606 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4607 FormSet
->HiiHandle
= Handle
;
4608 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4609 FormSet
->QuestionInited
= FALSE
;
4612 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4614 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4615 if (EFI_ERROR (Status
)) {
4618 FormSet
->DriverHandle
= DriverHandle
;
4619 Status
= gBS
->HandleProtocol (
4621 &gEfiHiiConfigAccessProtocolGuid
,
4622 (VOID
**) &FormSet
->ConfigAccess
4624 if (EFI_ERROR (Status
)) {
4626 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4627 // list, then there will be no configuration action required
4629 FormSet
->ConfigAccess
= NULL
;
4633 // Parse the IFR binary OpCodes
4635 Status
= ParseOpCodes (FormSet
);
4642 Save globals used by previous call to SendForm(). SendForm() may be called from
4643 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4644 So, save globals of previous call to SendForm() and restore them upon exit.
4648 SaveBrowserContext (
4652 BROWSER_CONTEXT
*Context
;
4653 FORM_ENTRY_INFO
*MenuList
;
4655 gBrowserContextCount
++;
4656 if (gBrowserContextCount
== 1) {
4658 // This is not reentry of SendForm(), no context to save
4663 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4664 ASSERT (Context
!= NULL
);
4666 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4669 // Save FormBrowser context
4671 Context
->Selection
= gCurrentSelection
;
4672 Context
->ResetRequired
= gResetRequired
;
4673 Context
->ExitRequired
= gExitRequired
;
4674 Context
->HiiHandle
= mCurrentHiiHandle
;
4675 Context
->FormId
= mCurrentFormId
;
4676 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4679 // Save the menu history data.
4681 InitializeListHead(&Context
->FormHistoryList
);
4682 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4683 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4684 RemoveEntryList (&MenuList
->Link
);
4686 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4690 // Insert to FormBrowser context list
4692 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4697 Restore globals used by previous call to SendForm().
4701 RestoreBrowserContext (
4706 BROWSER_CONTEXT
*Context
;
4707 FORM_ENTRY_INFO
*MenuList
;
4709 ASSERT (gBrowserContextCount
!= 0);
4710 gBrowserContextCount
--;
4711 if (gBrowserContextCount
== 0) {
4713 // This is not reentry of SendForm(), no context to restore
4718 ASSERT (!IsListEmpty (&gBrowserContextList
));
4720 Link
= GetFirstNode (&gBrowserContextList
);
4721 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4724 // Restore FormBrowser context
4726 gCurrentSelection
= Context
->Selection
;
4727 gResetRequired
= Context
->ResetRequired
;
4728 gExitRequired
= Context
->ExitRequired
;
4729 mCurrentHiiHandle
= Context
->HiiHandle
;
4730 mCurrentFormId
= Context
->FormId
;
4731 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4734 // Restore the menu history data.
4736 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4737 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4738 RemoveEntryList (&MenuList
->Link
);
4740 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4744 // Remove from FormBrowser context list
4746 RemoveEntryList (&Context
->Link
);
4747 gBS
->FreePool (Context
);
4751 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4753 @param Handle The Hii Handle.
4755 @return the found FormSet context. If no found, NULL will return.
4758 FORM_BROWSER_FORMSET
*
4759 GetFormSetFromHiiHandle (
4760 EFI_HII_HANDLE Handle
4764 FORM_BROWSER_FORMSET
*FormSet
;
4766 Link
= GetFirstNode (&gBrowserFormSetList
);
4767 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4768 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4769 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4770 if (!ValidateFormSet(FormSet
)) {
4773 if (FormSet
->HiiHandle
== Handle
) {
4782 Check whether the input HII handle is the FormSet that is being used.
4784 @param Handle The Hii Handle.
4786 @retval TRUE HII handle is being used.
4787 @retval FALSE HII handle is not being used.
4791 IsHiiHandleInBrowserContext (
4792 EFI_HII_HANDLE Handle
4796 BROWSER_CONTEXT
*Context
;
4799 // HiiHandle is Current FormSet.
4801 if (mCurrentHiiHandle
== Handle
) {
4806 // Check whether HiiHandle is in BrowserContext.
4808 Link
= GetFirstNode (&gBrowserContextList
);
4809 while (!IsNull (&gBrowserContextList
, Link
)) {
4810 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4811 if (Context
->HiiHandle
== Handle
) {
4813 // HiiHandle is in BrowserContext
4817 Link
= GetNextNode (&gBrowserContextList
, Link
);
4824 Perform Password check.
4825 Passwork may be encrypted by driver that requires the specific check.
4827 @param Form Form where Password Statement is in.
4828 @param Statement Password statement
4829 @param PasswordString Password string to be checked. It may be NULL.
4830 NULL means to restore password.
4831 "" string can be used to checked whether old password does exist.
4833 @return Status Status of Password check.
4838 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4839 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4840 IN EFI_STRING PasswordString OPTIONAL
4844 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4845 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4846 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4847 FORM_BROWSER_STATEMENT
*Question
;
4849 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4850 Question
= GetBrowserStatement(Statement
);
4851 ASSERT (Question
!= NULL
);
4853 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4854 if (ConfigAccess
== NULL
) {
4855 return EFI_UNSUPPORTED
;
4858 if (PasswordString
== NULL
) {
4863 // Check whether has preexisted password.
4865 if (PasswordString
[0] == 0) {
4866 if (*((CHAR16
*) Question
->BufferValue
) == 0) {
4869 return EFI_NOT_READY
;
4874 // Check whether the input password is same as preexisted password.
4876 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4879 return EFI_NOT_READY
;
4884 // Prepare password string in HII database
4886 if (PasswordString
!= NULL
) {
4887 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4889 IfrTypeValue
.string
= 0;
4893 // Send password to Configuration Driver for validation
4895 Status
= ConfigAccess
->Callback (
4897 EFI_BROWSER_ACTION_CHANGING
,
4898 Question
->QuestionId
,
4899 Question
->HiiValue
.Type
,
4905 // Remove password string from HII database
4907 if (PasswordString
!= NULL
) {
4908 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4915 Find the registered HotKey based on KeyData.
4917 @param[in] KeyData A pointer to a buffer that describes the keystroke
4918 information for the hot key.
4920 @return The registered HotKey context. If no found, NULL will return.
4923 GetHotKeyFromRegisterList (
4924 IN EFI_INPUT_KEY
*KeyData
4928 BROWSER_HOT_KEY
*HotKey
;
4930 Link
= GetFirstNode (&gBrowserHotKeyList
);
4931 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4932 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4933 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4936 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4943 Configure what scope the hot key will impact.
4944 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4945 If no scope is set, the default scope will be FormSet level.
4946 After all registered hot keys are removed, previous Scope can reset to another level.
4948 @param[in] Scope Scope level to be set.
4950 @retval EFI_SUCCESS Scope is set correctly.
4951 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4952 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4958 IN BROWSER_SETTING_SCOPE Scope
4961 if (Scope
>= MaxLevel
) {
4962 return EFI_INVALID_PARAMETER
;
4966 // When no hot key registered in system or on the first setting,
4967 // Scope can be set.
4969 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4970 gBrowserSettingScope
= Scope
;
4971 mBrowserScopeFirstSet
= FALSE
;
4972 } else if (Scope
!= gBrowserSettingScope
) {
4973 return EFI_UNSUPPORTED
;
4980 Register the hot key with its browser action, or unregistered the hot key.
4981 Only support hot key that is not printable character (control key, function key, etc.).
4982 If the action value is zero, the hot key will be unregistered if it has been registered.
4983 If the same hot key has been registered, the new action and help string will override the previous ones.
4985 @param[in] KeyData A pointer to a buffer that describes the keystroke
4986 information for the hot key. Its type is EFI_INPUT_KEY to
4987 be supported by all ConsoleIn devices.
4988 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4989 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4990 @param[in] HelpString Help string that describes the hot key information.
4991 Its value may be NULL for the unregistered hot key.
4993 @retval EFI_SUCCESS Hot key is registered or unregistered.
4994 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4995 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4996 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
5001 IN EFI_INPUT_KEY
*KeyData
,
5003 IN UINT16 DefaultId
,
5004 IN EFI_STRING HelpString OPTIONAL
5007 BROWSER_HOT_KEY
*HotKey
;
5010 // Check input parameters.
5012 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
5013 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
5014 return EFI_INVALID_PARAMETER
;
5018 // Check whether the input KeyData is in BrowserHotKeyList.
5020 HotKey
= GetHotKeyFromRegisterList (KeyData
);
5023 // Unregister HotKey
5025 if (Action
== BROWSER_ACTION_UNREGISTER
) {
5026 if (HotKey
!= NULL
) {
5028 // The registered HotKey is found.
5029 // Remove it from List, and free its resource.
5031 RemoveEntryList (&HotKey
->Link
);
5032 FreePool (HotKey
->KeyData
);
5033 FreePool (HotKey
->HelpString
);
5037 // The registered HotKey is not found.
5039 return EFI_NOT_FOUND
;
5044 // Register HotKey into List.
5046 if (HotKey
== NULL
) {
5048 // Create new Key, and add it into List.
5050 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5051 ASSERT (HotKey
!= NULL
);
5052 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5053 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5054 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5058 // Fill HotKey information.
5060 HotKey
->Action
= Action
;
5061 HotKey
->DefaultId
= DefaultId
;
5062 if (HotKey
->HelpString
!= NULL
) {
5063 FreePool (HotKey
->HelpString
);
5065 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5071 Register Exit handler function.
5072 When more than one handler function is registered, the latter one will override the previous one.
5073 When NULL handler is specified, the previous Exit handler will be unregistered.
5075 @param[in] Handler Pointer to handler function.
5080 RegiserExitHandler (
5081 IN EXIT_HANDLER Handler
5084 ExitHandlerFunction
= Handler
;
5089 Check whether the browser data has been modified.
5091 @retval TRUE Browser data is modified.
5092 @retval FALSE No browser data is modified.
5097 IsBrowserDataModified (
5102 FORM_BROWSER_FORMSET
*FormSet
;
5104 switch (gBrowserSettingScope
) {
5106 if (gCurrentSelection
== NULL
) {
5109 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5112 if (gCurrentSelection
== NULL
) {
5115 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5118 Link
= GetFirstNode (&gBrowserFormSetList
);
5119 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5120 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5121 if (!ValidateFormSet(FormSet
)) {
5125 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5128 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5138 Execute the action requested by the Action parameter.
5140 @param[in] Action Execute the request action.
5141 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5143 @retval EFI_SUCCESS Execute the request action succss.
5144 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5155 FORM_BROWSER_FORMSET
*FormSet
;
5156 FORM_BROWSER_FORM
*Form
;
5158 if (gBrowserSettingScope
< SystemLevel
&& gCurrentSelection
== NULL
) {
5159 return EFI_NOT_READY
;
5162 Status
= EFI_SUCCESS
;
5165 if (gBrowserSettingScope
< SystemLevel
) {
5166 FormSet
= gCurrentSelection
->FormSet
;
5167 Form
= gCurrentSelection
->Form
;
5171 // Executet the discard action.
5173 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5174 Status
= DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5175 if (EFI_ERROR (Status
)) {
5181 // Executet the difault action.
5183 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5184 Status
= ExtractDefault (FormSet
, Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5185 if (EFI_ERROR (Status
)) {
5188 UpdateStatementStatus (FormSet
, Form
, gBrowserSettingScope
);
5192 // Executet the submit action.
5194 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5195 Status
= SubmitForm (FormSet
, Form
, gBrowserSettingScope
);
5196 if (EFI_ERROR (Status
)) {
5202 // Executet the reset action.
5204 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5205 gResetRequired
= TRUE
;
5209 // Executet the exit action.
5211 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5212 DiscardForm (FormSet
, Form
, gBrowserSettingScope
);
5213 if (gBrowserSettingScope
== SystemLevel
) {
5214 if (ExitHandlerFunction
!= NULL
) {
5215 ExitHandlerFunction ();
5219 gExitRequired
= TRUE
;
5226 Create reminder to let user to choose save or discard the changed browser data.
5227 Caller can use it to actively check the changed browser data.
5229 @retval BROWSER_NO_CHANGES No browser data is changed.
5230 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5231 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5232 @retval BROWSER_KEEP_CURRENT Browser keep current changes.
5242 FORM_BROWSER_FORMSET
*FormSet
;
5243 BOOLEAN IsDataChanged
;
5244 UINT32 DataSavedAction
;
5247 DataSavedAction
= BROWSER_NO_CHANGES
;
5248 IsDataChanged
= FALSE
;
5249 Link
= GetFirstNode (&gBrowserFormSetList
);
5250 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5251 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5252 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5253 if (!ValidateFormSet(FormSet
)) {
5256 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5257 IsDataChanged
= TRUE
;
5263 // No data is changed. No save is required.
5265 if (!IsDataChanged
) {
5266 return DataSavedAction
;
5270 // If data is changed, prompt user to save or discard it.
5273 ConfirmRet
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5275 if (ConfirmRet
== BROWSER_ACTION_SUBMIT
) {
5276 SubmitForm (NULL
, NULL
, SystemLevel
);
5277 DataSavedAction
= BROWSER_SAVE_CHANGES
;
5279 } else if (ConfirmRet
== BROWSER_ACTION_DISCARD
) {
5280 DiscardForm (NULL
, NULL
, SystemLevel
);
5281 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
5283 } else if (ConfirmRet
== BROWSER_ACTION_NONE
) {
5284 DataSavedAction
= BROWSER_KEEP_CURRENT
;
5289 return DataSavedAction
;