2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, 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 gFinishRetrieveCall
;
52 BOOLEAN gResetRequired
;
53 BOOLEAN gExitRequired
;
54 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
55 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
56 EXIT_HANDLER ExitHandlerFunction
= NULL
;
57 FORM_BROWSER_FORMSET
*mSystemLevelFormSet
;
60 // Browser Global Strings
63 CHAR16
*mUnknownString
= L
"!";
65 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
67 extern UINT32 gBrowserStatus
;
68 extern CHAR16
*gErrorInfo
;
69 extern EFI_GUID mCurrentFormSetGuid
;
70 extern EFI_HII_HANDLE mCurrentHiiHandle
;
71 extern UINT16 mCurrentFormId
;
72 extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData
;
75 Create a menu with specified formset GUID and form ID, and add it as a child
76 of the given parent menu.
78 @param HiiHandle Hii handle related to this formset.
79 @param FormSetGuid The Formset Guid of menu to be added.
80 @param FormId The Form ID of menu to be added.
81 @param QuestionId The question id of this menu to be added.
83 @return A pointer to the newly added menu or NULL if memory is insufficient.
88 IN EFI_HII_HANDLE HiiHandle
,
89 IN EFI_GUID
*FormSetGuid
,
94 FORM_ENTRY_INFO
*MenuList
;
96 MenuList
= AllocateZeroPool (sizeof (FORM_ENTRY_INFO
));
97 if (MenuList
== NULL
) {
101 MenuList
->Signature
= FORM_ENTRY_INFO_SIGNATURE
;
103 MenuList
->HiiHandle
= HiiHandle
;
104 CopyMem (&MenuList
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
105 MenuList
->FormId
= FormId
;
106 MenuList
->QuestionId
= QuestionId
;
109 // If parent is not specified, it is the root Form of a Formset
111 InsertTailList (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
117 Return the form id for the input hiihandle and formset.
119 @param HiiHandle HiiHandle for FormSet.
120 @param FormSetGuid The Formset GUID of the menu to search.
122 @return First form's id for this form set.
127 IN EFI_HII_HANDLE HiiHandle
,
128 IN EFI_GUID
*FormSetGuid
132 FORM_BROWSER_FORM
*Form
;
134 Link
= GetFirstNode (&gCurrentSelection
->FormSet
->FormListHead
);
135 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
141 Search Menu with given FormSetGuid and FormId in all cached menu list.
143 @param HiiHandle HiiHandle for FormSet.
144 @param FormSetGuid The Formset GUID of the menu to search.
145 @param FormId The Form ID of menu to search.
147 @return A pointer to menu found or NULL if not found.
152 IN EFI_HII_HANDLE HiiHandle
,
153 IN EFI_GUID
*FormSetGuid
,
158 FORM_ENTRY_INFO
*MenuList
;
159 FORM_ENTRY_INFO
*RetMenu
;
160 EFI_FORM_ID FirstFormId
;
164 Link
= GetFirstNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
165 while (!IsNull (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
)) {
166 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Link
);
167 Link
= GetNextNode (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, Link
);
170 // If already find the menu, free the menus behind it.
172 if (RetMenu
!= NULL
) {
173 RemoveEntryList (&MenuList
->Link
);
179 // Find the same FromSet.
181 if (MenuList
->HiiHandle
== HiiHandle
) {
182 if (CompareGuid (&MenuList
->FormSetGuid
, &gZeroGuid
)) {
184 // FormSetGuid is not specified.
187 } else if (CompareGuid (&MenuList
->FormSetGuid
, FormSetGuid
)) {
188 if (MenuList
->FormId
== FormId
) {
190 } else if (FormId
== 0 || MenuList
->FormId
== 0 ) {
191 FirstFormId
= GetFirstFormId (HiiHandle
, FormSetGuid
);
192 if ((FormId
== 0 && FirstFormId
== MenuList
->FormId
) || (MenuList
->FormId
==0 && FirstFormId
== FormId
)) {
204 Find parent menu for current menu.
206 @param CurrentMenu Current Menu
208 @retval The parent menu for current menu.
212 IN FORM_ENTRY_INFO
*CurrentMenu
215 FORM_ENTRY_INFO
*ParentMenu
;
218 if (CurrentMenu
->Link
.BackLink
!= &mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
) {
219 ParentMenu
= FORM_ENTRY_INFO_FROM_LINK (CurrentMenu
->Link
.BackLink
);
226 Free Menu list linked list.
228 @param MenuListHead One Menu list point in the menu list.
233 LIST_ENTRY
*MenuListHead
236 FORM_ENTRY_INFO
*MenuList
;
238 while (!IsListEmpty (MenuListHead
)) {
239 MenuList
= FORM_ENTRY_INFO_FROM_LINK (MenuListHead
->ForwardLink
);
240 RemoveEntryList (&MenuList
->Link
);
247 Load all hii formset to the browser.
255 FORM_BROWSER_FORMSET
*LocalFormSet
;
256 EFI_HII_HANDLE
*HiiHandles
;
260 FORM_BROWSER_FORMSET
*OldFormset
;
261 BOOLEAN OldRetrieveValue
;
263 OldFormset
= mSystemLevelFormSet
;
264 OldRetrieveValue
= gFinishRetrieveCall
;
265 gFinishRetrieveCall
= FALSE
;
268 // Get all the Hii handles
270 HiiHandles
= HiiGetHiiHandles (NULL
);
271 ASSERT (HiiHandles
!= NULL
);
274 // Search for formset of each class type
276 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
278 // Check HiiHandles[Index] does exist in global maintain list.
280 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
285 // Initilize FormSet Setting
287 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
288 ASSERT (LocalFormSet
!= NULL
);
289 mSystemLevelFormSet
= LocalFormSet
;
291 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
292 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
);
293 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
294 DestroyFormSet (LocalFormSet
);
297 InitializeCurrentSetting (LocalFormSet
);
300 // Initilize Questions' Value
302 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
303 if (EFI_ERROR (Status
)) {
304 DestroyFormSet (LocalFormSet
);
310 // Free resources, and restore gOldFormSet and gClassOfVfr
312 FreePool (HiiHandles
);
314 gFinishRetrieveCall
= OldRetrieveValue
;
315 mSystemLevelFormSet
= OldFormset
;
319 This is the routine which an external caller uses to direct the browser
320 where to obtain it's information.
323 @param This The Form Browser protocol instanse.
324 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
325 display a list of the formsets for the handles specified.
326 @param HandleCount The number of Handles specified in Handle.
327 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
328 field in the EFI_IFR_FORM_SET op-code for the specified
329 forms-based package. If FormSetGuid is NULL, then this
330 function will display the first found forms package.
331 @param FormId This field specifies which EFI_IFR_FORM to render as the first
332 displayable page. If this field has a value of 0x0000, then
333 the forms browser will render the specified forms in their encoded order.
334 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
336 @param ActionRequest Points to the action recommended by the form.
338 @retval EFI_SUCCESS The function completed successfully.
339 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
340 @retval EFI_NOT_FOUND No valid forms could be found to display.
346 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
347 IN EFI_HII_HANDLE
*Handles
,
348 IN UINTN HandleCount
,
349 IN EFI_GUID
*FormSetGuid
, OPTIONAL
350 IN UINT16 FormId
, OPTIONAL
351 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
352 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
356 UI_MENU_SELECTION
*Selection
;
358 FORM_BROWSER_FORMSET
*FormSet
;
359 FORM_ENTRY_INFO
*MenuList
;
362 // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
364 if (mFormDisplay
== NULL
) {
365 return EFI_UNSUPPORTED
;
369 // Save globals used by SendForm()
371 SaveBrowserContext ();
373 gFinishRetrieveCall
= FALSE
;
374 gResetRequired
= FALSE
;
375 gExitRequired
= FALSE
;
376 Status
= EFI_SUCCESS
;
378 gDisplayFormData
.ScreenDimensions
= (EFI_SCREEN_DESCRIPTOR
*) ScreenDimensions
;
380 for (Index
= 0; Index
< HandleCount
; Index
++) {
381 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
382 ASSERT (Selection
!= NULL
);
384 Selection
->Handle
= Handles
[Index
];
385 if (FormSetGuid
!= NULL
) {
386 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
387 Selection
->FormId
= FormId
;
389 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
393 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
394 ASSERT (FormSet
!= NULL
);
397 // Initialize internal data structures of FormSet
399 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
);
400 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
401 DestroyFormSet (FormSet
);
404 Selection
->FormSet
= FormSet
;
405 mSystemLevelFormSet
= FormSet
;
408 // Display this formset
410 gCurrentSelection
= Selection
;
412 Status
= SetupBrowser (Selection
);
414 gCurrentSelection
= NULL
;
415 mSystemLevelFormSet
= NULL
;
418 // If no data is changed, don't need to save current FormSet into the maintain list.
420 if (!IsNvUpdateRequiredForFormSet (FormSet
) && !IsStorageDataChangedForFormSet(FormSet
)) {
421 CleanBrowserStorage(FormSet
);
422 RemoveEntryList (&FormSet
->Link
);
423 DestroyFormSet (FormSet
);
426 if (EFI_ERROR (Status
)) {
429 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
431 FreePool (Selection
);
435 // Still has error info, pop up a message.
437 if (gBrowserStatus
!= BROWSER_SUCCESS
) {
438 gDisplayFormData
.BrowserStatus
= gBrowserStatus
;
439 gDisplayFormData
.ErrorString
= gErrorInfo
;
441 gBrowserStatus
= BROWSER_SUCCESS
;
444 mFormDisplay
->FormDisplay (&gDisplayFormData
, NULL
);
447 if (ActionRequest
!= NULL
) {
448 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
449 if (gResetRequired
) {
450 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
454 mFormDisplay
->ExitDisplay();
457 // Clear the menu history data.
459 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
460 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
461 RemoveEntryList (&MenuList
->Link
);
466 // Restore globals used by SendForm()
468 RestoreBrowserContext ();
474 Get or set data to the storage.
476 @param ResultsDataSize The size of the buffer associatedwith ResultsData.
477 @param ResultsData A string returned from an IFR browser or
478 equivalent. The results string will have no
479 routing information in them.
480 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
481 (if RetrieveData = TRUE) data from the uncommitted
482 browser state information or set (if RetrieveData
483 = FALSE) data in the uncommitted browser state
485 @param Storage The pointer to the storage.
487 @retval EFI_SUCCESS The results have been distributed or are awaiting
493 IN OUT UINTN
*ResultsDataSize
,
494 IN OUT EFI_STRING
*ResultsData
,
495 IN BOOLEAN RetrieveData
,
496 IN BROWSER_STORAGE
*Storage
507 // Generate <ConfigResp>
509 Status
= StorageToConfigResp (Storage
, &ConfigResp
, Storage
->ConfigRequest
, TRUE
);
510 if (EFI_ERROR (Status
)) {
515 // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
516 // Also need to consider add "\0" at first time.
518 StrPtr
= ConfigResp
+ StrLen (Storage
->ConfigHdr
) + 1;
519 BufferSize
= StrSize (StrPtr
);
523 // Copy the data if the input buffer is bigger enough.
525 if (*ResultsDataSize
>= BufferSize
) {
526 StrCpy (*ResultsData
, StrPtr
);
529 *ResultsDataSize
= BufferSize
;
530 FreePool (ConfigResp
);
533 // Prepare <ConfigResp>
535 TmpSize
= StrLen (*ResultsData
);
536 BufferSize
= (TmpSize
+ StrLen (Storage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
537 ConfigResp
= AllocateZeroPool (BufferSize
);
538 ASSERT (ConfigResp
!= NULL
);
540 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
541 StrCat (ConfigResp
, L
"&");
542 StrCat (ConfigResp
, *ResultsData
);
545 // Update Browser uncommited data
547 Status
= ConfigRespToStorage (Storage
, ConfigResp
);
548 FreePool (ConfigResp
);
549 if (EFI_ERROR (Status
)) {
558 This routine called this service in the browser to retrieve or set certain uncommitted
559 state information that resides in the open formsets.
561 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
563 @param ResultsDataSize A pointer to the size of the buffer associated
565 @param ResultsData A string returned from an IFR browser or
566 equivalent. The results string will have no
567 routing information in them.
568 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
569 (if RetrieveData = TRUE) data from the uncommitted
570 browser state information or set (if RetrieveData
571 = FALSE) data in the uncommitted browser state
573 @param VariableGuid An optional field to indicate the target variable
575 @param VariableName An optional field to indicate the target
576 human-readable variable name.
578 @retval EFI_SUCCESS The results have been distributed or are awaiting
580 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
581 contain the results data.
587 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
588 IN OUT UINTN
*ResultsDataSize
,
589 IN OUT EFI_STRING ResultsData
,
590 IN BOOLEAN RetrieveData
,
591 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
592 IN CONST CHAR16
*VariableName OPTIONAL
597 BROWSER_STORAGE
*Storage
;
598 FORMSET_STORAGE
*FormsetStorage
;
602 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
603 return EFI_INVALID_PARAMETER
;
606 TotalSize
= *ResultsDataSize
;
609 Status
= EFI_SUCCESS
;
612 // If set browser data, pre load all hii formset to avoid set the varstore which is not
615 if (!RetrieveData
&& (gBrowserSettingScope
== SystemLevel
)) {
619 if (VariableGuid
!= NULL
) {
621 // Try to find target storage in the current formset.
623 Link
= GetFirstNode (&gBrowserStorageList
);
624 while (!IsNull (&gBrowserStorageList
, Link
)) {
625 Storage
= BROWSER_STORAGE_FROM_LINK (Link
);
626 Link
= GetNextNode (&gBrowserStorageList
, Link
);
628 // Check the current storage.
630 if (!CompareGuid (&Storage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
634 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
635 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
637 // Buffer storage require both GUID and Name
639 if (VariableName
== NULL
) {
640 return EFI_NOT_FOUND
;
643 if (StrCmp (Storage
->Name
, (CHAR16
*) VariableName
) != 0) {
648 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
||
649 Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) {
650 if (mSystemLevelFormSet
== NULL
|| mSystemLevelFormSet
->HiiHandle
== NULL
) {
651 return EFI_NOT_FOUND
;
654 if (Storage
->HiiHandle
!= mSystemLevelFormSet
->HiiHandle
) {
659 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, Storage
);
660 if (EFI_ERROR (Status
)) {
665 // Different formsets may have same varstore, so here just set the flag
666 // not exit the circle.
673 return EFI_NOT_FOUND
;
677 // GUID/Name is not specified, take the first storage in FormSet
679 if (mSystemLevelFormSet
== NULL
) {
680 return EFI_NOT_READY
;
684 // Generate <ConfigResp>
686 Link
= GetFirstNode (&mSystemLevelFormSet
->StorageListHead
);
687 if (IsNull (&mSystemLevelFormSet
->StorageListHead
, Link
)) {
688 return EFI_UNSUPPORTED
;
691 FormsetStorage
= FORMSET_STORAGE_FROM_LINK (Link
);
693 Status
= ProcessStorage (&TotalSize
, &ResultsData
, RetrieveData
, FormsetStorage
->BrowserStorage
);
694 if (EFI_ERROR (Status
)) {
700 Status
= TotalSize
<= *ResultsDataSize
? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
701 *ResultsDataSize
= TotalSize
;
710 Callback function for SimpleTextInEx protocol install events
712 @param Event the event that is signaled.
713 @param Context not used here.
718 FormDisplayCallback (
725 if (mFormDisplay
!= NULL
) {
729 Status
= gBS
->LocateProtocol (
730 &gEdkiiFormDisplayEngineProtocolGuid
,
732 (VOID
**) &mFormDisplay
737 Initialize Setup Browser driver.
739 @param ImageHandle The image handle.
740 @param SystemTable The system table.
742 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
743 @return Other value if failed to initialize the Setup Browser module.
749 IN EFI_HANDLE ImageHandle
,
750 IN EFI_SYSTEM_TABLE
*SystemTable
757 // Locate required Hii relative protocols
759 Status
= gBS
->LocateProtocol (
760 &gEfiHiiDatabaseProtocolGuid
,
762 (VOID
**) &mHiiDatabase
764 ASSERT_EFI_ERROR (Status
);
766 Status
= gBS
->LocateProtocol (
767 &gEfiHiiConfigRoutingProtocolGuid
,
769 (VOID
**) &mHiiConfigRouting
771 ASSERT_EFI_ERROR (Status
);
773 Status
= gBS
->LocateProtocol (
774 &gEfiDevicePathFromTextProtocolGuid
,
776 (VOID
**) &mPathFromText
780 // Install FormBrowser2 protocol
782 mPrivateData
.Handle
= NULL
;
783 Status
= gBS
->InstallProtocolInterface (
784 &mPrivateData
.Handle
,
785 &gEfiFormBrowser2ProtocolGuid
,
786 EFI_NATIVE_INTERFACE
,
787 &mPrivateData
.FormBrowser2
789 ASSERT_EFI_ERROR (Status
);
792 // Install FormBrowserEx2 protocol
794 InitializeListHead (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
);
795 InitializeListHead (&mPrivateData
.FormBrowserEx2
.OverrideQestListHead
);
796 mPrivateData
.Handle
= NULL
;
797 Status
= gBS
->InstallProtocolInterface (
798 &mPrivateData
.Handle
,
799 &gEdkiiFormBrowserEx2ProtocolGuid
,
800 EFI_NATIVE_INTERFACE
,
801 &mPrivateData
.FormBrowserEx2
803 ASSERT_EFI_ERROR (Status
);
805 Status
= gBS
->InstallProtocolInterface (
806 &mPrivateData
.Handle
,
807 &gEfiFormBrowserExProtocolGuid
,
808 EFI_NATIVE_INTERFACE
,
809 &mPrivateData
.FormBrowserEx
811 ASSERT_EFI_ERROR (Status
);
813 InitializeDisplayFormData ();
815 Status
= gBS
->LocateProtocol (
816 &gEdkiiFormDisplayEngineProtocolGuid
,
818 (VOID
**) &mFormDisplay
821 if (EFI_ERROR (Status
)) {
822 EfiCreateProtocolNotifyEvent (
823 &gEdkiiFormDisplayEngineProtocolGuid
,
836 Create a new string in HII Package List.
838 @param String The String to be added
839 @param HiiHandle The package list in the HII database to insert the
842 @return The output string.
848 IN EFI_HII_HANDLE HiiHandle
851 EFI_STRING_ID StringId
;
853 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
854 ASSERT (StringId
!= 0);
861 Delete a string from HII Package List.
863 @param StringId Id of the string in HII database.
864 @param HiiHandle The HII package list handle.
866 @retval EFI_SUCCESS The string was deleted successfully.
871 IN EFI_STRING_ID StringId
,
872 IN EFI_HII_HANDLE HiiHandle
877 NullChar
= CHAR_NULL
;
878 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
884 Get the string based on the StringId and HII Package List Handle.
886 @param Token The String's ID.
887 @param HiiHandle The package list in the HII database to search for
888 the specified string.
890 @return The output string.
895 IN EFI_STRING_ID Token
,
896 IN EFI_HII_HANDLE HiiHandle
901 if (HiiHandle
== NULL
) {
905 String
= HiiGetString (HiiHandle
, Token
, NULL
);
906 if (String
== NULL
) {
907 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
908 ASSERT (String
!= NULL
);
910 return (CHAR16
*) String
;
915 Allocate new memory and then copy the Unicode string Source to Destination.
917 @param Dest Location to copy string
918 @param Src String to copy
923 IN OUT CHAR16
**Dest
,
930 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
931 ASSERT (*Dest
!= NULL
);
936 Allocate new memory and concatinate Source on the end of Destination.
938 @param Dest String to added to the end of.
939 @param Src String to concatinate.
944 IN OUT CHAR16
**Dest
,
952 NewStringCpy (Dest
, Src
);
956 TmpSize
= StrSize (*Dest
);
957 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
958 ASSERT (NewString
!= NULL
);
960 StrCpy (NewString
, *Dest
);
961 StrCat (NewString
, Src
);
968 Get Value for given Name from a NameValue Storage.
970 @param Storage The NameValue Storage.
971 @param Name The Name.
972 @param Value The retured Value.
973 @param GetValueFrom Where to get source value, from EditValue or Value.
975 @retval EFI_SUCCESS Value found for given Name.
976 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
981 IN BROWSER_STORAGE
*Storage
,
983 IN OUT CHAR16
**Value
,
984 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
988 NAME_VALUE_NODE
*Node
;
990 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
991 return EFI_INVALID_PARAMETER
;
996 Link
= GetFirstNode (&Storage
->NameValueListHead
);
997 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
998 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1000 if (StrCmp (Name
, Node
->Name
) == 0) {
1001 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1002 NewStringCpy (Value
, Node
->EditValue
);
1004 NewStringCpy (Value
, Node
->Value
);
1009 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1012 return EFI_NOT_FOUND
;
1017 Set Value of given Name in a NameValue Storage.
1019 @param Storage The NameValue Storage.
1020 @param Name The Name.
1021 @param Value The Value to set.
1022 @param SetValueTo Whether update editValue or Value.
1023 @param ReturnNode The node use the input name.
1025 @retval EFI_SUCCESS Value found for given Name.
1026 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1031 IN BROWSER_STORAGE
*Storage
,
1034 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
,
1035 OUT NAME_VALUE_NODE
**ReturnNode
1039 NAME_VALUE_NODE
*Node
;
1042 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
1043 return EFI_INVALID_PARAMETER
;
1046 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1047 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1048 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1050 if (StrCmp (Name
, Node
->Name
) == 0) {
1051 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1052 Buffer
= Node
->EditValue
;
1054 Buffer
= Node
->Value
;
1056 if (Buffer
!= NULL
) {
1059 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
1060 ASSERT (Buffer
!= NULL
);
1061 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1062 Node
->EditValue
= Buffer
;
1064 Node
->Value
= Buffer
;
1067 if (ReturnNode
!= NULL
) {
1074 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1077 return EFI_NOT_FOUND
;
1082 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
1084 @param Storage The Storage to be conveted.
1085 @param ConfigResp The returned <ConfigResp>.
1086 @param ConfigRequest The ConfigRequest string.
1087 @param GetEditBuf Get the data from editbuffer or buffer.
1089 @retval EFI_SUCCESS Convert success.
1090 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1094 StorageToConfigResp (
1095 IN BROWSER_STORAGE
*Storage
,
1096 IN CHAR16
**ConfigResp
,
1097 IN CHAR16
*ConfigRequest
,
1098 IN BOOLEAN GetEditBuf
1102 EFI_STRING Progress
;
1104 NAME_VALUE_NODE
*Node
;
1107 Status
= EFI_SUCCESS
;
1109 switch (Storage
->Type
) {
1110 case EFI_HII_VARSTORE_BUFFER
:
1111 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1112 SourceBuf
= GetEditBuf
? Storage
->EditBuffer
: Storage
->Buffer
;
1113 Status
= mHiiConfigRouting
->BlockToConfig (
1123 case EFI_HII_VARSTORE_NAME_VALUE
:
1125 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1127 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1128 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1129 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1131 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1132 NewStringCat (ConfigResp
, L
"&");
1133 NewStringCat (ConfigResp
, Node
->Name
);
1134 NewStringCat (ConfigResp
, L
"=");
1136 NewStringCat (ConfigResp
, Node
->EditValue
);
1138 NewStringCat (ConfigResp
, Node
->Value
);
1141 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1145 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1147 Status
= EFI_INVALID_PARAMETER
;
1156 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1158 @param Storage The Storage to receive the settings.
1159 @param ConfigResp The <ConfigResp> to be converted.
1161 @retval EFI_SUCCESS Convert success.
1162 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1166 ConfigRespToStorage (
1167 IN BROWSER_STORAGE
*Storage
,
1168 IN CHAR16
*ConfigResp
1172 EFI_STRING Progress
;
1178 Status
= EFI_SUCCESS
;
1180 switch (Storage
->Type
) {
1181 case EFI_HII_VARSTORE_BUFFER
:
1182 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1183 BufferSize
= Storage
->Size
;
1184 Status
= mHiiConfigRouting
->ConfigToBlock (
1187 Storage
->EditBuffer
,
1193 case EFI_HII_VARSTORE_NAME_VALUE
:
1194 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1195 if (StrPtr
== NULL
) {
1198 StrPtr
= StrStr (ConfigResp
, L
"&");
1199 while (StrPtr
!= NULL
) {
1203 StrPtr
= StrPtr
+ 1;
1205 StrPtr
= StrStr (StrPtr
, L
"=");
1206 if (StrPtr
== NULL
) {
1214 StrPtr
= StrPtr
+ 1;
1216 StrPtr
= StrStr (StrPtr
, L
"&");
1217 if (StrPtr
!= NULL
) {
1220 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
, NULL
);
1224 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1226 Status
= EFI_INVALID_PARAMETER
;
1235 Get Question's current Value.
1237 @param FormSet FormSet data structure.
1238 @param Form Form data structure.
1239 @param Question Question to be initialized.
1240 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1242 @retval EFI_SUCCESS The function completed successfully.
1247 IN FORM_BROWSER_FORMSET
*FormSet
,
1248 IN FORM_BROWSER_FORM
*Form
,
1249 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1250 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1259 BROWSER_STORAGE
*Storage
;
1260 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1261 CHAR16
*ConfigRequest
;
1269 BOOLEAN IsBufferStorage
;
1275 Status
= EFI_SUCCESS
;
1279 if (GetValueFrom
>= GetSetValueWithMax
) {
1280 return EFI_INVALID_PARAMETER
;
1284 // Question value is provided by an Expression, evaluate it
1286 if (Question
->ValueExpression
!= NULL
) {
1287 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1288 if (!EFI_ERROR (Status
)) {
1289 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1290 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1291 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1292 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1293 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1295 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1296 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1298 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1300 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1301 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1307 // Get question value by read expression.
1309 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1310 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1311 if (!EFI_ERROR (Status
) &&
1312 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1314 // Only update question value to the valid result.
1316 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1317 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1318 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1319 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1320 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1322 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1323 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1325 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1327 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1328 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1334 // Question value is provided by RTC
1336 Storage
= Question
->Storage
;
1337 QuestionValue
= &Question
->HiiValue
.Value
;
1338 if (Storage
== NULL
) {
1340 // It's a Question without storage, or RTC date/time
1342 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1344 // Date and time define the same Flags bit
1346 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1347 case QF_DATE_STORAGE_TIME
:
1348 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1351 case QF_DATE_STORAGE_WAKEUP
:
1352 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1355 case QF_DATE_STORAGE_NORMAL
:
1358 // For date/time without storage
1363 if (EFI_ERROR (Status
)) {
1367 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1368 QuestionValue
->date
.Year
= EfiTime
.Year
;
1369 QuestionValue
->date
.Month
= EfiTime
.Month
;
1370 QuestionValue
->date
.Day
= EfiTime
.Day
;
1372 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1373 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1374 QuestionValue
->time
.Second
= EfiTime
.Second
;
1382 // Question value is provided by EFI variable
1384 StorageWidth
= Question
->StorageWidth
;
1385 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1386 if (Question
->BufferValue
!= NULL
) {
1387 Dst
= Question
->BufferValue
;
1389 Dst
= (UINT8
*) QuestionValue
;
1392 Status
= gRT
->GetVariable (
1393 Question
->VariableName
,
1400 // Always return success, even this EFI variable doesn't exist
1406 // Question Value is provided by Buffer Storage or NameValue Storage
1408 if (Question
->BufferValue
!= NULL
) {
1410 // This Question is password or orderedlist
1412 Dst
= Question
->BufferValue
;
1415 // Other type of Questions
1417 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1420 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1421 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1422 IsBufferStorage
= TRUE
;
1424 IsBufferStorage
= FALSE
;
1426 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1427 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1428 if (IsBufferStorage
) {
1429 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1431 // Copy from storage Edit buffer
1433 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1436 // Copy from storage Edit buffer
1438 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1442 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1443 if (EFI_ERROR (Status
)) {
1447 ASSERT (Value
!= NULL
);
1448 LengthStr
= StrLen (Value
);
1449 Status
= EFI_SUCCESS
;
1452 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1453 // Add string tail char L'\0' into Length
1455 Length
= StorageWidth
+ sizeof (CHAR16
);
1456 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1457 Status
= EFI_BUFFER_TOO_SMALL
;
1459 StringPtr
= (CHAR16
*) Dst
;
1460 ZeroMem (TemStr
, sizeof (TemStr
));
1461 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1462 StrnCpy (TemStr
, Value
+ Index
, 4);
1463 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1466 // Add tailing L'\0' character
1468 StringPtr
[Index
/4] = L
'\0';
1471 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1472 Status
= EFI_BUFFER_TOO_SMALL
;
1474 ZeroMem (TemStr
, sizeof (TemStr
));
1475 for (Index
= 0; Index
< LengthStr
; Index
++) {
1476 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1477 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1478 if ((Index
& 1) == 0) {
1479 Dst
[Index
/2] = DigitUint8
;
1481 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1490 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1492 // Request current settings from Configuration Driver
1494 if (FormSet
->ConfigAccess
== NULL
) {
1495 return EFI_NOT_FOUND
;
1499 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1500 // <ConfigHdr> + "&" + <VariableName>
1502 if (IsBufferStorage
) {
1503 Length
= StrLen (Storage
->ConfigHdr
);
1504 Length
+= StrLen (Question
->BlockName
);
1506 Length
= StrLen (Storage
->ConfigHdr
);
1507 Length
+= StrLen (Question
->VariableName
) + 1;
1509 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1510 ASSERT (ConfigRequest
!= NULL
);
1512 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1513 if (IsBufferStorage
) {
1514 StrCat (ConfigRequest
, Question
->BlockName
);
1516 StrCat (ConfigRequest
, L
"&");
1517 StrCat (ConfigRequest
, Question
->VariableName
);
1520 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1521 FormSet
->ConfigAccess
,
1526 FreePool (ConfigRequest
);
1527 if (EFI_ERROR (Status
)) {
1532 // Skip <ConfigRequest>
1534 if (IsBufferStorage
) {
1535 Value
= StrStr (Result
, L
"&VALUE");
1536 if (Value
== NULL
) {
1538 return EFI_NOT_FOUND
;
1545 Value
= Result
+ Length
;
1547 if (*Value
!= '=') {
1549 return EFI_NOT_FOUND
;
1552 // Skip '=', point to value
1557 // Suppress <AltResp> if any
1560 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1565 LengthStr
= StrLen (Value
);
1566 Status
= EFI_SUCCESS
;
1567 if (!IsBufferStorage
&& IsString
) {
1569 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1570 // Add string tail char L'\0' into Length
1572 Length
= StorageWidth
+ sizeof (CHAR16
);
1573 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1574 Status
= EFI_BUFFER_TOO_SMALL
;
1576 StringPtr
= (CHAR16
*) Dst
;
1577 ZeroMem (TemStr
, sizeof (TemStr
));
1578 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1579 StrnCpy (TemStr
, Value
+ Index
, 4);
1580 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1583 // Add tailing L'\0' character
1585 StringPtr
[Index
/4] = L
'\0';
1588 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1589 Status
= EFI_BUFFER_TOO_SMALL
;
1591 ZeroMem (TemStr
, sizeof (TemStr
));
1592 for (Index
= 0; Index
< LengthStr
; Index
++) {
1593 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1594 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1595 if ((Index
& 1) == 0) {
1596 Dst
[Index
/2] = DigitUint8
;
1598 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1604 if (EFI_ERROR (Status
)) {
1608 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1610 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1611 if (TemBuffer
== NULL
) {
1612 Status
= EFI_OUT_OF_RESOURCES
;
1615 Length
= Storage
->Size
;
1616 Status
= gRT
->GetVariable (
1623 if (EFI_ERROR (Status
)) {
1624 FreePool (TemBuffer
);
1628 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1630 FreePool (TemBuffer
);
1634 // Synchronize Edit Buffer
1636 if (IsBufferStorage
) {
1637 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1639 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
, NULL
);
1642 if (Result
!= NULL
) {
1652 Save Question Value to edit copy(cached) or Storage(uncached).
1654 @param FormSet FormSet data structure.
1655 @param Form Form data structure.
1656 @param Question Pointer to the Question.
1657 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1659 @retval EFI_SUCCESS The function completed successfully.
1664 IN FORM_BROWSER_FORMSET
*FormSet
,
1665 IN FORM_BROWSER_FORM
*Form
,
1666 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1667 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1677 BROWSER_STORAGE
*Storage
;
1678 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1683 BOOLEAN IsBufferStorage
;
1689 NAME_VALUE_NODE
*Node
;
1691 Status
= EFI_SUCCESS
;
1694 if (SetValueTo
>= GetSetValueWithMax
) {
1695 return EFI_INVALID_PARAMETER
;
1699 // If Question value is provided by an Expression, then it is read only
1701 if (Question
->ValueExpression
!= NULL
) {
1706 // Before set question value, evaluate its write expression.
1708 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1709 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1710 if (EFI_ERROR (Status
)) {
1716 // Question value is provided by RTC
1718 Storage
= Question
->Storage
;
1719 QuestionValue
= &Question
->HiiValue
.Value
;
1720 if (Storage
== NULL
) {
1722 // It's a Question without storage, or RTC date/time
1724 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1726 // Date and time define the same Flags bit
1728 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1729 case QF_DATE_STORAGE_TIME
:
1730 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1733 case QF_DATE_STORAGE_WAKEUP
:
1734 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1737 case QF_DATE_STORAGE_NORMAL
:
1740 // For date/time without storage
1745 if (EFI_ERROR (Status
)) {
1749 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1750 EfiTime
.Year
= QuestionValue
->date
.Year
;
1751 EfiTime
.Month
= QuestionValue
->date
.Month
;
1752 EfiTime
.Day
= QuestionValue
->date
.Day
;
1754 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1755 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1756 EfiTime
.Second
= QuestionValue
->time
.Second
;
1759 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1760 Status
= gRT
->SetTime (&EfiTime
);
1762 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1770 // Question value is provided by EFI variable
1772 StorageWidth
= Question
->StorageWidth
;
1773 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1774 if (Question
->BufferValue
!= NULL
) {
1775 Src
= Question
->BufferValue
;
1777 Src
= (UINT8
*) QuestionValue
;
1780 Status
= gRT
->SetVariable (
1781 Question
->VariableName
,
1783 Storage
->Attributes
,
1791 // Question Value is provided by Buffer Storage or NameValue Storage
1793 if (Question
->BufferValue
!= NULL
) {
1794 Src
= Question
->BufferValue
;
1796 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1799 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1800 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1801 IsBufferStorage
= TRUE
;
1803 IsBufferStorage
= FALSE
;
1805 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1807 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1808 if (IsBufferStorage
) {
1809 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1811 // Copy to storage edit buffer
1813 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1814 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1816 // Copy to storage edit buffer
1818 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1821 // Check whether question value has been changed.
1823 if (CompareMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
) != 0) {
1824 Question
->ValueChanged
= TRUE
;
1826 Question
->ValueChanged
= FALSE
;
1831 // Allocate enough string buffer.
1834 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1835 Value
= AllocateZeroPool (BufferLen
);
1836 ASSERT (Value
!= NULL
);
1838 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1840 TemName
= (CHAR16
*) Src
;
1842 for (; *TemName
!= L
'\0'; TemName
++) {
1843 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1846 BufferLen
= StorageWidth
* 2 + 1;
1847 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1848 ASSERT (Value
!= NULL
);
1850 // Convert Buffer to Hex String
1852 TemBuffer
= Src
+ StorageWidth
- 1;
1854 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1855 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1859 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
, &Node
);
1861 if (EFI_ERROR (Status
)) {
1865 // Check whether question value has been changed.
1867 if (StrCmp (Node
->Value
, Node
->EditValue
) != 0) {
1868 Question
->ValueChanged
= TRUE
;
1870 Question
->ValueChanged
= FALSE
;
1873 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1874 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1876 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1877 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1879 if (IsBufferStorage
) {
1880 Length
= StrLen (Question
->BlockName
) + 7;
1882 Length
= StrLen (Question
->VariableName
) + 2;
1884 if (!IsBufferStorage
&& IsString
) {
1885 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1887 Length
+= (StorageWidth
* 2);
1889 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1890 ASSERT (ConfigResp
!= NULL
);
1892 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1893 if (IsBufferStorage
) {
1894 StrCat (ConfigResp
, Question
->BlockName
);
1895 StrCat (ConfigResp
, L
"&VALUE=");
1897 StrCat (ConfigResp
, L
"&");
1898 StrCat (ConfigResp
, Question
->VariableName
);
1899 StrCat (ConfigResp
, L
"=");
1902 Value
= ConfigResp
+ StrLen (ConfigResp
);
1904 if (!IsBufferStorage
&& IsString
) {
1906 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1908 TemName
= (CHAR16
*) Src
;
1910 for (; *TemName
!= L
'\0'; TemName
++) {
1911 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1915 // Convert Buffer to Hex String
1917 TemBuffer
= Src
+ StorageWidth
- 1;
1919 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1920 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1925 // Convert to lower char.
1927 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1928 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1929 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1934 // Submit Question Value to Configuration Driver
1936 if (FormSet
->ConfigAccess
!= NULL
) {
1937 Status
= FormSet
->ConfigAccess
->RouteConfig (
1938 FormSet
->ConfigAccess
,
1942 if (EFI_ERROR (Status
)) {
1943 FreePool (ConfigResp
);
1947 FreePool (ConfigResp
);
1949 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1951 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1952 if (TemBuffer
== NULL
) {
1953 Status
= EFI_OUT_OF_RESOURCES
;
1956 Length
= Storage
->Size
;
1957 Status
= gRT
->GetVariable (
1965 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1967 Status
= gRT
->SetVariable (
1970 Storage
->Attributes
,
1974 FreePool (TemBuffer
);
1975 if (EFI_ERROR (Status
)){
1980 // Sync storage, from editbuffer to buffer.
1982 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1990 Perform nosubmitif check for a Form.
1992 @param FormSet FormSet data structure.
1993 @param Form Form data structure.
1994 @param Question The Question to be validated.
1995 @param Type Validation type: NoSubmit
1997 @retval EFI_SUCCESS Form validation pass.
1998 @retval other Form validation failed.
2003 IN FORM_BROWSER_FORMSET
*FormSet
,
2004 IN FORM_BROWSER_FORM
*Form
,
2005 IN FORM_BROWSER_STATEMENT
*Question
,
2011 LIST_ENTRY
*ListHead
;
2013 FORM_EXPRESSION
*Expression
;
2015 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
2016 ListHead
= &Question
->NoSubmitListHead
;
2018 return EFI_UNSUPPORTED
;
2021 Link
= GetFirstNode (ListHead
);
2022 while (!IsNull (ListHead
, Link
)) {
2023 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
2026 // Evaluate the expression
2028 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
2029 if (EFI_ERROR (Status
)) {
2033 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
2035 // Condition meet, show up error message
2037 if (Expression
->Error
!= 0) {
2038 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
2039 if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
2040 gBrowserStatus
= BROWSER_NO_SUBMIT_IF
;
2045 return EFI_NOT_READY
;
2048 Link
= GetNextNode (ListHead
, Link
);
2056 Perform NoSubmit check for each Form in FormSet.
2058 @param FormSet FormSet data structure.
2059 @param CurrentForm Current input form data structure.
2061 @retval EFI_SUCCESS Form validation pass.
2062 @retval other Form validation failed.
2067 IN FORM_BROWSER_FORMSET
*FormSet
,
2068 IN FORM_BROWSER_FORM
*CurrentForm
2073 FORM_BROWSER_STATEMENT
*Question
;
2074 FORM_BROWSER_FORM
*Form
;
2075 LIST_ENTRY
*LinkForm
;
2077 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
2078 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
2079 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
2080 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
2082 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
2086 Link
= GetFirstNode (&Form
->StatementListHead
);
2087 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2088 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2090 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
2091 if (EFI_ERROR (Status
)) {
2095 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2103 Fill storage's edit copy with settings requested from Configuration Driver.
2105 @param FormSet FormSet data structure.
2106 @param Storage The storage which need to sync.
2107 @param ConfigRequest The config request string which used to sync storage.
2108 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
2109 editbuffer to buffer
2110 if TRUE, copy the editbuffer to the buffer.
2111 if FALSE, copy the buffer to the editbuffer.
2113 @retval EFI_SUCCESS The function completed successfully.
2117 SynchronizeStorage (
2118 IN FORM_BROWSER_FORMSET
*FormSet
,
2119 OUT BROWSER_STORAGE
*Storage
,
2120 IN CHAR16
*ConfigRequest
,
2121 IN BOOLEAN SyncOrRestore
2125 EFI_STRING Progress
;
2129 NAME_VALUE_NODE
*Node
;
2133 Status
= EFI_SUCCESS
;
2136 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2137 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2138 BufferSize
= Storage
->Size
;
2140 if (SyncOrRestore
) {
2141 Src
= Storage
->EditBuffer
;
2142 Dst
= Storage
->Buffer
;
2144 Src
= Storage
->Buffer
;
2145 Dst
= Storage
->EditBuffer
;
2148 if (ConfigRequest
!= NULL
) {
2149 Status
= mHiiConfigRouting
->BlockToConfig(
2157 if (EFI_ERROR (Status
)) {
2161 Status
= mHiiConfigRouting
->ConfigToBlock (
2168 if (Result
!= NULL
) {
2172 CopyMem (Dst
, Src
, BufferSize
);
2174 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2175 Link
= GetFirstNode (&Storage
->NameValueListHead
);
2176 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
2177 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2179 if ((ConfigRequest
!= NULL
&& StrStr (ConfigRequest
, Node
->Name
) != NULL
) ||
2180 (ConfigRequest
== NULL
)) {
2181 if (SyncOrRestore
) {
2182 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2184 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2188 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
2196 When discard the question value, call the callback function with Changed type
2197 to inform the hii driver.
2199 @param FormSet FormSet data structure.
2200 @param Form Form data structure.
2204 SendDiscardInfoToDriver (
2205 IN FORM_BROWSER_FORMSET
*FormSet
,
2206 IN FORM_BROWSER_FORM
*Form
2210 FORM_BROWSER_STATEMENT
*Question
;
2211 EFI_IFR_TYPE_VALUE
*TypeValue
;
2212 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2214 Link
= GetFirstNode (&Form
->StatementListHead
);
2215 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2216 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2217 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2219 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2223 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2227 if (!Question
->ValueChanged
) {
2231 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2232 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2234 TypeValue
= &Question
->HiiValue
.Value
;
2237 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2238 FormSet
->ConfigAccess
->Callback (
2239 FormSet
->ConfigAccess
,
2240 EFI_BROWSER_ACTION_CHANGED
,
2241 Question
->QuestionId
,
2242 Question
->HiiValue
.Type
,
2250 Validate the FormSet. If the formset is not validate, remove it from the list.
2252 @param FormSet The input FormSet which need to validate.
2254 @retval TRUE The handle is validate.
2255 @retval FALSE The handle is invalidate.
2260 FORM_BROWSER_FORMSET
*FormSet
2263 EFI_HII_HANDLE
*HiiHandles
;
2267 ASSERT (FormSet
!= NULL
);
2270 // Get all the Hii handles
2272 HiiHandles
= HiiGetHiiHandles (NULL
);
2273 ASSERT (HiiHandles
!= NULL
);
2276 // Search for formset of each class type
2278 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2279 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2286 CleanBrowserStorage(FormSet
);
2287 RemoveEntryList (&FormSet
->Link
);
2288 DestroyFormSet (FormSet
);
2291 FreePool (HiiHandles
);
2296 Check whether need to enable the reset flag in form level.
2297 Also clean all ValueChanged flag in question.
2299 @param SetFlag Whether need to set the Reset Flag.
2300 @param Form Form data structure.
2306 IN FORM_BROWSER_FORM
*Form
2310 FORM_BROWSER_STATEMENT
*Question
;
2314 Link
= GetFirstNode (&Form
->StatementListHead
);
2315 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2316 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2318 if (SetFlag
&& Question
->ValueChanged
&& ((Question
->QuestionFlags
& EFI_IFR_FLAG_RESET_REQUIRED
) != 0)) {
2319 gResetRequired
= TRUE
;
2322 if (Question
->ValueChanged
) {
2323 Question
->ValueChanged
= FALSE
;
2326 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2331 Check whether need to enable the reset flag.
2332 Also clean ValueChanged flag for all statements.
2334 Form level or formset level, only one.
2336 @param SetFlag Whether need to set the Reset Flag.
2337 @param FormSet FormSet data structure.
2338 @param Form Form data structure.
2342 ValueChangeResetFlagUpdate (
2344 IN FORM_BROWSER_FORMSET
*FormSet
,
2345 IN FORM_BROWSER_FORM
*Form
2348 FORM_BROWSER_FORM
*CurrentForm
;
2352 // Form != NULL means only check form level.
2355 UpdateFlagForForm(SetFlag
, Form
);
2359 Link
= GetFirstNode (&FormSet
->FormListHead
);
2360 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2361 CurrentForm
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2362 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2364 UpdateFlagForForm(SetFlag
, CurrentForm
);
2369 Discard data based on the input setting scope (Form, FormSet or System).
2371 @param FormSet FormSet data structure.
2372 @param Form Form data structure.
2373 @param SettingScope Setting Scope for Discard action.
2375 @retval EFI_SUCCESS The function completed successfully.
2376 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2381 IN FORM_BROWSER_FORMSET
*FormSet
,
2382 IN FORM_BROWSER_FORM
*Form
,
2383 IN BROWSER_SETTING_SCOPE SettingScope
2387 FORMSET_STORAGE
*Storage
;
2388 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2389 FORM_BROWSER_FORMSET
*LocalFormSet
;
2390 FORM_BROWSER_FORMSET
*OldFormSet
;
2393 // Check the supported setting level.
2395 if (SettingScope
>= MaxLevel
) {
2396 return EFI_UNSUPPORTED
;
2399 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2401 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2402 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2403 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2404 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2406 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2411 // Skip if there is no RequestElement
2413 if (ConfigInfo
->ElementCount
== 0) {
2418 // Prepare <ConfigResp>
2420 SynchronizeStorage(FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, FALSE
);
2423 // Call callback with Changed type to inform the driver.
2425 SendDiscardInfoToDriver (FormSet
, Form
);
2428 ValueChangeResetFlagUpdate (FALSE
, NULL
, Form
);
2429 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2432 // Discard Buffer storage or Name/Value storage
2434 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2435 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2436 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2437 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2439 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2444 // Skip if there is no RequestElement
2446 if (Storage
->ElementCount
== 0) {
2450 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, FALSE
);
2453 Link
= GetFirstNode (&FormSet
->FormListHead
);
2454 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2455 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2456 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2459 // Call callback with Changed type to inform the driver.
2461 SendDiscardInfoToDriver (FormSet
, Form
);
2464 ValueChangeResetFlagUpdate(FALSE
, FormSet
, NULL
);
2465 } else if (SettingScope
== SystemLevel
) {
2467 // System Level Discard.
2469 OldFormSet
= mSystemLevelFormSet
;
2472 // Discard changed value for each FormSet in the maintain list.
2474 Link
= GetFirstNode (&gBrowserFormSetList
);
2475 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2476 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2477 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2478 if (!ValidateFormSet(LocalFormSet
)) {
2482 mSystemLevelFormSet
= LocalFormSet
;
2484 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2485 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2487 // Remove maintain backup list after discard except for the current using FormSet.
2489 CleanBrowserStorage(LocalFormSet
);
2490 RemoveEntryList (&LocalFormSet
->Link
);
2491 DestroyFormSet (LocalFormSet
);
2495 mSystemLevelFormSet
= OldFormSet
;
2502 Submit data based on the input Setting level (Form, FormSet or System).
2504 @param FormSet FormSet data structure.
2505 @param Form Form data structure.
2506 @param SettingScope Setting Scope for Submit action.
2508 @retval EFI_SUCCESS The function completed successfully.
2509 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2514 IN FORM_BROWSER_FORMSET
*FormSet
,
2515 IN FORM_BROWSER_FORM
*Form
,
2516 IN BROWSER_SETTING_SCOPE SettingScope
2521 EFI_STRING ConfigResp
;
2522 EFI_STRING Progress
;
2523 BROWSER_STORAGE
*Storage
;
2524 FORMSET_STORAGE
*FormSetStorage
;
2527 FORM_BROWSER_FORMSET
*LocalFormSet
;
2528 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2531 // Check the supported setting level.
2533 if (SettingScope
>= MaxLevel
) {
2534 return EFI_UNSUPPORTED
;
2538 // Validate the Form by NoSubmit check
2540 Status
= EFI_SUCCESS
;
2541 if (SettingScope
== FormLevel
) {
2542 Status
= NoSubmitCheck (FormSet
, Form
);
2543 } else if (SettingScope
== FormSetLevel
) {
2544 Status
= NoSubmitCheck (FormSet
, NULL
);
2546 if (EFI_ERROR (Status
)) {
2550 if (SettingScope
== FormLevel
&& IsNvUpdateRequiredForForm (Form
)) {
2552 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2553 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2554 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2555 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2557 Storage
= ConfigInfo
->Storage
;
2558 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2563 // Skip if there is no RequestElement
2565 if (ConfigInfo
->ElementCount
== 0) {
2570 // 1. Prepare <ConfigResp>
2572 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
, TRUE
);
2573 if (EFI_ERROR (Status
)) {
2578 // 2. Set value to hii driver or efi variable.
2580 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2581 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2583 // Send <ConfigResp> to Configuration Driver
2585 if (FormSet
->ConfigAccess
!= NULL
) {
2586 Status
= FormSet
->ConfigAccess
->RouteConfig (
2587 FormSet
->ConfigAccess
,
2591 if (EFI_ERROR (Status
)) {
2592 FreePool (ConfigResp
);
2596 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2598 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2599 if (TmpBuf
== NULL
) {
2600 Status
= EFI_OUT_OF_RESOURCES
;
2604 BufferSize
= Storage
->Size
;
2605 Status
= gRT
->GetVariable (
2612 if (EFI_ERROR (Status
)) {
2614 FreePool (ConfigResp
);
2617 ASSERT (BufferSize
== Storage
->Size
);
2618 Status
= mHiiConfigRouting
->ConfigToBlock (
2625 if (EFI_ERROR (Status
)) {
2627 FreePool (ConfigResp
);
2631 Status
= gRT
->SetVariable (
2634 Storage
->Attributes
,
2639 if (EFI_ERROR (Status
)) {
2640 FreePool (ConfigResp
);
2644 FreePool (ConfigResp
);
2646 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2648 SynchronizeStorage (FormSet
, ConfigInfo
->Storage
, ConfigInfo
->ConfigRequest
, TRUE
);
2652 // 4. Update the NV flag.
2654 ValueChangeResetFlagUpdate(TRUE
, NULL
, Form
);
2655 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequiredForFormSet (FormSet
)) {
2657 // Submit Buffer storage or Name/Value storage
2659 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2660 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2661 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2662 Storage
= FormSetStorage
->BrowserStorage
;
2663 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2665 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2670 // Skip if there is no RequestElement
2672 if (FormSetStorage
->ElementCount
== 0) {
2677 // 1. Prepare <ConfigResp>
2679 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
, TRUE
);
2680 if (EFI_ERROR (Status
)) {
2684 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2685 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2688 // 2. Send <ConfigResp> to Configuration Driver
2690 if (FormSet
->ConfigAccess
!= NULL
) {
2691 Status
= FormSet
->ConfigAccess
->RouteConfig (
2692 FormSet
->ConfigAccess
,
2696 if (EFI_ERROR (Status
)) {
2697 FreePool (ConfigResp
);
2701 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2703 // 1&2. Set the edit data to the variable.
2706 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2707 if (TmpBuf
== NULL
) {
2708 Status
= EFI_OUT_OF_RESOURCES
;
2711 BufferSize
= Storage
->Size
;
2712 Status
= gRT
->GetVariable (
2719 ASSERT (BufferSize
== Storage
->Size
);
2720 Status
= mHiiConfigRouting
->ConfigToBlock (
2727 if (EFI_ERROR (Status
)) {
2729 FreePool (ConfigResp
);
2733 Status
= gRT
->SetVariable (
2736 Storage
->Attributes
,
2740 if (EFI_ERROR (Status
)) {
2742 FreePool (ConfigResp
);
2747 FreePool (ConfigResp
);
2749 // 3. Config success, update storage shadow Buffer
2751 SynchronizeStorage (FormSet
, Storage
, FormSetStorage
->ConfigRequest
, TRUE
);
2755 // 4. Update the NV flag.
2757 ValueChangeResetFlagUpdate(TRUE
, FormSet
, NULL
);
2758 } else if (SettingScope
== SystemLevel
) {
2760 // System Level Save.
2764 // Save changed value for each FormSet in the maintain list.
2766 Link
= GetFirstNode (&gBrowserFormSetList
);
2767 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2768 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2769 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2770 if (!ValidateFormSet(LocalFormSet
)) {
2773 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2774 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2776 // Remove maintain backup list after save except for the current using FormSet.
2778 CleanBrowserStorage(LocalFormSet
);
2779 RemoveEntryList (&LocalFormSet
->Link
);
2780 DestroyFormSet (LocalFormSet
);
2789 Get Question default value from AltCfg string.
2791 @param FormSet The form set.
2792 @param Question The question.
2793 @param DefaultId The default Id.
2795 @retval EFI_SUCCESS Question is reset to default value.
2799 GetDefaultValueFromAltCfg (
2800 IN FORM_BROWSER_FORMSET
*FormSet
,
2801 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2805 BOOLEAN IsBufferStorage
;
2808 BROWSER_STORAGE
*Storage
;
2809 CHAR16
*ConfigRequest
;
2822 Status
= EFI_NOT_FOUND
;
2825 ConfigRequest
= NULL
;
2829 Storage
= Question
->Storage
;
2831 if ((Storage
== NULL
) ||
2832 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2833 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2838 // Question Value is provided by Buffer Storage or NameValue Storage
2840 if (Question
->BufferValue
!= NULL
) {
2842 // This Question is password or orderedlist
2844 Dst
= Question
->BufferValue
;
2847 // Other type of Questions
2849 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2852 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2853 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2856 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2857 // <ConfigHdr> + "&" + <VariableName>
2859 if (IsBufferStorage
) {
2860 Length
= StrLen (Storage
->ConfigHdr
);
2861 Length
+= StrLen (Question
->BlockName
);
2863 Length
= StrLen (Storage
->ConfigHdr
);
2864 Length
+= StrLen (Question
->VariableName
) + 1;
2866 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2867 ASSERT (ConfigRequest
!= NULL
);
2869 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2870 if (IsBufferStorage
) {
2871 StrCat (ConfigRequest
, Question
->BlockName
);
2873 StrCat (ConfigRequest
, L
"&");
2874 StrCat (ConfigRequest
, Question
->VariableName
);
2877 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2878 FormSet
->ConfigAccess
,
2883 if (EFI_ERROR (Status
)) {
2888 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2889 // Get the default configuration string according to the default ID.
2891 Status
= mHiiConfigRouting
->GetAltConfig (
2897 &DefaultId
, // it can be NULL to get the current setting.
2902 // The required setting can't be found. So, it is not required to be validated and set.
2904 if (EFI_ERROR (Status
)) {
2909 // Skip <ConfigRequest>
2911 if (IsBufferStorage
) {
2912 Value
= StrStr (ConfigResp
, L
"&VALUE");
2913 ASSERT (Value
!= NULL
);
2919 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2920 ASSERT (Value
!= NULL
);
2922 Value
= Value
+ StrLen (Question
->VariableName
);
2924 if (*Value
!= '=') {
2925 Status
= EFI_NOT_FOUND
;
2929 // Skip '=', point to value
2934 // Suppress <AltResp> if any
2937 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2942 LengthStr
= StrLen (Value
);
2943 if (!IsBufferStorage
&& IsString
) {
2944 StringPtr
= (CHAR16
*) Dst
;
2945 ZeroMem (TemStr
, sizeof (TemStr
));
2946 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2947 StrnCpy (TemStr
, Value
+ Index
, 4);
2948 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2951 // Add tailing L'\0' character
2953 StringPtr
[Index
/4] = L
'\0';
2955 ZeroMem (TemStr
, sizeof (TemStr
));
2956 for (Index
= 0; Index
< LengthStr
; Index
++) {
2957 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2958 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2959 if ((Index
& 1) == 0) {
2960 Dst
[Index
/2] = DigitUint8
;
2962 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2968 if (ConfigRequest
!= NULL
){
2969 FreePool (ConfigRequest
);
2972 if (ConfigResp
!= NULL
) {
2973 FreePool (ConfigResp
);
2976 if (Result
!= NULL
) {
2984 Get default Id value used for browser.
2986 @param DefaultId The default id value used by hii.
2988 @retval Browser used default value.
2992 GetDefaultIdForCallBack (
2996 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2997 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2998 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2999 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
3000 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
3001 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
3002 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
3003 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
3004 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
3005 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
3006 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
3007 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
3016 Return data element in an Array by its Index.
3018 @param Array The data array.
3019 @param Type Type of the data in this array.
3020 @param Index Zero based index for data in this array.
3022 @retval Value The data to be returned
3034 ASSERT (Array
!= NULL
);
3038 case EFI_IFR_TYPE_NUM_SIZE_8
:
3039 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
3042 case EFI_IFR_TYPE_NUM_SIZE_16
:
3043 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
3046 case EFI_IFR_TYPE_NUM_SIZE_32
:
3047 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
3050 case EFI_IFR_TYPE_NUM_SIZE_64
:
3051 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
3063 Set value of a data element in an Array by its Index.
3065 @param Array The data array.
3066 @param Type Type of the data in this array.
3067 @param Index Zero based index for data in this array.
3068 @param Value The value to be set.
3080 ASSERT (Array
!= NULL
);
3083 case EFI_IFR_TYPE_NUM_SIZE_8
:
3084 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
3087 case EFI_IFR_TYPE_NUM_SIZE_16
:
3088 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
3091 case EFI_IFR_TYPE_NUM_SIZE_32
:
3092 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
3095 case EFI_IFR_TYPE_NUM_SIZE_64
:
3096 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
3105 Search an Option of a Question by its value.
3107 @param Question The Question
3108 @param OptionValue Value for Option to be searched.
3110 @retval Pointer Pointer to the found Option.
3111 @retval NULL Option not found.
3116 IN FORM_BROWSER_STATEMENT
*Question
,
3117 IN EFI_HII_VALUE
*OptionValue
3121 QUESTION_OPTION
*Option
;
3124 Link
= GetFirstNode (&Question
->OptionListHead
);
3125 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3126 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3128 if ((CompareHiiValue (&Option
->Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3130 // Check the suppressif condition, only a valid option can be return.
3132 if ((Option
->SuppressExpression
== NULL
) ||
3133 ((EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) == ExpressFalse
))) {
3138 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3146 Reset Question to its default value.
3148 @param FormSet The form set.
3149 @param Form The form.
3150 @param Question The question.
3151 @param DefaultId The Class of the default.
3153 @retval EFI_SUCCESS Question is reset to default value.
3157 GetQuestionDefault (
3158 IN FORM_BROWSER_FORMSET
*FormSet
,
3159 IN FORM_BROWSER_FORM
*Form
,
3160 IN FORM_BROWSER_STATEMENT
*Question
,
3166 QUESTION_DEFAULT
*Default
;
3167 QUESTION_OPTION
*Option
;
3168 EFI_HII_VALUE
*HiiValue
;
3170 EFI_STRING StrValue
;
3171 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3172 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
3175 Status
= EFI_NOT_FOUND
;
3179 // Statement don't have storage, skip them
3181 if (Question
->QuestionId
== 0) {
3186 // There are Five ways to specify default value for a Question:
3187 // 1, use call back function (highest priority)
3188 // 2, use ExtractConfig function
3189 // 3, use nested EFI_IFR_DEFAULT
3190 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
3191 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
3193 HiiValue
= &Question
->HiiValue
;
3196 // Get Question defaut value from call back function.
3198 ConfigAccess
= FormSet
->ConfigAccess
;
3199 Action
= GetDefaultIdForCallBack (DefaultId
);
3200 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
3201 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
3202 Status
= ConfigAccess
->Callback (
3205 Question
->QuestionId
,
3210 if (!EFI_ERROR (Status
)) {
3216 // Get default value from altcfg string.
3218 if (ConfigAccess
!= NULL
) {
3219 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
3220 if (!EFI_ERROR (Status
)) {
3226 // EFI_IFR_DEFAULT has highest priority
3228 if (!IsListEmpty (&Question
->DefaultListHead
)) {
3229 Link
= GetFirstNode (&Question
->DefaultListHead
);
3230 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
3231 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
3233 if (Default
->DefaultId
== DefaultId
) {
3234 if (Default
->ValueExpression
!= NULL
) {
3236 // Default is provided by an Expression, evaluate it
3238 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
3239 if (EFI_ERROR (Status
)) {
3243 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
3244 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
3245 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
3246 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
3247 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
3249 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
3250 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
3252 FreePool (Default
->ValueExpression
->Result
.Buffer
);
3254 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
3255 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
3258 // Default value is embedded in EFI_IFR_DEFAULT
3260 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
3263 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
3264 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
3265 if (StrValue
== NULL
) {
3266 return EFI_NOT_FOUND
;
3268 if (Question
->StorageWidth
> StrSize (StrValue
)) {
3269 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
3271 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
3278 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3283 // EFI_ONE_OF_OPTION
3285 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3286 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3288 // OneOfOption could only provide Standard and Manufacturing default
3290 Link
= GetFirstNode (&Question
->OptionListHead
);
3291 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3292 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3293 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3295 if ((Option
->SuppressExpression
!= NULL
) &&
3296 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3300 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3301 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3303 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3312 // EFI_IFR_CHECKBOX - lowest priority
3314 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3315 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3317 // Checkbox could only provide Standard and Manufacturing default
3319 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3320 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3322 HiiValue
->Value
.b
= TRUE
;
3324 HiiValue
->Value
.b
= FALSE
;
3332 // For Questions without default
3334 Status
= EFI_NOT_FOUND
;
3335 switch (Question
->Operand
) {
3336 case EFI_IFR_NUMERIC_OP
:
3338 // Take minimum value as numeric default value
3340 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3341 HiiValue
->Value
.u64
= Question
->Minimum
;
3342 Status
= EFI_SUCCESS
;
3346 case EFI_IFR_ONE_OF_OP
:
3348 // Take first oneof option as oneof's default value
3350 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3351 Link
= GetFirstNode (&Question
->OptionListHead
);
3352 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3353 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3354 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3356 if ((Option
->SuppressExpression
!= NULL
) &&
3357 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3361 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3362 Status
= EFI_SUCCESS
;
3368 case EFI_IFR_ORDERED_LIST_OP
:
3370 // Take option sequence in IFR as ordered list's default value
3373 Link
= GetFirstNode (&Question
->OptionListHead
);
3374 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3375 Status
= EFI_SUCCESS
;
3376 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3377 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3379 if ((Option
->SuppressExpression
!= NULL
) &&
3380 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3384 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3387 if (Index
>= Question
->MaxContainers
) {
3402 Reset Questions to their initial value or default value in a Form, Formset or System.
3404 GetDefaultValueScope parameter decides which questions will reset
3405 to its default value.
3407 @param FormSet FormSet data structure.
3408 @param Form Form data structure.
3409 @param DefaultId The Class of the default.
3410 @param SettingScope Setting Scope for Default action.
3411 @param GetDefaultValueScope Get default value scope.
3412 @param Storage Get default value only for this storage.
3413 @param RetrieveValueFirst Whether call the retrieve call back to
3414 get the initial value before get default
3417 @retval EFI_SUCCESS The function completed successfully.
3418 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3423 IN FORM_BROWSER_FORMSET
*FormSet
,
3424 IN FORM_BROWSER_FORM
*Form
,
3425 IN UINT16 DefaultId
,
3426 IN BROWSER_SETTING_SCOPE SettingScope
,
3427 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3428 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3429 IN BOOLEAN RetrieveValueFirst
3433 LIST_ENTRY
*FormLink
;
3435 FORM_BROWSER_STATEMENT
*Question
;
3436 FORM_BROWSER_FORMSET
*LocalFormSet
;
3437 FORM_BROWSER_FORMSET
*OldFormSet
;
3439 Status
= EFI_SUCCESS
;
3442 // Check the supported setting level.
3444 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3445 return EFI_UNSUPPORTED
;
3448 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3449 return EFI_UNSUPPORTED
;
3452 if (SettingScope
== FormLevel
) {
3454 // Extract Form default
3456 Link
= GetFirstNode (&Form
->StatementListHead
);
3457 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3458 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3459 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3462 // If get default value only for this storage, check the storage first.
3464 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3469 // If get default value only for no storage question, just skip the question which has storage.
3471 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3476 // If Question is disabled, don't reset it to default
3478 if (Question
->Expression
!= NULL
) {
3479 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3484 if (RetrieveValueFirst
) {
3486 // Call the Retrieve call back to get the initial question value.
3488 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3492 // If not request to get the initial value or get initial value fail, then get default value.
3494 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3495 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3496 if (EFI_ERROR (Status
)) {
3502 // Synchronize Buffer storage's Edit buffer
3504 if ((Question
->Storage
!= NULL
) &&
3505 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3506 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3509 } else if (SettingScope
== FormSetLevel
) {
3510 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3511 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3512 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3513 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3514 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3516 } else if (SettingScope
== SystemLevel
) {
3518 // Preload all Hii formset.
3520 LoadAllHiiFormset();
3522 OldFormSet
= mSystemLevelFormSet
;
3525 // Set Default Value for each FormSet in the maintain list.
3527 Link
= GetFirstNode (&gBrowserFormSetList
);
3528 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3529 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3530 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3531 if (!ValidateFormSet(LocalFormSet
)) {
3535 mSystemLevelFormSet
= LocalFormSet
;
3537 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3540 mSystemLevelFormSet
= OldFormSet
;
3548 Validate whether this question's value has changed.
3550 @param FormSet FormSet data structure.
3551 @param Form Form data structure.
3552 @param Question Question to be initialized.
3553 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
3555 @retval TRUE Question's value has changed.
3556 @retval FALSE Question's value has not changed
3560 IsQuestionValueChanged (
3561 IN FORM_BROWSER_FORMSET
*FormSet
,
3562 IN FORM_BROWSER_FORM
*Form
,
3563 IN OUT FORM_BROWSER_STATEMENT
*Question
,
3564 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
3567 EFI_HII_VALUE BackUpValue
;
3568 CHAR8
*BackUpBuffer
;
3570 BOOLEAN ValueChanged
;
3574 // For quetion without storage, always mark it as data not changed.
3576 if (Question
->Storage
== NULL
&& Question
->Operand
!= EFI_IFR_TIME_OP
&& Question
->Operand
!= EFI_IFR_DATE_OP
) {
3580 BackUpBuffer
= NULL
;
3581 ValueChanged
= FALSE
;
3583 switch (Question
->Operand
) {
3584 case EFI_IFR_ORDERED_LIST_OP
:
3585 BufferWidth
= Question
->StorageWidth
;
3586 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3587 ASSERT (BackUpBuffer
!= NULL
);
3590 case EFI_IFR_STRING_OP
:
3591 case EFI_IFR_PASSWORD_OP
:
3592 BufferWidth
= (UINTN
) Question
->Maximum
* sizeof (CHAR16
);
3593 BackUpBuffer
= AllocateCopyPool (BufferWidth
, Question
->BufferValue
);
3594 ASSERT (BackUpBuffer
!= NULL
);
3601 CopyMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
3603 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetValueFrom
);
3604 ASSERT_EFI_ERROR(Status
);
3606 if (CompareMem (&BackUpValue
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
)) != 0 ||
3607 CompareMem (BackUpBuffer
, Question
->BufferValue
, BufferWidth
) != 0) {
3608 ValueChanged
= TRUE
;
3611 CopyMem (&Question
->HiiValue
, &BackUpValue
, sizeof (EFI_HII_VALUE
));
3612 CopyMem (Question
->BufferValue
, BackUpBuffer
, BufferWidth
);
3614 if (BackUpBuffer
!= NULL
) {
3615 FreePool (BackUpBuffer
);
3618 return ValueChanged
;
3622 Initialize Question's Edit copy from Storage.
3624 @param Selection Selection contains the information about
3625 the Selection, form and formset to be displayed.
3626 Selection action may be updated in retrieve callback.
3627 If Selection is NULL, only initialize Question value.
3628 @param FormSet FormSet data structure.
3629 @param Form Form data structure.
3631 @retval EFI_SUCCESS The function completed successfully.
3636 IN OUT UI_MENU_SELECTION
*Selection
,
3637 IN FORM_BROWSER_FORMSET
*FormSet
,
3638 IN FORM_BROWSER_FORM
*Form
3643 FORM_BROWSER_STATEMENT
*Question
;
3647 Link
= GetFirstNode (&Form
->StatementListHead
);
3648 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3649 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3652 // Initialize local copy of Value for each Question
3654 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
&& (Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
)== 0) {
3655 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
3657 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3659 if (EFI_ERROR (Status
)) {
3663 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3664 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3668 // Call the Retrieve call back function for all questions.
3670 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3671 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) &&
3672 !gFinishRetrieveCall
) {
3674 // Check QuestionValue does exist.
3676 StorageWidth
= Question
->StorageWidth
;
3677 if (Question
->BufferValue
!= NULL
) {
3678 BufferValue
= Question
->BufferValue
;
3680 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3684 // For efivarstore storage, initial question value first.
3686 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3687 Status
= gRT
->GetVariable (
3688 Question
->VariableName
,
3689 &Question
->Storage
->Guid
,
3696 Status
= ProcessCallBackFunction(Selection
, FormSet
, Form
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3700 // Update Question Value changed flag.
3702 Question
->ValueChanged
= IsQuestionValueChanged(FormSet
, Form
, Question
, GetSetValueWithBuffer
);
3704 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3711 Initialize Question's Edit copy from Storage for the whole Formset.
3713 @param Selection Selection contains the information about
3714 the Selection, form and formset to be displayed.
3715 Selection action may be updated in retrieve callback.
3716 If Selection is NULL, only initialize Question value.
3717 @param FormSet FormSet data structure.
3719 @retval EFI_SUCCESS The function completed successfully.
3724 IN OUT UI_MENU_SELECTION
*Selection
,
3725 IN FORM_BROWSER_FORMSET
*FormSet
3730 FORM_BROWSER_FORM
*Form
;
3732 Link
= GetFirstNode (&FormSet
->FormListHead
);
3733 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3734 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3737 // Initialize local copy of Value for each Form
3739 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3740 if (EFI_ERROR (Status
)) {
3744 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3748 // Finished question initialization.
3750 FormSet
->QuestionInited
= TRUE
;
3756 Remove the Request element from the Config Request.
3758 @param Storage Pointer to the browser storage.
3759 @param RequestElement The pointer to the Request element.
3764 IN OUT BROWSER_STORAGE
*Storage
,
3765 IN CHAR16
*RequestElement
3771 ASSERT (Storage
->ConfigRequest
!= NULL
&& RequestElement
!= NULL
);
3773 NewStr
= StrStr (Storage
->ConfigRequest
, RequestElement
);
3775 if (NewStr
== NULL
) {
3780 // Remove this element from this ConfigRequest.
3783 NewStr
+= StrLen (RequestElement
);
3784 CopyMem (DestStr
, NewStr
, StrSize (NewStr
));
3786 Storage
->SpareStrLen
+= StrLen (RequestElement
);
3790 Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
3792 @param Storage Pointer to the browser storage.
3793 @param ConfigRequest The pointer to the Request element.
3797 RemoveConfigRequest (
3798 BROWSER_STORAGE
*Storage
,
3799 CHAR16
*ConfigRequest
3802 CHAR16
*RequestElement
;
3803 CHAR16
*NextRequestElement
;
3807 // No request element in it, just return.
3809 if (ConfigRequest
== NULL
) {
3813 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3815 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
3820 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
3822 SearchKey
= L
"&OFFSET";
3826 // Find SearchKey storage
3828 if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3829 RequestElement
= StrStr (ConfigRequest
, L
"PATH");
3830 ASSERT (RequestElement
!= NULL
);
3831 RequestElement
= StrStr (RequestElement
, SearchKey
);
3833 RequestElement
= StrStr (ConfigRequest
, SearchKey
);
3836 while (RequestElement
!= NULL
) {
3838 // +1 to avoid find header itself.
3840 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
3843 // The last Request element in configRequest string.
3845 if (NextRequestElement
!= NULL
) {
3847 // Replace "&" with '\0'.
3849 *NextRequestElement
= L
'\0';
3852 RemoveElement (Storage
, RequestElement
);
3854 if (NextRequestElement
!= NULL
) {
3856 // Restore '&' with '\0' for later used.
3858 *NextRequestElement
= L
'&';
3861 RequestElement
= NextRequestElement
;
3865 // If no request element remain, just remove the ConfigRequest string.
3867 if (StrCmp (Storage
->ConfigRequest
, Storage
->ConfigHdr
) == 0) {
3868 FreePool (Storage
->ConfigRequest
);
3869 Storage
->ConfigRequest
= NULL
;
3870 Storage
->SpareStrLen
= 0;
3875 Base on the current formset info, clean the ConfigRequest string in browser storage.
3877 @param FormSet Pointer of the FormSet
3881 CleanBrowserStorage (
3882 IN OUT FORM_BROWSER_FORMSET
*FormSet
3886 FORMSET_STORAGE
*Storage
;
3887 CHAR16
*ConfigRequest
;
3889 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3890 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3891 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3892 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3894 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3895 if (Storage
->ConfigRequest
== NULL
|| Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
3899 ConfigRequest
= FormSet
->QuestionInited
? Storage
->ConfigRequest
: Storage
->ConfigElements
;
3900 RemoveConfigRequest (Storage
->BrowserStorage
, ConfigRequest
);
3901 } else if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
3902 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3903 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
3904 FreePool (Storage
->BrowserStorage
->ConfigRequest
);
3906 Storage
->BrowserStorage
->Initialized
= FALSE
;
3912 Check whether current element in the ConfigReqeust string.
3914 @param BrowserStorage Storage which includes ConfigReqeust.
3915 @param RequestElement New element need to check.
3917 @retval TRUE The Element is in the ConfigReqeust string.
3918 @retval FALSE The Element not in the configReqeust String.
3923 BROWSER_STORAGE
*BrowserStorage
,
3924 CHAR16
*RequestElement
3927 return StrStr (BrowserStorage
->ConfigRequest
, RequestElement
) != NULL
? TRUE
: FALSE
;
3931 Append the Request element to the Config Request.
3933 @param ConfigRequest Current ConfigRequest info.
3934 @param SpareStrLen Current remain free buffer for config reqeust.
3935 @param RequestElement New Request element.
3939 AppendConfigRequest (
3940 IN OUT CHAR16
**ConfigRequest
,
3941 IN OUT UINTN
*SpareStrLen
,
3942 IN CHAR16
*RequestElement
3949 StrLength
= StrLen (RequestElement
);
3952 // Append <RequestElement> to <ConfigRequest>
3954 if (StrLength
> *SpareStrLen
) {
3956 // Old String buffer is not sufficient for RequestElement, allocate a new one
3958 StringSize
= (*ConfigRequest
!= NULL
) ? StrSize (*ConfigRequest
) : sizeof (CHAR16
);
3959 NewStr
= AllocateZeroPool (StringSize
+ CONFIG_REQUEST_STRING_INCREMENTAL
* sizeof (CHAR16
));
3960 ASSERT (NewStr
!= NULL
);
3962 if (*ConfigRequest
!= NULL
) {
3963 CopyMem (NewStr
, *ConfigRequest
, StringSize
);
3964 FreePool (*ConfigRequest
);
3966 *ConfigRequest
= NewStr
;
3967 *SpareStrLen
= CONFIG_REQUEST_STRING_INCREMENTAL
;
3970 StrCat (*ConfigRequest
, RequestElement
);
3971 *SpareStrLen
-= StrLength
;
3975 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
3977 @param Storage Form set Storage.
3979 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
3980 @retval FALSE All elements covered by current used elements.
3984 ConfigRequestAdjust (
3985 IN FORMSET_STORAGE
*Storage
3988 CHAR16
*RequestElement
;
3989 CHAR16
*NextRequestElement
;
3999 if (Storage
->BrowserStorage
->ConfigRequest
== NULL
) {
4000 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4001 if (Storage
->ConfigElements
!= NULL
) {
4002 FreePool (Storage
->ConfigElements
);
4004 Storage
->ConfigElements
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4008 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4010 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
4015 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
4017 SearchKey
= L
"&OFFSET";
4021 // Prepare the config header.
4023 RetBuf
= AllocateCopyPool(StrSize (Storage
->BrowserStorage
->ConfigHdr
), Storage
->BrowserStorage
->ConfigHdr
);
4024 ASSERT (RetBuf
!= NULL
);
4027 // Find SearchKey storage
4029 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4030 RequestElement
= StrStr (Storage
->ConfigRequest
, L
"PATH");
4031 ASSERT (RequestElement
!= NULL
);
4032 RequestElement
= StrStr (RequestElement
, SearchKey
);
4034 RequestElement
= StrStr (Storage
->ConfigRequest
, SearchKey
);
4037 while (RequestElement
!= NULL
) {
4039 // +1 to avoid find header itself.
4041 NextRequestElement
= StrStr (RequestElement
+ 1, SearchKey
);
4044 // The last Request element in configRequest string.
4046 if (NextRequestElement
!= NULL
) {
4048 // Replace "&" with '\0'.
4050 *NextRequestElement
= L
'\0';
4053 if (!ElementValidation (Storage
->BrowserStorage
, RequestElement
)) {
4055 // Add this element to the Storage->BrowserStorage->AllRequestElement.
4057 AppendConfigRequest(&Storage
->BrowserStorage
->ConfigRequest
, &Storage
->BrowserStorage
->SpareStrLen
, RequestElement
);
4058 AppendConfigRequest (&RetBuf
, &SpareBufLen
, RequestElement
);
4062 if (NextRequestElement
!= NULL
) {
4064 // Restore '&' with '\0' for later used.
4066 *NextRequestElement
= L
'&';
4069 RequestElement
= NextRequestElement
;
4073 if (Storage
->ConfigElements
!= NULL
) {
4074 FreePool (Storage
->ConfigElements
);
4076 Storage
->ConfigElements
= RetBuf
;
4086 Base on ConfigRequest info to get default value for current formset.
4088 ConfigRequest info include the info about which questions in current formset need to
4089 get default value. This function only get these questions default value.
4091 @param FormSet FormSet data structure.
4092 @param Storage Storage need to update value.
4093 @param ConfigRequest The config request string.
4097 GetDefaultForFormset (
4098 IN FORM_BROWSER_FORMSET
*FormSet
,
4099 IN BROWSER_STORAGE
*Storage
,
4100 IN CHAR16
*ConfigRequest
4105 LIST_ENTRY BackUpList
;
4106 NAME_VALUE_NODE
*Node
;
4108 LIST_ENTRY
*NodeLink
;
4109 NAME_VALUE_NODE
*TmpNode
;
4111 EFI_STRING Progress
;
4115 InitializeListHead(&BackUpList
);
4118 // Back update the edit buffer.
4120 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4121 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4122 BackUpBuf
= AllocateCopyPool (Storage
->Size
, Storage
->EditBuffer
);
4123 ASSERT (BackUpBuf
!= NULL
);
4124 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4125 Link
= GetFirstNode (&Storage
->NameValueListHead
);
4126 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
4127 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4128 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
4131 // Only back Node belong to this formset.
4133 if (StrStr (Storage
->ConfigRequest
, Node
->Name
) == NULL
) {
4137 TmpNode
= AllocateCopyPool (sizeof (NAME_VALUE_NODE
), Node
);
4138 TmpNode
->Name
= AllocateCopyPool (StrSize(Node
->Name
) * sizeof (CHAR16
), Node
->Name
);
4139 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4141 InsertTailList(&BackUpList
, &TmpNode
->Link
);
4146 // Get default value.
4148 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
, TRUE
);
4151 // Update the question value based on the input ConfigRequest.
4153 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
4154 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
4155 ASSERT (BackUpBuf
!= NULL
);
4156 BufferSize
= Storage
->Size
;
4157 Status
= mHiiConfigRouting
->BlockToConfig(
4160 Storage
->EditBuffer
,
4165 ASSERT_EFI_ERROR (Status
);
4167 Status
= mHiiConfigRouting
->ConfigToBlock (
4174 ASSERT_EFI_ERROR (Status
);
4176 if (Result
!= NULL
) {
4180 CopyMem (Storage
->EditBuffer
, BackUpBuf
, Storage
->Size
);
4181 FreePool (BackUpBuf
);
4182 } else if (Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4184 // Update question value, only element in ConfigReqeust will be update.
4186 Link
= GetFirstNode (&BackUpList
);
4187 while (!IsNull (&BackUpList
, Link
)) {
4188 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4189 Link
= GetNextNode (&BackUpList
, Link
);
4191 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
4195 NodeLink
= GetFirstNode (&Storage
->NameValueListHead
);
4196 while (!IsNull (&Storage
->NameValueListHead
, NodeLink
)) {
4197 TmpNode
= NAME_VALUE_NODE_FROM_LINK (NodeLink
);
4198 NodeLink
= GetNextNode (&Storage
->NameValueListHead
, NodeLink
);
4200 if (StrCmp (Node
->Name
, TmpNode
->Name
) != 0) {
4204 FreePool (TmpNode
->EditValue
);
4205 TmpNode
->EditValue
= AllocateCopyPool (StrSize(Node
->EditValue
) * sizeof (CHAR16
), Node
->EditValue
);
4207 RemoveEntryList (&Node
->Link
);
4208 FreePool (Node
->EditValue
);
4209 FreePool (Node
->Name
);
4215 // Restore the Name/Value node.
4217 Link
= GetFirstNode (&BackUpList
);
4218 while (!IsNull (&BackUpList
, Link
)) {
4219 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
4220 Link
= GetNextNode (&BackUpList
, Link
);
4225 RemoveEntryList (&Node
->Link
);
4226 FreePool (Node
->EditValue
);
4227 FreePool (Node
->Name
);
4234 Fill storage's edit copy with settings requested from Configuration Driver.
4236 @param FormSet FormSet data structure.
4237 @param Storage Buffer Storage.
4242 IN FORM_BROWSER_FORMSET
*FormSet
,
4243 IN FORMSET_STORAGE
*Storage
4247 EFI_STRING Progress
;
4251 switch (Storage
->BrowserStorage
->Type
) {
4252 case EFI_HII_VARSTORE_EFI_VARIABLE
:
4255 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
4256 if (Storage
->BrowserStorage
->ConfigRequest
!= NULL
) {
4257 ConfigRequestAdjust(Storage
);
4261 Status
= gRT
->GetVariable (
4262 Storage
->BrowserStorage
->Name
,
4263 &Storage
->BrowserStorage
->Guid
,
4265 (UINTN
*)&Storage
->BrowserStorage
->Size
,
4266 Storage
->BrowserStorage
->EditBuffer
4269 // If get variable fail, extract default from IFR binary
4271 if (EFI_ERROR (Status
)) {
4272 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
4275 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4277 // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
4279 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, NULL
, TRUE
);
4282 case EFI_HII_VARSTORE_BUFFER
:
4283 case EFI_HII_VARSTORE_NAME_VALUE
:
4285 // Skip if there is no RequestElement or data has initilized.
4287 if (Storage
->ElementCount
== 0 || Storage
->BrowserStorage
->Initialized
) {
4291 Status
= EFI_NOT_FOUND
;
4292 if (FormSet
->ConfigAccess
!= NULL
) {
4294 // Request current settings from Configuration Driver
4296 Status
= FormSet
->ConfigAccess
->ExtractConfig (
4297 FormSet
->ConfigAccess
,
4298 Storage
->ConfigRequest
,
4303 if (!EFI_ERROR (Status
)) {
4305 // Convert Result from <ConfigAltResp> to <ConfigResp>
4307 StrPtr
= StrStr (Result
, L
"&GUID=");
4308 if (StrPtr
!= NULL
) {
4312 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
4317 if (EFI_ERROR (Status
)) {
4319 // Base on the configRequest string to get default value.
4321 GetDefaultForFormset (FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
);
4324 SynchronizeStorage(FormSet
, Storage
->BrowserStorage
, Storage
->ConfigRequest
, TRUE
);
4326 Storage
->BrowserStorage
->ConfigRequest
= AllocateCopyPool (StrSize (Storage
->ConfigRequest
), Storage
->ConfigRequest
);
4327 Storage
->BrowserStorage
->Initialized
= TRUE
;
4336 Get current setting of Questions.
4338 @param FormSet FormSet data structure.
4342 InitializeCurrentSetting (
4343 IN OUT FORM_BROWSER_FORMSET
*FormSet
4347 FORMSET_STORAGE
*Storage
;
4348 FORM_BROWSER_FORMSET
*OldFormSet
;
4351 // Try to find pre FormSet in the maintain backup list.
4352 // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
4354 OldFormSet
= GetFormSetFromHiiHandle (FormSet
->HiiHandle
);
4355 if (OldFormSet
!= NULL
) {
4356 RemoveEntryList (&OldFormSet
->Link
);
4357 DestroyFormSet (OldFormSet
);
4359 InsertTailList (&gBrowserFormSetList
, &FormSet
->Link
);
4362 // Extract default from IFR binary for no storage questions.
4364 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
4367 // Request current settings from Configuration Driver
4369 Link
= GetFirstNode (&FormSet
->StorageListHead
);
4370 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
4371 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
4373 LoadStorage (FormSet
, Storage
);
4375 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
4381 Fetch the Ifr binary data of a FormSet.
4383 @param Handle PackageList Handle
4384 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4385 specified (NULL or zero GUID), take the first
4386 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4387 found in package list.
4388 On output, GUID of the formset found(if not NULL).
4389 @param BinaryLength The length of the FormSet IFR binary.
4390 @param BinaryData The buffer designed to receive the FormSet.
4392 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
4393 BufferLength was updated.
4394 @retval EFI_INVALID_PARAMETER The handle is unknown.
4395 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
4396 be found with the requested FormId.
4401 IN EFI_HII_HANDLE Handle
,
4402 IN OUT EFI_GUID
*FormSetGuid
,
4403 OUT UINTN
*BinaryLength
,
4404 OUT UINT8
**BinaryData
4408 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
4414 UINT32 PackageListLength
;
4415 EFI_HII_PACKAGE_HEADER PackageHeader
;
4417 UINT8 NumberOfClassGuid
;
4418 BOOLEAN ClassGuidMatch
;
4419 EFI_GUID
*ClassGuid
;
4420 EFI_GUID
*ComparingGuid
;
4424 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
4427 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
4429 if (FormSetGuid
== NULL
) {
4430 ComparingGuid
= &gZeroGuid
;
4432 ComparingGuid
= FormSetGuid
;
4436 // Get HII PackageList
4439 HiiPackageList
= NULL
;
4440 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4441 if (Status
== EFI_BUFFER_TOO_SMALL
) {
4442 HiiPackageList
= AllocatePool (BufferSize
);
4443 ASSERT (HiiPackageList
!= NULL
);
4445 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
4447 if (EFI_ERROR (Status
)) {
4450 ASSERT (HiiPackageList
!= NULL
);
4453 // Get Form package from this HII package List
4455 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
4457 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
4459 ClassGuidMatch
= FALSE
;
4460 while (Offset
< PackageListLength
) {
4461 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
4462 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
4464 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
4466 // Search FormSet in this Form Package
4468 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
4469 while (Offset2
< PackageHeader
.Length
) {
4470 OpCodeData
= Package
+ Offset2
;
4472 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
4474 // Try to compare against formset GUID
4476 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
4477 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
4481 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
4483 // Try to compare against formset class GUID
4485 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
4486 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
4487 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
4488 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
4489 ClassGuidMatch
= TRUE
;
4493 if (ClassGuidMatch
) {
4496 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
4497 ClassGuidMatch
= TRUE
;
4502 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
4505 if (Offset2
< PackageHeader
.Length
) {
4507 // Target formset found
4513 Offset
+= PackageHeader
.Length
;
4516 if (Offset
>= PackageListLength
) {
4518 // Form package not found in this Package List
4520 FreePool (HiiPackageList
);
4521 return EFI_NOT_FOUND
;
4524 if (FormSetGuid
!= NULL
) {
4526 // Return the FormSet GUID
4528 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
4532 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
4533 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
4534 // of the Form Package.
4536 *BinaryLength
= PackageHeader
.Length
- Offset2
;
4537 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
4539 FreePool (HiiPackageList
);
4541 if (*BinaryData
== NULL
) {
4542 return EFI_OUT_OF_RESOURCES
;
4550 Initialize the internal data structure of a FormSet.
4552 @param Handle PackageList Handle
4553 @param FormSetGuid On input, GUID or class GUID of a formset. If not
4554 specified (NULL or zero GUID), take the first
4555 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
4556 found in package list.
4557 On output, GUID of the formset found(if not NULL).
4558 @param FormSet FormSet data structure.
4560 @retval EFI_SUCCESS The function completed successfully.
4561 @retval EFI_NOT_FOUND The specified FormSet could not be found.
4566 IN EFI_HII_HANDLE Handle
,
4567 IN OUT EFI_GUID
*FormSetGuid
,
4568 OUT FORM_BROWSER_FORMSET
*FormSet
4572 EFI_HANDLE DriverHandle
;
4574 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
4575 if (EFI_ERROR (Status
)) {
4579 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
4580 FormSet
->HiiHandle
= Handle
;
4581 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
4582 FormSet
->QuestionInited
= FALSE
;
4585 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
4587 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
4588 if (EFI_ERROR (Status
)) {
4591 FormSet
->DriverHandle
= DriverHandle
;
4592 Status
= gBS
->HandleProtocol (
4594 &gEfiHiiConfigAccessProtocolGuid
,
4595 (VOID
**) &FormSet
->ConfigAccess
4597 if (EFI_ERROR (Status
)) {
4599 // Configuration Driver don't attach ConfigAccess protocol to its HII package
4600 // list, then there will be no configuration action required
4602 FormSet
->ConfigAccess
= NULL
;
4606 // Parse the IFR binary OpCodes
4608 Status
= ParseOpCodes (FormSet
);
4615 Save globals used by previous call to SendForm(). SendForm() may be called from
4616 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
4617 So, save globals of previous call to SendForm() and restore them upon exit.
4621 SaveBrowserContext (
4625 BROWSER_CONTEXT
*Context
;
4626 FORM_ENTRY_INFO
*MenuList
;
4628 gBrowserContextCount
++;
4629 if (gBrowserContextCount
== 1) {
4631 // This is not reentry of SendForm(), no context to save
4636 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
4637 ASSERT (Context
!= NULL
);
4639 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
4642 // Save FormBrowser context
4644 Context
->Selection
= gCurrentSelection
;
4645 Context
->ResetRequired
= gResetRequired
;
4646 Context
->ExitRequired
= gExitRequired
;
4647 Context
->HiiHandle
= mCurrentHiiHandle
;
4648 Context
->FormId
= mCurrentFormId
;
4649 CopyGuid (&Context
->FormSetGuid
, &mCurrentFormSetGuid
);
4652 // Save the menu history data.
4654 InitializeListHead(&Context
->FormHistoryList
);
4655 while (!IsListEmpty (&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
)) {
4656 MenuList
= FORM_ENTRY_INFO_FROM_LINK (mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
.ForwardLink
);
4657 RemoveEntryList (&MenuList
->Link
);
4659 InsertTailList(&Context
->FormHistoryList
, &MenuList
->Link
);
4663 // Insert to FormBrowser context list
4665 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
4670 Restore globals used by previous call to SendForm().
4674 RestoreBrowserContext (
4679 BROWSER_CONTEXT
*Context
;
4680 FORM_ENTRY_INFO
*MenuList
;
4682 ASSERT (gBrowserContextCount
!= 0);
4683 gBrowserContextCount
--;
4684 if (gBrowserContextCount
== 0) {
4686 // This is not reentry of SendForm(), no context to restore
4691 ASSERT (!IsListEmpty (&gBrowserContextList
));
4693 Link
= GetFirstNode (&gBrowserContextList
);
4694 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4697 // Restore FormBrowser context
4699 gCurrentSelection
= Context
->Selection
;
4700 gResetRequired
= Context
->ResetRequired
;
4701 gExitRequired
= Context
->ExitRequired
;
4702 mCurrentHiiHandle
= Context
->HiiHandle
;
4703 mCurrentFormId
= Context
->FormId
;
4704 CopyGuid (&mCurrentFormSetGuid
, &Context
->FormSetGuid
);
4707 // Restore the menu history data.
4709 while (!IsListEmpty (&Context
->FormHistoryList
)) {
4710 MenuList
= FORM_ENTRY_INFO_FROM_LINK (Context
->FormHistoryList
.ForwardLink
);
4711 RemoveEntryList (&MenuList
->Link
);
4713 InsertTailList(&mPrivateData
.FormBrowserEx2
.FormViewHistoryHead
, &MenuList
->Link
);
4717 // Remove from FormBrowser context list
4719 RemoveEntryList (&Context
->Link
);
4720 gBS
->FreePool (Context
);
4724 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4726 @param Handle The Hii Handle.
4728 @return the found FormSet context. If no found, NULL will return.
4731 FORM_BROWSER_FORMSET
*
4732 GetFormSetFromHiiHandle (
4733 EFI_HII_HANDLE Handle
4737 FORM_BROWSER_FORMSET
*FormSet
;
4739 Link
= GetFirstNode (&gBrowserFormSetList
);
4740 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4741 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4742 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4743 if (!ValidateFormSet(FormSet
)) {
4746 if (FormSet
->HiiHandle
== Handle
) {
4755 Check whether the input HII handle is the FormSet that is being used.
4757 @param Handle The Hii Handle.
4759 @retval TRUE HII handle is being used.
4760 @retval FALSE HII handle is not being used.
4764 IsHiiHandleInBrowserContext (
4765 EFI_HII_HANDLE Handle
4769 BROWSER_CONTEXT
*Context
;
4772 // HiiHandle is Current FormSet.
4774 if (mCurrentHiiHandle
== Handle
) {
4779 // Check whether HiiHandle is in BrowserContext.
4781 Link
= GetFirstNode (&gBrowserContextList
);
4782 while (!IsNull (&gBrowserContextList
, Link
)) {
4783 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4784 if (Context
->HiiHandle
== Handle
) {
4786 // HiiHandle is in BrowserContext
4790 Link
= GetNextNode (&gBrowserContextList
, Link
);
4797 Perform Password check.
4798 Passwork may be encrypted by driver that requires the specific check.
4800 @param Form Form where Password Statement is in.
4801 @param Statement Password statement
4802 @param PasswordString Password string to be checked. It may be NULL.
4803 NULL means to restore password.
4804 "" string can be used to checked whether old password does exist.
4806 @return Status Status of Password check.
4811 IN FORM_DISPLAY_ENGINE_FORM
*Form
,
4812 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
4813 IN EFI_STRING PasswordString OPTIONAL
4817 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4818 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
4819 EFI_IFR_TYPE_VALUE IfrTypeValue
;
4820 FORM_BROWSER_STATEMENT
*Question
;
4822 ConfigAccess
= gCurrentSelection
->FormSet
->ConfigAccess
;
4823 Question
= GetBrowserStatement(Statement
);
4824 ASSERT (Question
!= NULL
);
4826 if ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
) {
4827 if (ConfigAccess
== NULL
) {
4828 return EFI_UNSUPPORTED
;
4831 if (PasswordString
== NULL
) {
4835 if (StrnCmp (PasswordString
, (CHAR16
*) Question
->BufferValue
, Question
->StorageWidth
/sizeof (CHAR16
)) == 0) {
4838 return EFI_NOT_READY
;
4843 // Prepare password string in HII database
4845 if (PasswordString
!= NULL
) {
4846 IfrTypeValue
.string
= NewString (PasswordString
, gCurrentSelection
->FormSet
->HiiHandle
);
4848 IfrTypeValue
.string
= 0;
4852 // Send password to Configuration Driver for validation
4854 Status
= ConfigAccess
->Callback (
4856 EFI_BROWSER_ACTION_CHANGING
,
4857 Question
->QuestionId
,
4858 Question
->HiiValue
.Type
,
4864 // Remove password string from HII database
4866 if (PasswordString
!= NULL
) {
4867 DeleteString (IfrTypeValue
.string
, gCurrentSelection
->FormSet
->HiiHandle
);
4874 Find the registered HotKey based on KeyData.
4876 @param[in] KeyData A pointer to a buffer that describes the keystroke
4877 information for the hot key.
4879 @return The registered HotKey context. If no found, NULL will return.
4882 GetHotKeyFromRegisterList (
4883 IN EFI_INPUT_KEY
*KeyData
4887 BROWSER_HOT_KEY
*HotKey
;
4889 Link
= GetFirstNode (&gBrowserHotKeyList
);
4890 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4891 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4892 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4895 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4902 Configure what scope the hot key will impact.
4903 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4904 If no scope is set, the default scope will be FormSet level.
4905 After all registered hot keys are removed, previous Scope can reset to another level.
4907 @param[in] Scope Scope level to be set.
4909 @retval EFI_SUCCESS Scope is set correctly.
4910 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4911 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4917 IN BROWSER_SETTING_SCOPE Scope
4920 if (Scope
>= MaxLevel
) {
4921 return EFI_INVALID_PARAMETER
;
4925 // When no hot key registered in system or on the first setting,
4926 // Scope can be set.
4928 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4929 gBrowserSettingScope
= Scope
;
4930 mBrowserScopeFirstSet
= FALSE
;
4931 } else if (Scope
!= gBrowserSettingScope
) {
4932 return EFI_UNSUPPORTED
;
4939 Register the hot key with its browser action, or unregistered the hot key.
4940 Only support hot key that is not printable character (control key, function key, etc.).
4941 If the action value is zero, the hot key will be unregistered if it has been registered.
4942 If the same hot key has been registered, the new action and help string will override the previous ones.
4944 @param[in] KeyData A pointer to a buffer that describes the keystroke
4945 information for the hot key. Its type is EFI_INPUT_KEY to
4946 be supported by all ConsoleIn devices.
4947 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4948 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4949 @param[in] HelpString Help string that describes the hot key information.
4950 Its value may be NULL for the unregistered hot key.
4952 @retval EFI_SUCCESS Hot key is registered or unregistered.
4953 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4954 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4955 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4960 IN EFI_INPUT_KEY
*KeyData
,
4962 IN UINT16 DefaultId
,
4963 IN EFI_STRING HelpString OPTIONAL
4966 BROWSER_HOT_KEY
*HotKey
;
4969 // Check input parameters.
4971 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4972 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4973 return EFI_INVALID_PARAMETER
;
4977 // Check whether the input KeyData is in BrowserHotKeyList.
4979 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4982 // Unregister HotKey
4984 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4985 if (HotKey
!= NULL
) {
4987 // The registered HotKey is found.
4988 // Remove it from List, and free its resource.
4990 RemoveEntryList (&HotKey
->Link
);
4991 FreePool (HotKey
->KeyData
);
4992 FreePool (HotKey
->HelpString
);
4996 // The registered HotKey is not found.
4998 return EFI_NOT_FOUND
;
5003 // Register HotKey into List.
5005 if (HotKey
== NULL
) {
5007 // Create new Key, and add it into List.
5009 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
5010 ASSERT (HotKey
!= NULL
);
5011 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
5012 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
5013 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
5017 // Fill HotKey information.
5019 HotKey
->Action
= Action
;
5020 HotKey
->DefaultId
= DefaultId
;
5021 if (HotKey
->HelpString
!= NULL
) {
5022 FreePool (HotKey
->HelpString
);
5024 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
5030 Register Exit handler function.
5031 When more than one handler function is registered, the latter one will override the previous one.
5032 When NULL handler is specified, the previous Exit handler will be unregistered.
5034 @param[in] Handler Pointer to handler function.
5039 RegiserExitHandler (
5040 IN EXIT_HANDLER Handler
5043 ExitHandlerFunction
= Handler
;
5048 Check whether the browser data has been modified.
5050 @retval TRUE Browser data is modified.
5051 @retval FALSE No browser data is modified.
5056 IsBrowserDataModified (
5061 FORM_BROWSER_FORMSET
*FormSet
;
5063 if (gCurrentSelection
== NULL
) {
5067 switch (gBrowserSettingScope
) {
5069 return IsNvUpdateRequiredForForm (gCurrentSelection
->Form
);
5072 return IsNvUpdateRequiredForFormSet (gCurrentSelection
->FormSet
);
5075 Link
= GetFirstNode (&gBrowserFormSetList
);
5076 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5077 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5078 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5081 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5091 Execute the action requested by the Action parameter.
5093 @param[in] Action Execute the request action.
5094 @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
5096 @retval EFI_SUCCESS Execute the request action succss.
5097 @retval EFI_INVALID_PARAMETER The input action value is invalid.
5109 if (gCurrentSelection
== NULL
) {
5110 return EFI_NOT_READY
;
5113 Status
= EFI_SUCCESS
;
5116 // Executet the discard action.
5118 if ((Action
& BROWSER_ACTION_DISCARD
) != 0) {
5119 Status
= DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5120 if (EFI_ERROR (Status
)) {
5126 // Executet the difault action.
5128 if ((Action
& BROWSER_ACTION_DEFAULT
) != 0) {
5129 Status
= ExtractDefault (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, DefaultId
, gBrowserSettingScope
, GetDefaultForAll
, NULL
, FALSE
);
5130 if (EFI_ERROR (Status
)) {
5136 // Executet the submit action.
5138 if ((Action
& BROWSER_ACTION_SUBMIT
) != 0) {
5139 Status
= SubmitForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5140 if (EFI_ERROR (Status
)) {
5146 // Executet the reset action.
5148 if ((Action
& BROWSER_ACTION_RESET
) != 0) {
5149 gResetRequired
= TRUE
;
5153 // Executet the exit action.
5155 if ((Action
& BROWSER_ACTION_EXIT
) != 0) {
5156 DiscardForm (gCurrentSelection
->FormSet
, gCurrentSelection
->Form
, gBrowserSettingScope
);
5157 if (gBrowserSettingScope
== SystemLevel
) {
5158 if (ExitHandlerFunction
!= NULL
) {
5159 ExitHandlerFunction ();
5163 gExitRequired
= TRUE
;
5170 Create reminder to let user to choose save or discard the changed browser data.
5171 Caller can use it to actively check the changed browser data.
5173 @retval BROWSER_NO_CHANGES No browser data is changed.
5174 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
5175 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
5185 FORM_BROWSER_FORMSET
*FormSet
;
5186 BOOLEAN IsDataChanged
;
5187 UINT32 DataSavedAction
;
5189 DataSavedAction
= BROWSER_NO_CHANGES
;
5190 IsDataChanged
= FALSE
;
5191 Link
= GetFirstNode (&gBrowserFormSetList
);
5192 while (!IsNull (&gBrowserFormSetList
, Link
)) {
5193 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
5194 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
5195 if (!ValidateFormSet(FormSet
)) {
5198 if (IsNvUpdateRequiredForFormSet (FormSet
)) {
5199 IsDataChanged
= TRUE
;
5205 // No data is changed. No save is required.
5207 if (!IsDataChanged
) {
5208 return DataSavedAction
;
5212 // If data is changed, prompt user to save or discard it.
5215 DataSavedAction
= (UINT32
) mFormDisplay
->ConfirmDataChange();
5217 if (DataSavedAction
== BROWSER_SAVE_CHANGES
) {
5218 SubmitForm (NULL
, NULL
, SystemLevel
);
5220 } else if (DataSavedAction
== BROWSER_DISCARD_CHANGES
) {
5221 DiscardForm (NULL
, NULL
, SystemLevel
);
5226 return DataSavedAction
;