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
,
32 EFI_HII_DATABASE_PROTOCOL
*mHiiDatabase
;
33 EFI_HII_STRING_PROTOCOL
*mHiiString
;
34 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
;
35 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*mPathFromText
;
37 UINTN gBrowserContextCount
= 0;
38 LIST_ENTRY gBrowserContextList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList
);
39 LIST_ENTRY gBrowserFormSetList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList
);
40 LIST_ENTRY gBrowserHotKeyList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList
);
41 LIST_ENTRY gBrowserStorageList
= INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList
);
43 BANNER_DATA
*gBannerData
;
44 EFI_HII_HANDLE gFrontPageHandle
;
46 UINTN gFunctionKeySetting
;
47 BOOLEAN gResetRequired
;
48 EFI_HII_HANDLE gHiiHandle
;
50 EFI_SCREEN_DESCRIPTOR gScreenDimensions
;
51 BROWSER_SETTING_SCOPE gBrowserSettingScope
= FormSetLevel
;
52 BOOLEAN mBrowserScopeFirstSet
= TRUE
;
53 EXIT_HANDLER ExitHandlerFunction
= NULL
;
57 // Browser Global Strings
60 CHAR16
*gDiscardFailed
;
61 CHAR16
*gDefaultFailed
;
63 CHAR16
*gEnterCommitString
;
64 CHAR16
*gEnterEscapeString
;
65 CHAR16
*gEscapeString
;
66 CHAR16
*gMoveHighlight
;
67 CHAR16
*gMakeSelection
;
68 CHAR16
*gDecNumericInput
;
69 CHAR16
*gHexNumericInput
;
70 CHAR16
*gToggleCheckBox
;
71 CHAR16
*gPromptForData
;
72 CHAR16
*gPromptForPassword
;
73 CHAR16
*gPromptForNewPassword
;
74 CHAR16
*gConfirmPassword
;
75 CHAR16
*gConfirmError
;
76 CHAR16
*gPassowordInvalid
;
85 CHAR16
*gAdjustNumber
;
87 CHAR16
*gOptionMismatch
;
88 CHAR16
*gFormSuppress
;
89 CHAR16
*gProtocolNotFound
;
91 CHAR16
*mUnknownString
= L
"!";
93 CHAR16 gPromptBlockWidth
;
94 CHAR16 gOptionBlockWidth
;
95 CHAR16 gHelpBlockWidth
;
97 EFI_GUID gZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
98 EFI_GUID gSetupBrowserGuid
= {
99 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
102 FORM_BROWSER_FORMSET
*gOldFormSet
= NULL
;
104 FUNCTIION_KEY_SETTING gFunctionKeySettingTable
[] = {
124 NONE_FUNCTION_KEY_SETTING
145 NONE_FUNCTION_KEY_SETTING
166 NONE_FUNCTION_KEY_SETTING
169 // BMM File Explorer FormSet.
187 NONE_FUNCTION_KEY_SETTING
192 This is the routine which an external caller uses to direct the browser
193 where to obtain it's information.
196 @param This The Form Browser protocol instanse.
197 @param Handles A pointer to an array of Handles. If HandleCount > 1 we
198 display a list of the formsets for the handles specified.
199 @param HandleCount The number of Handles specified in Handle.
200 @param FormSetGuid This field points to the EFI_GUID which must match the Guid
201 field in the EFI_IFR_FORM_SET op-code for the specified
202 forms-based package. If FormSetGuid is NULL, then this
203 function will display the first found forms package.
204 @param FormId This field specifies which EFI_IFR_FORM to render as the first
205 displayable page. If this field has a value of 0x0000, then
206 the forms browser will render the specified forms in their encoded order.
207 @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
209 @param ActionRequest Points to the action recommended by the form.
211 @retval EFI_SUCCESS The function completed successfully.
212 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
213 @retval EFI_NOT_FOUND No valid forms could be found to display.
219 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
220 IN EFI_HII_HANDLE
*Handles
,
221 IN UINTN HandleCount
,
222 IN EFI_GUID
*FormSetGuid
, OPTIONAL
223 IN UINT16 FormId
, OPTIONAL
224 IN CONST EFI_SCREEN_DESCRIPTOR
*ScreenDimensions
, OPTIONAL
225 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest OPTIONAL
229 UI_MENU_SELECTION
*Selection
;
231 FORM_BROWSER_FORMSET
*FormSet
;
235 // Calculate total number of Register HotKeys.
238 Link
= GetFirstNode (&gBrowserHotKeyList
);
239 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
240 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
244 // Show three HotKeys help information on one ROW.
246 gFooterHeight
= FOOTER_HEIGHT
+ (Index
/ 3);
249 // Clean the history menu list.
251 InitializeListHead (&gMenuList
);
254 // Save globals used by SendForm()
256 SaveBrowserContext ();
258 gResetRequired
= FALSE
;
259 Status
= EFI_SUCCESS
;
260 ZeroMem (&gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
263 // Seed the dimensions in the global
265 gST
->ConOut
->QueryMode (
267 gST
->ConOut
->Mode
->Mode
,
268 &gScreenDimensions
.RightColumn
,
269 &gScreenDimensions
.BottomRow
272 if (ScreenDimensions
!= NULL
) {
274 // Check local dimension vs. global dimension.
276 if ((gScreenDimensions
.RightColumn
< ScreenDimensions
->RightColumn
) ||
277 (gScreenDimensions
.BottomRow
< ScreenDimensions
->BottomRow
)
279 Status
= EFI_INVALID_PARAMETER
;
283 // Local dimension validation.
285 if ((ScreenDimensions
->RightColumn
> ScreenDimensions
->LeftColumn
) &&
286 (ScreenDimensions
->BottomRow
> ScreenDimensions
->TopRow
) &&
287 ((ScreenDimensions
->RightColumn
- ScreenDimensions
->LeftColumn
) > 2) &&
289 (ScreenDimensions
->BottomRow
- ScreenDimensions
->TopRow
) > STATUS_BAR_HEIGHT
+
290 SCROLL_ARROW_HEIGHT
*
292 FRONT_PAGE_HEADER_HEIGHT
+
297 CopyMem (&gScreenDimensions
, (VOID
*) ScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
299 Status
= EFI_INVALID_PARAMETER
;
305 gOptionBlockWidth
= (CHAR16
) ((gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
) / 3);
306 gPromptBlockWidth
= (CHAR16
) (gOptionBlockWidth
+ LEFT_SKIPPED_COLUMNS
);
307 gHelpBlockWidth
= (CHAR16
) (gOptionBlockWidth
- LEFT_SKIPPED_COLUMNS
);
310 // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
312 InitializeBrowserStrings ();
315 // Ensure we are in Text mode
317 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
319 for (Index
= 0; Index
< HandleCount
; Index
++) {
320 Selection
= AllocateZeroPool (sizeof (UI_MENU_SELECTION
));
321 ASSERT (Selection
!= NULL
);
323 Selection
->Handle
= Handles
[Index
];
324 if (FormSetGuid
!= NULL
) {
325 CopyMem (&Selection
->FormSetGuid
, FormSetGuid
, sizeof (EFI_GUID
));
326 Selection
->FormId
= FormId
;
328 CopyMem (&Selection
->FormSetGuid
, &gEfiHiiPlatformSetupFormsetGuid
, sizeof (EFI_GUID
));
332 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
333 ASSERT (FormSet
!= NULL
);
336 // Initialize internal data structures of FormSet
338 Status
= InitializeFormSet (Selection
->Handle
, &Selection
->FormSetGuid
, FormSet
, TRUE
);
339 if (EFI_ERROR (Status
) || IsListEmpty (&FormSet
->FormListHead
)) {
340 DestroyFormSet (FormSet
);
343 Selection
->FormSet
= FormSet
;
346 // Try to find pre FormSet in the maintain backup list.
348 gOldFormSet
= GetFormSetFromHiiHandle (Selection
->Handle
);
351 // Display this formset
353 gCurrentSelection
= Selection
;
355 Status
= SetupBrowser (Selection
);
357 gCurrentSelection
= NULL
;
359 if (EFI_ERROR (Status
)) {
363 } while (Selection
->Action
== UI_ACTION_REFRESH_FORMSET
);
365 if (gOldFormSet
!= NULL
) {
367 // If no data is changed, don't need to save current FormSet into the maintain list.
369 if (!IsNvUpdateRequired (gOldFormSet
)) {
370 RemoveEntryList (&gOldFormSet
->Link
);
371 DestroyFormSet (gOldFormSet
);
376 FreePool (Selection
);
379 if (ActionRequest
!= NULL
) {
380 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
381 if (gResetRequired
) {
382 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
386 FreeBrowserStrings ();
387 UiFreeMenuList(&gMenuList
);
389 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
390 gST
->ConOut
->ClearScreen (gST
->ConOut
);
394 // Restore globals used by SendForm()
396 RestoreBrowserContext ();
403 This function is called by a callback handler to retrieve uncommitted state
404 data from the browser.
406 @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
408 @param ResultsDataSize A pointer to the size of the buffer associated
410 @param ResultsData A string returned from an IFR browser or
411 equivalent. The results string will have no
412 routing information in them.
413 @param RetrieveData A BOOLEAN field which allows an agent to retrieve
414 (if RetrieveData = TRUE) data from the uncommitted
415 browser state information or set (if RetrieveData
416 = FALSE) data in the uncommitted browser state
418 @param VariableGuid An optional field to indicate the target variable
420 @param VariableName An optional field to indicate the target
421 human-readable variable name.
423 @retval EFI_SUCCESS The results have been distributed or are awaiting
425 @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
426 contain the results data.
432 IN CONST EFI_FORM_BROWSER2_PROTOCOL
*This
,
433 IN OUT UINTN
*ResultsDataSize
,
434 IN OUT EFI_STRING ResultsData
,
435 IN BOOLEAN RetrieveData
,
436 IN CONST EFI_GUID
*VariableGuid
, OPTIONAL
437 IN CONST CHAR16
*VariableName OPTIONAL
442 FORMSET_STORAGE
*Storage
;
443 FORM_BROWSER_FORMSET
*FormSet
;
450 if (ResultsDataSize
== NULL
|| ResultsData
== NULL
) {
451 return EFI_INVALID_PARAMETER
;
454 if (gCurrentSelection
== NULL
) {
455 return EFI_NOT_READY
;
460 FormSet
= gCurrentSelection
->FormSet
;
463 // Find target storage
465 Link
= GetFirstNode (&FormSet
->StorageListHead
);
466 if (IsNull (&FormSet
->StorageListHead
, Link
)) {
467 return EFI_UNSUPPORTED
;
470 if (VariableGuid
!= NULL
) {
472 // Try to find target storage
475 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
476 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
477 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
479 if (CompareGuid (&Storage
->BrowserStorage
->Guid
, (EFI_GUID
*) VariableGuid
)) {
480 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_BUFFER
||
481 Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
483 // Buffer storage require both GUID and Name
485 if (VariableName
== NULL
) {
486 return EFI_NOT_FOUND
;
489 if (StrCmp (Storage
->BrowserStorage
->Name
, (CHAR16
*) VariableName
) != 0) {
499 return EFI_NOT_FOUND
;
503 // GUID/Name is not specified, take the first storage in FormSet
505 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
510 // Skip if there is no RequestElement
512 if (Storage
->ElementCount
== 0) {
517 // Generate <ConfigResp>
519 Status
= StorageToConfigResp (Storage
->BrowserStorage
, &ConfigResp
, Storage
->ConfigRequest
);
520 if (EFI_ERROR (Status
)) {
525 // Skip <ConfigHdr> and '&' to point to <ConfigBody>
527 StrPtr
= ConfigResp
+ StrLen (Storage
->BrowserStorage
->ConfigHdr
) + 1;
529 BufferSize
= StrSize (StrPtr
);
530 if (*ResultsDataSize
< BufferSize
) {
531 *ResultsDataSize
= BufferSize
;
533 FreePool (ConfigResp
);
534 return EFI_BUFFER_TOO_SMALL
;
537 *ResultsDataSize
= BufferSize
;
538 CopyMem (ResultsData
, StrPtr
, BufferSize
);
540 FreePool (ConfigResp
);
543 // Prepare <ConfigResp>
545 TmpSize
= StrLen (ResultsData
);
546 BufferSize
= (TmpSize
+ StrLen (Storage
->BrowserStorage
->ConfigHdr
) + 2) * sizeof (CHAR16
);
547 ConfigResp
= AllocateZeroPool (BufferSize
);
548 ASSERT (ConfigResp
!= NULL
);
550 StrCpy (ConfigResp
, Storage
->BrowserStorage
->ConfigHdr
);
551 StrCat (ConfigResp
, L
"&");
552 StrCat (ConfigResp
, ResultsData
);
555 // Update Browser uncommited data
557 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, ConfigResp
);
558 if (EFI_ERROR (Status
)) {
567 Initialize Setup Browser driver.
569 @param ImageHandle The image handle.
570 @param SystemTable The system table.
572 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
573 @return Other value if failed to initialize the Setup Browser module.
579 IN EFI_HANDLE ImageHandle
,
580 IN EFI_SYSTEM_TABLE
*SystemTable
584 EFI_INPUT_KEY DefaultHotKey
;
585 EFI_STRING HelpString
;
588 // Locate required Hii relative protocols
590 Status
= gBS
->LocateProtocol (
591 &gEfiHiiDatabaseProtocolGuid
,
593 (VOID
**) &mHiiDatabase
595 ASSERT_EFI_ERROR (Status
);
597 Status
= gBS
->LocateProtocol (
598 &gEfiHiiStringProtocolGuid
,
600 (VOID
**) &mHiiString
602 ASSERT_EFI_ERROR (Status
);
604 Status
= gBS
->LocateProtocol (
605 &gEfiHiiConfigRoutingProtocolGuid
,
607 (VOID
**) &mHiiConfigRouting
609 ASSERT_EFI_ERROR (Status
);
611 Status
= gBS
->LocateProtocol (
612 &gEfiDevicePathFromTextProtocolGuid
,
614 (VOID
**) &mPathFromText
618 // Publish our HII data
620 gHiiHandle
= HiiAddPackages (
626 ASSERT (gHiiHandle
!= NULL
);
629 // Initialize Driver private data
631 gBannerData
= AllocateZeroPool (sizeof (BANNER_DATA
));
632 ASSERT (gBannerData
!= NULL
);
635 // Initialize generic help strings.
637 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
638 gDiscardFailed
= GetToken (STRING_TOKEN (DISCARD_FAILED
), gHiiHandle
);
639 gDefaultFailed
= GetToken (STRING_TOKEN (DEFAULT_FAILED
), gHiiHandle
);
642 // Install FormBrowser2 protocol
644 mPrivateData
.Handle
= NULL
;
645 Status
= gBS
->InstallProtocolInterface (
646 &mPrivateData
.Handle
,
647 &gEfiFormBrowser2ProtocolGuid
,
648 EFI_NATIVE_INTERFACE
,
649 &mPrivateData
.FormBrowser2
651 ASSERT_EFI_ERROR (Status
);
654 // Install default HotKey F10 for Save
656 DefaultHotKey
.UnicodeChar
= CHAR_NULL
;
657 HelpString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
658 DefaultHotKey
.ScanCode
= SCAN_F10
;
659 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_SUBMIT
, 0, HelpString
);
660 FreePool (HelpString
);
662 // Install default HotKey F9 for Reset To Defaults
664 DefaultHotKey
.ScanCode
= SCAN_F9
;
665 HelpString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
666 RegisterHotKey (&DefaultHotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, HelpString
);
667 FreePool (HelpString
);
670 // Install FormBrowserEx protocol
672 mPrivateData
.Handle
= NULL
;
673 Status
= gBS
->InstallProtocolInterface (
674 &mPrivateData
.Handle
,
675 &gEfiFormBrowserExProtocolGuid
,
676 EFI_NATIVE_INTERFACE
,
677 &mPrivateData
.FormBrowserEx
679 ASSERT_EFI_ERROR (Status
);
686 Create a new string in HII Package List.
688 @param String The String to be added
689 @param HiiHandle The package list in the HII database to insert the
692 @return The output string.
698 IN EFI_HII_HANDLE HiiHandle
701 EFI_STRING_ID StringId
;
703 StringId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
704 ASSERT (StringId
!= 0);
711 Delete a string from HII Package List.
713 @param StringId Id of the string in HII database.
714 @param HiiHandle The HII package list handle.
716 @retval EFI_SUCCESS The string was deleted successfully.
721 IN EFI_STRING_ID StringId
,
722 IN EFI_HII_HANDLE HiiHandle
727 NullChar
= CHAR_NULL
;
728 HiiSetString (HiiHandle
, StringId
, &NullChar
, NULL
);
734 Get the string based on the StringId and HII Package List Handle.
736 @param Token The String's ID.
737 @param HiiHandle The package list in the HII database to search for
738 the specified string.
740 @return The output string.
745 IN EFI_STRING_ID Token
,
746 IN EFI_HII_HANDLE HiiHandle
751 if (HiiHandle
== NULL
) {
755 String
= HiiGetString (HiiHandle
, Token
, NULL
);
756 if (String
== NULL
) {
757 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
758 ASSERT (String
!= NULL
);
760 return (CHAR16
*) String
;
765 Allocate new memory and then copy the Unicode string Source to Destination.
767 @param Dest Location to copy string
768 @param Src String to copy
773 IN OUT CHAR16
**Dest
,
780 *Dest
= AllocateCopyPool (StrSize (Src
), Src
);
781 ASSERT (*Dest
!= NULL
);
786 Allocate new memory and concatinate Source on the end of Destination.
788 @param Dest String to added to the end of.
789 @param Src String to concatinate.
794 IN OUT CHAR16
**Dest
,
802 NewStringCpy (Dest
, Src
);
806 TmpSize
= StrSize (*Dest
);
807 NewString
= AllocateZeroPool (TmpSize
+ StrSize (Src
) - 1);
808 ASSERT (NewString
!= NULL
);
810 StrCpy (NewString
, *Dest
);
811 StrCat (NewString
, Src
);
819 Synchronize or restore Storage's Edit copy and Shadow copy.
821 @param Storage The Storage to be synchronized.
822 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
824 if TRUE, copy the editbuffer to the buffer.
825 if FALSE, copy the buffer to the editbuffer.
830 IN BROWSER_STORAGE
*Storage
,
831 IN BOOLEAN SyncOrRestore
835 NAME_VALUE_NODE
*Node
;
837 switch (Storage
->Type
) {
838 case EFI_HII_VARSTORE_BUFFER
:
839 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
841 CopyMem (Storage
->Buffer
, Storage
->EditBuffer
, Storage
->Size
);
843 CopyMem (Storage
->EditBuffer
, Storage
->Buffer
, Storage
->Size
);
847 case EFI_HII_VARSTORE_NAME_VALUE
:
848 Link
= GetFirstNode (&Storage
->NameValueListHead
);
849 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
850 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
853 NewStringCpy (&Node
->Value
, Node
->EditValue
);
855 NewStringCpy (&Node
->EditValue
, Node
->Value
);
858 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
862 case EFI_HII_VARSTORE_EFI_VARIABLE
:
870 Get Value for given Name from a NameValue Storage.
872 @param Storage The NameValue Storage.
873 @param Name The Name.
874 @param Value The retured Value.
875 @param GetValueFrom Where to get source value, from EditValue or Value.
877 @retval EFI_SUCCESS Value found for given Name.
878 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
883 IN BROWSER_STORAGE
*Storage
,
885 IN OUT CHAR16
**Value
,
886 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
890 NAME_VALUE_NODE
*Node
;
892 if (GetValueFrom
!= GetSetValueWithEditBuffer
&& GetValueFrom
!= GetSetValueWithBuffer
) {
893 return EFI_INVALID_PARAMETER
;
898 Link
= GetFirstNode (&Storage
->NameValueListHead
);
899 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
900 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
902 if (StrCmp (Name
, Node
->Name
) == 0) {
903 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
904 NewStringCpy (Value
, Node
->EditValue
);
906 NewStringCpy (Value
, Node
->Value
);
911 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
914 return EFI_NOT_FOUND
;
919 Set Value of given Name in a NameValue Storage.
921 @param Storage The NameValue Storage.
922 @param Name The Name.
923 @param Value The Value to set.
924 @param SetValueTo Whether update editValue or Value.
926 @retval EFI_SUCCESS Value found for given Name.
927 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
932 IN BROWSER_STORAGE
*Storage
,
935 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
939 NAME_VALUE_NODE
*Node
;
942 if (SetValueTo
!= GetSetValueWithEditBuffer
&& SetValueTo
!= GetSetValueWithBuffer
) {
943 return EFI_INVALID_PARAMETER
;
946 Link
= GetFirstNode (&Storage
->NameValueListHead
);
947 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
948 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
950 if (StrCmp (Name
, Node
->Name
) == 0) {
951 if (SetValueTo
== GetSetValueWithEditBuffer
) {
952 Buffer
= Node
->EditValue
;
954 Buffer
= Node
->Value
;
956 if (Buffer
!= NULL
) {
959 Buffer
= AllocateCopyPool (StrSize (Value
), Value
);
960 ASSERT (Buffer
!= NULL
);
961 if (SetValueTo
== GetSetValueWithEditBuffer
) {
962 Node
->EditValue
= Buffer
;
964 Node
->Value
= Buffer
;
969 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
972 return EFI_NOT_FOUND
;
977 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
979 @param Storage The Storage to be conveted.
980 @param ConfigResp The returned <ConfigResp>.
981 @param ConfigRequest The ConfigRequest string.
983 @retval EFI_SUCCESS Convert success.
984 @retval EFI_INVALID_PARAMETER Incorrect storage type.
988 StorageToConfigResp (
989 IN BROWSER_STORAGE
*Storage
,
990 IN CHAR16
**ConfigResp
,
991 IN CHAR16
*ConfigRequest
997 NAME_VALUE_NODE
*Node
;
999 Status
= EFI_SUCCESS
;
1001 switch (Storage
->Type
) {
1002 case EFI_HII_VARSTORE_BUFFER
:
1003 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1004 Status
= mHiiConfigRouting
->BlockToConfig (
1007 Storage
->EditBuffer
,
1014 case EFI_HII_VARSTORE_NAME_VALUE
:
1016 NewStringCat (ConfigResp
, Storage
->ConfigHdr
);
1018 Link
= GetFirstNode (&Storage
->NameValueListHead
);
1019 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
1020 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
1022 if (StrStr (ConfigRequest
, Node
->Name
) != NULL
) {
1023 NewStringCat (ConfigResp
, L
"&");
1024 NewStringCat (ConfigResp
, Node
->Name
);
1025 NewStringCat (ConfigResp
, L
"=");
1026 NewStringCat (ConfigResp
, Node
->EditValue
);
1028 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
1032 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1034 Status
= EFI_INVALID_PARAMETER
;
1043 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
1045 @param Storage The Storage to receive the settings.
1046 @param ConfigResp The <ConfigResp> to be converted.
1048 @retval EFI_SUCCESS Convert success.
1049 @retval EFI_INVALID_PARAMETER Incorrect storage type.
1053 ConfigRespToStorage (
1054 IN BROWSER_STORAGE
*Storage
,
1055 IN CHAR16
*ConfigResp
1059 EFI_STRING Progress
;
1065 Status
= EFI_SUCCESS
;
1067 switch (Storage
->Type
) {
1068 case EFI_HII_VARSTORE_BUFFER
:
1069 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1070 BufferSize
= Storage
->Size
;
1071 Status
= mHiiConfigRouting
->ConfigToBlock (
1074 Storage
->EditBuffer
,
1080 case EFI_HII_VARSTORE_NAME_VALUE
:
1081 StrPtr
= StrStr (ConfigResp
, L
"PATH");
1082 if (StrPtr
== NULL
) {
1085 StrPtr
= StrStr (ConfigResp
, L
"&");
1086 while (StrPtr
!= NULL
) {
1090 StrPtr
= StrPtr
+ 1;
1092 StrPtr
= StrStr (StrPtr
, L
"=");
1093 if (StrPtr
== NULL
) {
1101 StrPtr
= StrPtr
+ 1;
1103 StrPtr
= StrStr (StrPtr
, L
"&");
1104 if (StrPtr
!= NULL
) {
1107 SetValueByName (Storage
, Name
, Value
, GetSetValueWithEditBuffer
);
1111 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1113 Status
= EFI_INVALID_PARAMETER
;
1122 Get Question's current Value.
1124 @param FormSet FormSet data structure.
1125 @param Form Form data structure.
1126 @param Question Question to be initialized.
1127 @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1129 @retval EFI_SUCCESS The function completed successfully.
1134 IN FORM_BROWSER_FORMSET
*FormSet
,
1135 IN FORM_BROWSER_FORM
*Form
,
1136 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1137 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1146 BROWSER_STORAGE
*Storage
;
1147 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1148 CHAR16
*ConfigRequest
;
1156 BOOLEAN IsBufferStorage
;
1162 Status
= EFI_SUCCESS
;
1166 if (GetValueFrom
>= GetSetValueWithMax
) {
1167 return EFI_INVALID_PARAMETER
;
1171 // Statement don't have storage, skip them
1173 if (Question
->QuestionId
== 0) {
1178 // Question value is provided by an Expression, evaluate it
1180 if (Question
->ValueExpression
!= NULL
) {
1181 Status
= EvaluateExpression (FormSet
, Form
, Question
->ValueExpression
);
1182 if (!EFI_ERROR (Status
)) {
1183 if (Question
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1184 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1185 if (Question
->StorageWidth
> Question
->ValueExpression
->Result
.BufferLen
) {
1186 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->ValueExpression
->Result
.BufferLen
);
1187 Question
->HiiValue
.BufferLen
= Question
->ValueExpression
->Result
.BufferLen
;
1189 CopyMem (Question
->HiiValue
.Buffer
, Question
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
1190 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1192 FreePool (Question
->ValueExpression
->Result
.Buffer
);
1194 Question
->HiiValue
.Type
= Question
->ValueExpression
->Result
.Type
;
1195 CopyMem (&Question
->HiiValue
.Value
, &Question
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1201 // Get question value by read expression.
1203 if (Question
->ReadExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1204 Status
= EvaluateExpression (FormSet
, Form
, Question
->ReadExpression
);
1205 if (!EFI_ERROR (Status
) &&
1206 ((Question
->ReadExpression
->Result
.Type
< EFI_IFR_TYPE_OTHER
) || (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
))) {
1208 // Only update question value to the valid result.
1210 if (Question
->ReadExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
1211 ASSERT (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
&& Question
->HiiValue
.Buffer
!= NULL
);
1212 if (Question
->StorageWidth
> Question
->ReadExpression
->Result
.BufferLen
) {
1213 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->ReadExpression
->Result
.BufferLen
);
1214 Question
->HiiValue
.BufferLen
= Question
->ReadExpression
->Result
.BufferLen
;
1216 CopyMem (Question
->HiiValue
.Buffer
, Question
->ReadExpression
->Result
.Buffer
, Question
->StorageWidth
);
1217 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
1219 FreePool (Question
->ReadExpression
->Result
.Buffer
);
1221 Question
->HiiValue
.Type
= Question
->ReadExpression
->Result
.Type
;
1222 CopyMem (&Question
->HiiValue
.Value
, &Question
->ReadExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1228 // Question value is provided by RTC
1230 Storage
= Question
->Storage
;
1231 QuestionValue
= &Question
->HiiValue
.Value
;
1232 if (Storage
== NULL
) {
1234 // It's a Question without storage, or RTC date/time
1236 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1238 // Date and time define the same Flags bit
1240 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1241 case QF_DATE_STORAGE_TIME
:
1242 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1245 case QF_DATE_STORAGE_WAKEUP
:
1246 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1249 case QF_DATE_STORAGE_NORMAL
:
1252 // For date/time without storage
1257 if (EFI_ERROR (Status
)) {
1261 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1262 QuestionValue
->date
.Year
= EfiTime
.Year
;
1263 QuestionValue
->date
.Month
= EfiTime
.Month
;
1264 QuestionValue
->date
.Day
= EfiTime
.Day
;
1266 QuestionValue
->time
.Hour
= EfiTime
.Hour
;
1267 QuestionValue
->time
.Minute
= EfiTime
.Minute
;
1268 QuestionValue
->time
.Second
= EfiTime
.Second
;
1276 // Question value is provided by EFI variable
1278 StorageWidth
= Question
->StorageWidth
;
1279 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1280 if (Question
->BufferValue
!= NULL
) {
1281 Dst
= Question
->BufferValue
;
1283 Dst
= (UINT8
*) QuestionValue
;
1286 Status
= gRT
->GetVariable (
1287 Question
->VariableName
,
1294 // Always return success, even this EFI variable doesn't exist
1300 // Question Value is provided by Buffer Storage or NameValue Storage
1302 if (Question
->BufferValue
!= NULL
) {
1304 // This Question is password or orderedlist
1306 Dst
= Question
->BufferValue
;
1309 // Other type of Questions
1311 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
1314 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1315 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1316 IsBufferStorage
= TRUE
;
1318 IsBufferStorage
= FALSE
;
1320 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1321 if (GetValueFrom
== GetSetValueWithEditBuffer
|| GetValueFrom
== GetSetValueWithBuffer
) {
1322 if (IsBufferStorage
) {
1323 if (GetValueFrom
== GetSetValueWithEditBuffer
) {
1325 // Copy from storage Edit buffer
1327 CopyMem (Dst
, Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1330 // Copy from storage Edit buffer
1332 CopyMem (Dst
, Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1336 Status
= GetValueByName (Storage
, Question
->VariableName
, &Value
, GetValueFrom
);
1337 if (EFI_ERROR (Status
)) {
1341 ASSERT (Value
!= NULL
);
1342 LengthStr
= StrLen (Value
);
1343 Status
= EFI_SUCCESS
;
1346 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1347 // Add string tail char L'\0' into Length
1349 Length
= StorageWidth
+ sizeof (CHAR16
);
1350 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1351 Status
= EFI_BUFFER_TOO_SMALL
;
1353 StringPtr
= (CHAR16
*) Dst
;
1354 ZeroMem (TemStr
, sizeof (TemStr
));
1355 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1356 StrnCpy (TemStr
, Value
+ Index
, 4);
1357 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1360 // Add tailing L'\0' character
1362 StringPtr
[Index
/4] = L
'\0';
1365 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1366 Status
= EFI_BUFFER_TOO_SMALL
;
1368 ZeroMem (TemStr
, sizeof (TemStr
));
1369 for (Index
= 0; Index
< LengthStr
; Index
++) {
1370 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1371 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1372 if ((Index
& 1) == 0) {
1373 Dst
[Index
/2] = DigitUint8
;
1375 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1384 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1386 // Request current settings from Configuration Driver
1388 if (FormSet
->ConfigAccess
== NULL
) {
1389 return EFI_NOT_FOUND
;
1393 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1394 // <ConfigHdr> + "&" + <VariableName>
1396 if (IsBufferStorage
) {
1397 Length
= StrLen (Storage
->ConfigHdr
);
1398 Length
+= StrLen (Question
->BlockName
);
1400 Length
= StrLen (Storage
->ConfigHdr
);
1401 Length
+= StrLen (Question
->VariableName
) + 1;
1403 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
1404 ASSERT (ConfigRequest
!= NULL
);
1406 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
1407 if (IsBufferStorage
) {
1408 StrCat (ConfigRequest
, Question
->BlockName
);
1410 StrCat (ConfigRequest
, L
"&");
1411 StrCat (ConfigRequest
, Question
->VariableName
);
1414 Status
= FormSet
->ConfigAccess
->ExtractConfig (
1415 FormSet
->ConfigAccess
,
1420 FreePool (ConfigRequest
);
1421 if (EFI_ERROR (Status
)) {
1426 // Skip <ConfigRequest>
1428 if (IsBufferStorage
) {
1429 Value
= StrStr (Result
, L
"&VALUE");
1430 if (Value
== NULL
) {
1432 return EFI_NOT_FOUND
;
1439 Value
= Result
+ Length
;
1441 if (*Value
!= '=') {
1443 return EFI_NOT_FOUND
;
1446 // Skip '=', point to value
1451 // Suppress <AltResp> if any
1454 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1459 LengthStr
= StrLen (Value
);
1460 Status
= EFI_SUCCESS
;
1461 if (!IsBufferStorage
&& IsString
) {
1463 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
1464 // Add string tail char L'\0' into Length
1466 Length
= StorageWidth
+ sizeof (CHAR16
);
1467 if (Length
< ((LengthStr
/ 4 + 1) * 2)) {
1468 Status
= EFI_BUFFER_TOO_SMALL
;
1470 StringPtr
= (CHAR16
*) Dst
;
1471 ZeroMem (TemStr
, sizeof (TemStr
));
1472 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
1473 StrnCpy (TemStr
, Value
+ Index
, 4);
1474 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
1477 // Add tailing L'\0' character
1479 StringPtr
[Index
/4] = L
'\0';
1482 if (StorageWidth
< ((LengthStr
+ 1) / 2)) {
1483 Status
= EFI_BUFFER_TOO_SMALL
;
1485 ZeroMem (TemStr
, sizeof (TemStr
));
1486 for (Index
= 0; Index
< LengthStr
; Index
++) {
1487 TemStr
[0] = Value
[LengthStr
- Index
- 1];
1488 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
1489 if ((Index
& 1) == 0) {
1490 Dst
[Index
/2] = DigitUint8
;
1492 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
1498 if (EFI_ERROR (Status
)) {
1502 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1504 TemBuffer
= AllocateZeroPool (Storage
->Size
);
1505 if (TemBuffer
== NULL
) {
1506 Status
= EFI_OUT_OF_RESOURCES
;
1509 Length
= Storage
->Size
;
1510 Status
= gRT
->GetVariable (
1517 if (EFI_ERROR (Status
)) {
1518 FreePool (TemBuffer
);
1522 CopyMem (Dst
, TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, StorageWidth
);
1524 FreePool (TemBuffer
);
1528 // Synchronize Edit Buffer
1530 if (IsBufferStorage
) {
1531 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Dst
, StorageWidth
);
1533 SetValueByName (Storage
, Question
->VariableName
, Value
, GetSetValueWithEditBuffer
);
1536 if (Result
!= NULL
) {
1546 Save Question Value to edit copy(cached) or Storage(uncached).
1548 @param FormSet FormSet data structure.
1549 @param Form Form data structure.
1550 @param Question Pointer to the Question.
1551 @param SetValueTo Update the question value to editbuffer , buffer or hii driver.
1553 @retval EFI_SUCCESS The function completed successfully.
1558 IN FORM_BROWSER_FORMSET
*FormSet
,
1559 IN FORM_BROWSER_FORM
*Form
,
1560 IN OUT FORM_BROWSER_STATEMENT
*Question
,
1561 IN GET_SET_QUESTION_VALUE_WITH SetValueTo
1571 BROWSER_STORAGE
*Storage
;
1572 EFI_IFR_TYPE_VALUE
*QuestionValue
;
1577 BOOLEAN IsBufferStorage
;
1584 Status
= EFI_SUCCESS
;
1586 if (SetValueTo
>= GetSetValueWithMax
) {
1587 return EFI_INVALID_PARAMETER
;
1591 // Statement don't have storage, skip them
1593 if (Question
->QuestionId
== 0) {
1598 // If Question value is provided by an Expression, then it is read only
1600 if (Question
->ValueExpression
!= NULL
) {
1605 // Before set question value, evaluate its write expression.
1607 if (Question
->WriteExpression
!= NULL
&& Form
->FormType
== STANDARD_MAP_FORM_TYPE
) {
1608 Status
= EvaluateExpression (FormSet
, Form
, Question
->WriteExpression
);
1609 if (EFI_ERROR (Status
)) {
1615 // Question value is provided by RTC
1617 Storage
= Question
->Storage
;
1618 QuestionValue
= &Question
->HiiValue
.Value
;
1619 if (Storage
== NULL
) {
1621 // It's a Question without storage, or RTC date/time
1623 if (Question
->Operand
== EFI_IFR_DATE_OP
|| Question
->Operand
== EFI_IFR_TIME_OP
) {
1625 // Date and time define the same Flags bit
1627 switch (Question
->Flags
& EFI_QF_DATE_STORAGE
) {
1628 case QF_DATE_STORAGE_TIME
:
1629 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1632 case QF_DATE_STORAGE_WAKEUP
:
1633 Status
= gRT
->GetWakeupTime (&Enabled
, &Pending
, &EfiTime
);
1636 case QF_DATE_STORAGE_NORMAL
:
1639 // For date/time without storage
1644 if (EFI_ERROR (Status
)) {
1648 if (Question
->Operand
== EFI_IFR_DATE_OP
) {
1649 EfiTime
.Year
= QuestionValue
->date
.Year
;
1650 EfiTime
.Month
= QuestionValue
->date
.Month
;
1651 EfiTime
.Day
= QuestionValue
->date
.Day
;
1653 EfiTime
.Hour
= QuestionValue
->time
.Hour
;
1654 EfiTime
.Minute
= QuestionValue
->time
.Minute
;
1655 EfiTime
.Second
= QuestionValue
->time
.Second
;
1658 if ((Question
->Flags
& EFI_QF_DATE_STORAGE
) == QF_DATE_STORAGE_TIME
) {
1659 Status
= gRT
->SetTime (&EfiTime
);
1661 Status
= gRT
->SetWakeupTime (TRUE
, &EfiTime
);
1669 // Question value is provided by EFI variable
1671 StorageWidth
= Question
->StorageWidth
;
1672 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
1673 if (Question
->BufferValue
!= NULL
) {
1674 Src
= Question
->BufferValue
;
1676 Src
= (UINT8
*) QuestionValue
;
1679 Status
= gRT
->SetVariable (
1680 Question
->VariableName
,
1682 Storage
->Attributes
,
1690 // Question Value is provided by Buffer Storage or NameValue Storage
1692 if (Question
->BufferValue
!= NULL
) {
1693 Src
= Question
->BufferValue
;
1695 Src
= (UINT8
*) &Question
->HiiValue
.Value
;
1698 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
1699 Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1700 IsBufferStorage
= TRUE
;
1702 IsBufferStorage
= FALSE
;
1704 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
1706 if (SetValueTo
== GetSetValueWithEditBuffer
|| SetValueTo
== GetSetValueWithBuffer
) {
1707 if (IsBufferStorage
) {
1708 if (SetValueTo
== GetSetValueWithEditBuffer
) {
1710 // Copy to storage edit buffer
1712 CopyMem (Storage
->EditBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1713 } else if (SetValueTo
== GetSetValueWithBuffer
) {
1715 // Copy to storage edit buffer
1717 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1722 // Allocate enough string buffer.
1725 BufferLen
= ((StrLen ((CHAR16
*) Src
) * 4) + 1) * sizeof (CHAR16
);
1726 Value
= AllocateZeroPool (BufferLen
);
1727 ASSERT (Value
!= NULL
);
1729 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1731 TemName
= (CHAR16
*) Src
;
1733 for (; *TemName
!= L
'\0'; TemName
++) {
1734 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1737 BufferLen
= StorageWidth
* 2 + 1;
1738 Value
= AllocateZeroPool (BufferLen
* sizeof (CHAR16
));
1739 ASSERT (Value
!= NULL
);
1741 // Convert Buffer to Hex String
1743 TemBuffer
= Src
+ StorageWidth
- 1;
1745 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1746 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1750 Status
= SetValueByName (Storage
, Question
->VariableName
, Value
, SetValueTo
);
1753 } else if (SetValueTo
== GetSetValueWithHiiDriver
) {
1754 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
|| Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1756 // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
1757 // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
1759 if (IsBufferStorage
) {
1760 Length
= StrLen (Question
->BlockName
) + 7;
1762 Length
= StrLen (Question
->VariableName
) + 2;
1764 if (!IsBufferStorage
&& IsString
) {
1765 Length
+= (StrLen ((CHAR16
*) Src
) * 4);
1767 Length
+= (StorageWidth
* 2);
1769 ConfigResp
= AllocateZeroPool ((StrLen (Storage
->ConfigHdr
) + Length
+ 1) * sizeof (CHAR16
));
1770 ASSERT (ConfigResp
!= NULL
);
1772 StrCpy (ConfigResp
, Storage
->ConfigHdr
);
1773 if (IsBufferStorage
) {
1774 StrCat (ConfigResp
, Question
->BlockName
);
1775 StrCat (ConfigResp
, L
"&VALUE=");
1777 StrCat (ConfigResp
, L
"&");
1778 StrCat (ConfigResp
, Question
->VariableName
);
1779 StrCat (ConfigResp
, L
"=");
1782 Value
= ConfigResp
+ StrLen (ConfigResp
);
1784 if (!IsBufferStorage
&& IsString
) {
1786 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
1788 TemName
= (CHAR16
*) Src
;
1790 for (; *TemName
!= L
'\0'; TemName
++) {
1791 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
1795 // Convert Buffer to Hex String
1797 TemBuffer
= Src
+ StorageWidth
- 1;
1799 for (Index
= 0; Index
< StorageWidth
; Index
++, TemBuffer
--) {
1800 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
1805 // Convert to lower char.
1807 for (TemString
= Value
; *Value
!= L
'\0'; Value
++) {
1808 if (*Value
>= L
'A' && *Value
<= L
'Z') {
1809 *Value
= (CHAR16
) (*Value
- L
'A' + L
'a');
1814 // Submit Question Value to Configuration Driver
1816 if (FormSet
->ConfigAccess
!= NULL
) {
1817 Status
= FormSet
->ConfigAccess
->RouteConfig (
1818 FormSet
->ConfigAccess
,
1822 if (EFI_ERROR (Status
)) {
1823 FreePool (ConfigResp
);
1827 FreePool (ConfigResp
);
1829 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
1831 TemBuffer
= AllocateZeroPool(Storage
->Size
);
1832 if (TemBuffer
== NULL
) {
1833 Status
= EFI_OUT_OF_RESOURCES
;
1836 Length
= Storage
->Size
;
1837 Status
= gRT
->GetVariable (
1845 CopyMem (TemBuffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1847 Status
= gRT
->SetVariable (
1850 Storage
->Attributes
,
1854 FreePool (TemBuffer
);
1855 if (EFI_ERROR (Status
)){
1860 // Sync storage, from editbuffer to buffer.
1862 CopyMem (Storage
->Buffer
+ Question
->VarStoreInfo
.VarOffset
, Src
, StorageWidth
);
1870 Perform inconsistent check for a Form.
1872 @param FormSet FormSet data structure.
1873 @param Form Form data structure.
1874 @param Question The Question to be validated.
1875 @param Type Validation type: InConsistent or NoSubmit
1877 @retval EFI_SUCCESS Form validation pass.
1878 @retval other Form validation failed.
1883 IN FORM_BROWSER_FORMSET
*FormSet
,
1884 IN FORM_BROWSER_FORM
*Form
,
1885 IN FORM_BROWSER_STATEMENT
*Question
,
1891 LIST_ENTRY
*ListHead
;
1894 FORM_EXPRESSION
*Expression
;
1896 if (Type
== EFI_HII_EXPRESSION_INCONSISTENT_IF
) {
1897 ListHead
= &Question
->InconsistentListHead
;
1898 } else if (Type
== EFI_HII_EXPRESSION_NO_SUBMIT_IF
) {
1899 ListHead
= &Question
->NoSubmitListHead
;
1901 return EFI_UNSUPPORTED
;
1904 Link
= GetFirstNode (ListHead
);
1905 while (!IsNull (ListHead
, Link
)) {
1906 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
1909 // Evaluate the expression
1911 Status
= EvaluateExpression (FormSet
, Form
, Expression
);
1912 if (EFI_ERROR (Status
)) {
1916 if ((Expression
->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
) && Expression
->Result
.Value
.b
) {
1918 // Condition meet, show up error message
1920 if (Expression
->Error
!= 0) {
1921 PopUp
= GetToken (Expression
->Error
, FormSet
->HiiHandle
);
1923 CreateDialog (4, TRUE
, 0, NULL
, &Key
, gEmptyString
, PopUp
, gPressEnter
, gEmptyString
);
1924 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1928 return EFI_NOT_READY
;
1931 Link
= GetNextNode (ListHead
, Link
);
1939 Perform NoSubmit check for each Form in FormSet.
1941 @param FormSet FormSet data structure.
1942 @param CurrentForm Current input form data structure.
1944 @retval EFI_SUCCESS Form validation pass.
1945 @retval other Form validation failed.
1950 IN FORM_BROWSER_FORMSET
*FormSet
,
1951 IN FORM_BROWSER_FORM
*CurrentForm
1956 FORM_BROWSER_STATEMENT
*Question
;
1957 FORM_BROWSER_FORM
*Form
;
1958 LIST_ENTRY
*LinkForm
;
1960 LinkForm
= GetFirstNode (&FormSet
->FormListHead
);
1961 while (!IsNull (&FormSet
->FormListHead
, LinkForm
)) {
1962 Form
= FORM_BROWSER_FORM_FROM_LINK (LinkForm
);
1963 LinkForm
= GetNextNode (&FormSet
->FormListHead
, LinkForm
);
1965 if (CurrentForm
!= NULL
&& CurrentForm
!= Form
) {
1969 Link
= GetFirstNode (&Form
->StatementListHead
);
1970 while (!IsNull (&Form
->StatementListHead
, Link
)) {
1971 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
1973 Status
= ValidateQuestion (FormSet
, Form
, Question
, EFI_HII_EXPRESSION_NO_SUBMIT_IF
);
1974 if (EFI_ERROR (Status
)) {
1978 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
1986 Fill storage's edit copy with settings requested from Configuration Driver.
1988 @param FormSet FormSet data structure.
1989 @param ConfigInfo The config info related to this form.
1990 @param SyncOrRestore Sync the buffer to editbuffer or Restore the
1991 editbuffer to buffer
1992 if TRUE, copy the editbuffer to the buffer.
1993 if FALSE, copy the buffer to the editbuffer.
1995 @retval EFI_SUCCESS The function completed successfully.
1999 SynchronizeStorageForForm (
2000 IN FORM_BROWSER_FORMSET
*FormSet
,
2001 IN FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
,
2002 IN BOOLEAN SyncOrRestore
2006 EFI_STRING Progress
;
2010 NAME_VALUE_NODE
*Node
;
2014 Status
= EFI_SUCCESS
;
2016 if (FormSet
->ConfigAccess
== NULL
&& ConfigInfo
->Storage
->Type
!= EFI_HII_VARSTORE_NAME_VALUE
) {
2017 return EFI_NOT_FOUND
;
2020 if (ConfigInfo
->ElementCount
== 0) {
2022 // Skip if there is no RequestElement
2027 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2028 (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2029 BufferSize
= ConfigInfo
->Storage
->Size
;
2031 if (SyncOrRestore
) {
2032 Src
= ConfigInfo
->Storage
->EditBuffer
;
2033 Dst
= ConfigInfo
->Storage
->Buffer
;
2035 Src
= ConfigInfo
->Storage
->Buffer
;
2036 Dst
= ConfigInfo
->Storage
->EditBuffer
;
2039 Status
= mHiiConfigRouting
->BlockToConfig(
2041 ConfigInfo
->ConfigRequest
,
2047 if (EFI_ERROR (Status
)) {
2051 Status
= mHiiConfigRouting
->ConfigToBlock (
2058 if (Result
!= NULL
) {
2061 } else if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2062 Link
= GetFirstNode (&ConfigInfo
->Storage
->NameValueListHead
);
2063 while (!IsNull (&ConfigInfo
->Storage
->NameValueListHead
, Link
)) {
2064 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
2066 if (StrStr (ConfigInfo
->ConfigRequest
, Node
->Name
) != NULL
) {
2067 if (SyncOrRestore
) {
2068 NewStringCpy (&Node
->Value
, Node
->EditValue
);
2070 NewStringCpy (&Node
->EditValue
, Node
->Value
);
2074 Link
= GetNextNode (&ConfigInfo
->Storage
->NameValueListHead
, Link
);
2082 When discard the question value, call the callback function with Changed type
2083 to inform the hii driver.
2085 @param FormSet FormSet data structure.
2086 @param Form Form data structure.
2090 SendDiscardInfoToDriver (
2091 IN FORM_BROWSER_FORMSET
*FormSet
,
2092 IN FORM_BROWSER_FORM
*Form
2096 FORM_BROWSER_STATEMENT
*Question
;
2098 EFI_HII_VALUE HiiValue
;
2100 BOOLEAN ValueChanged
;
2101 EFI_IFR_TYPE_VALUE
*TypeValue
;
2102 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2104 ValueChanged
= FALSE
;
2107 if(!Form
->NvUpdateRequired
) {
2111 Link
= GetFirstNode (&Form
->StatementListHead
);
2112 while (!IsNull (&Form
->StatementListHead
, Link
)) {
2113 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
2114 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
2116 if (Question
->Storage
== NULL
|| Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2120 if (Question
->Operand
== EFI_IFR_PASSWORD_OP
) {
2124 if (Question
->BufferValue
!= NULL
) {
2125 BufferValue
= AllocateZeroPool (Question
->StorageWidth
);
2126 ASSERT (BufferValue
!= NULL
);
2127 CopyMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
);
2129 HiiValue
.Type
= Question
->HiiValue
.Type
;
2130 CopyMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2133 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithBuffer
);
2134 if (EFI_ERROR (Status
)) {
2135 if (BufferValue
!= NULL
) {
2136 FreePool (BufferValue
);
2142 if (Question
->BufferValue
!= NULL
) {
2143 if (CompareMem (BufferValue
, Question
->BufferValue
, Question
->StorageWidth
)) {
2144 ValueChanged
= TRUE
;
2147 if (CompareMem (&HiiValue
.Value
, &Question
->HiiValue
.Value
, sizeof (EFI_IFR_TYPE_VALUE
))) {
2148 ValueChanged
= TRUE
;
2152 if (BufferValue
!= NULL
) {
2153 FreePool (BufferValue
);
2157 if (!ValueChanged
) {
2161 ValueChanged
= FALSE
;
2163 if (Question
->HiiValue
.Type
== EFI_IFR_TYPE_BUFFER
) {
2164 TypeValue
= (EFI_IFR_TYPE_VALUE
*) Question
->BufferValue
;
2166 TypeValue
= &Question
->HiiValue
.Value
;
2169 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2170 FormSet
->ConfigAccess
->Callback (
2171 FormSet
->ConfigAccess
,
2172 EFI_BROWSER_ACTION_CHANGED
,
2173 Question
->QuestionId
,
2174 Question
->HiiValue
.Type
,
2182 Validate the FormSet. If the formset is not validate, remove it from the list.
2184 @param FormSet The input FormSet which need to validate.
2186 @retval TRUE The handle is validate.
2187 @retval FALSE The handle is invalidate.
2192 FORM_BROWSER_FORMSET
*FormSet
2195 EFI_HII_HANDLE
*HiiHandles
;
2199 ASSERT (FormSet
!= NULL
);
2202 // Get all the Hii handles
2204 HiiHandles
= HiiGetHiiHandles (NULL
);
2205 ASSERT (HiiHandles
!= NULL
);
2208 // Search for formset of each class type
2210 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2211 if (HiiHandles
[Index
] == FormSet
->HiiHandle
) {
2218 RemoveEntryList (&FormSet
->Link
);
2219 DestroyFormSet (FormSet
);
2222 FreePool (HiiHandles
);
2228 Discard data based on the input setting scope (Form, FormSet or System).
2230 @param FormSet FormSet data structure.
2231 @param Form Form data structure.
2232 @param SettingScope Setting Scope for Discard action.
2234 @retval EFI_SUCCESS The function completed successfully.
2235 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2240 IN FORM_BROWSER_FORMSET
*FormSet
,
2241 IN FORM_BROWSER_FORM
*Form
,
2242 IN BROWSER_SETTING_SCOPE SettingScope
2246 FORMSET_STORAGE
*Storage
;
2247 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2248 FORM_BROWSER_FORMSET
*LocalFormSet
;
2251 // Check the supported setting level.
2253 if (SettingScope
>= MaxLevel
) {
2254 return EFI_UNSUPPORTED
;
2257 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2259 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2260 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2261 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2262 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2264 if (ConfigInfo
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2269 // Skip if there is no RequestElement
2271 if (ConfigInfo
->ElementCount
== 0) {
2276 // Prepare <ConfigResp>
2278 SynchronizeStorageForForm(FormSet
, ConfigInfo
, FALSE
);
2281 // Call callback with Changed type to inform the driver.
2283 SendDiscardInfoToDriver (FormSet
, Form
);
2286 Form
->NvUpdateRequired
= FALSE
;
2287 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2290 // Discard Buffer storage or Name/Value storage
2292 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2293 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2294 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
2295 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2297 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2302 // Skip if there is no RequestElement
2304 if (Storage
->ElementCount
== 0) {
2308 SynchronizeStorage(Storage
->BrowserStorage
, FALSE
);
2311 Link
= GetFirstNode (&FormSet
->FormListHead
);
2312 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2313 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2314 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2317 // Call callback with Changed type to inform the driver.
2319 SendDiscardInfoToDriver (FormSet
, Form
);
2322 UpdateNvInfoInForm (FormSet
, FALSE
);
2323 } else if (SettingScope
== SystemLevel
) {
2325 // System Level Discard.
2329 // Discard changed value for each FormSet in the maintain list.
2331 Link
= GetFirstNode (&gBrowserFormSetList
);
2332 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2333 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2334 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2335 if (!ValidateFormSet(LocalFormSet
)) {
2338 DiscardForm (LocalFormSet
, NULL
, FormSetLevel
);
2339 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2341 // Remove maintain backup list after discard except for the current using FormSet.
2343 RemoveEntryList (&LocalFormSet
->Link
);
2344 DestroyFormSet (LocalFormSet
);
2353 Submit data based on the input Setting level (Form, FormSet or System).
2355 @param FormSet FormSet data structure.
2356 @param Form Form data structure.
2357 @param SettingScope Setting Scope for Submit action.
2359 @retval EFI_SUCCESS The function completed successfully.
2360 @retval EFI_UNSUPPORTED Unsupport SettingScope.
2365 IN FORM_BROWSER_FORMSET
*FormSet
,
2366 IN FORM_BROWSER_FORM
*Form
,
2367 IN BROWSER_SETTING_SCOPE SettingScope
2372 EFI_STRING ConfigResp
;
2373 EFI_STRING Progress
;
2374 BROWSER_STORAGE
*Storage
;
2375 FORMSET_STORAGE
*FormSetStorage
;
2378 FORM_BROWSER_FORMSET
*LocalFormSet
;
2379 FORM_BROWSER_CONFIG_REQUEST
*ConfigInfo
;
2382 // Check the supported setting level.
2384 if (SettingScope
>= MaxLevel
) {
2385 return EFI_UNSUPPORTED
;
2389 // Validate the Form by NoSubmit check
2391 Status
= EFI_SUCCESS
;
2392 if (SettingScope
== FormLevel
) {
2393 Status
= NoSubmitCheck (FormSet
, Form
);
2394 } else if (SettingScope
== FormSetLevel
) {
2395 Status
= NoSubmitCheck (FormSet
, NULL
);
2397 if (EFI_ERROR (Status
)) {
2401 if (SettingScope
== FormLevel
&& Form
->NvUpdateRequired
) {
2403 Link
= GetFirstNode (&Form
->ConfigRequestHead
);
2404 while (!IsNull (&Form
->ConfigRequestHead
, Link
)) {
2405 ConfigInfo
= FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link
);
2406 Link
= GetNextNode (&Form
->ConfigRequestHead
, Link
);
2408 Storage
= ConfigInfo
->Storage
;
2409 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2414 // Skip if there is no RequestElement
2416 if (ConfigInfo
->ElementCount
== 0) {
2421 // 1. Prepare <ConfigResp>
2423 Status
= StorageToConfigResp (ConfigInfo
->Storage
, &ConfigResp
, ConfigInfo
->ConfigRequest
);
2424 if (EFI_ERROR (Status
)) {
2429 // 2. Set value to hii driver or efi variable.
2431 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2432 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2434 // Send <ConfigResp> to Configuration Driver
2436 if (FormSet
->ConfigAccess
!= NULL
) {
2437 Status
= FormSet
->ConfigAccess
->RouteConfig (
2438 FormSet
->ConfigAccess
,
2442 if (EFI_ERROR (Status
)) {
2443 FreePool (ConfigResp
);
2447 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2449 TmpBuf
= AllocateZeroPool(Storage
->Size
);
2450 if (TmpBuf
== NULL
) {
2451 Status
= EFI_OUT_OF_RESOURCES
;
2455 BufferSize
= Storage
->Size
;
2456 Status
= gRT
->GetVariable (
2463 if (EFI_ERROR (Status
)) {
2465 FreePool (ConfigResp
);
2468 ASSERT (BufferSize
== Storage
->Size
);
2469 Status
= mHiiConfigRouting
->ConfigToBlock (
2476 if (EFI_ERROR (Status
)) {
2478 FreePool (ConfigResp
);
2482 Status
= gRT
->SetVariable (
2485 Storage
->Attributes
,
2490 if (EFI_ERROR (Status
)) {
2491 FreePool (ConfigResp
);
2495 FreePool (ConfigResp
);
2497 // 3. Config success, update storage shadow Buffer, only update the data belong to this form.
2499 SynchronizeStorageForForm(FormSet
, ConfigInfo
, TRUE
);
2503 // 4. Update the NV flag.
2505 Form
->NvUpdateRequired
= FALSE
;
2506 } else if (SettingScope
== FormSetLevel
&& IsNvUpdateRequired(FormSet
)) {
2508 // Submit Buffer storage or Name/Value storage
2510 Link
= GetFirstNode (&FormSet
->StorageListHead
);
2511 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
2512 FormSetStorage
= (FORMSET_STORAGE_FROM_LINK (Link
));
2513 Storage
= FormSetStorage
->BrowserStorage
;
2514 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
2516 if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
2521 // Skip if there is no RequestElement
2523 if (FormSetStorage
->ElementCount
== 0) {
2528 // 1. Prepare <ConfigResp>
2530 Status
= StorageToConfigResp (Storage
, &ConfigResp
, FormSetStorage
->ConfigRequest
);
2531 if (EFI_ERROR (Status
)) {
2535 if (Storage
->Type
== EFI_HII_VARSTORE_BUFFER
||
2536 Storage
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2539 // 2. Send <ConfigResp> to Configuration Driver
2541 if (FormSet
->ConfigAccess
!= NULL
) {
2542 Status
= FormSet
->ConfigAccess
->RouteConfig (
2543 FormSet
->ConfigAccess
,
2547 if (EFI_ERROR (Status
)) {
2548 FreePool (ConfigResp
);
2552 } else if (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
2554 // 1&2. Set the edit data to the variable.
2557 TmpBuf
= AllocateZeroPool (Storage
->Size
);
2558 if (TmpBuf
== NULL
) {
2559 Status
= EFI_OUT_OF_RESOURCES
;
2562 BufferSize
= Storage
->Size
;
2563 Status
= gRT
->GetVariable (
2570 ASSERT (BufferSize
== Storage
->Size
);
2571 Status
= mHiiConfigRouting
->ConfigToBlock (
2578 if (EFI_ERROR (Status
)) {
2580 FreePool (ConfigResp
);
2584 Status
= gRT
->SetVariable (
2587 Storage
->Attributes
,
2591 if (EFI_ERROR (Status
)) {
2593 FreePool (ConfigResp
);
2598 FreePool (ConfigResp
);
2600 // 3. Config success, update storage shadow Buffer
2602 SynchronizeStorage (Storage
, TRUE
);
2606 // 4. Update the NV flag.
2608 UpdateNvInfoInForm (FormSet
, FALSE
);
2609 } else if (SettingScope
== SystemLevel
) {
2611 // System Level Save.
2615 // Save changed value for each FormSet in the maintain list.
2617 Link
= GetFirstNode (&gBrowserFormSetList
);
2618 while (!IsNull (&gBrowserFormSetList
, Link
)) {
2619 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
2620 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
2621 if (!ValidateFormSet(LocalFormSet
)) {
2624 SubmitForm (LocalFormSet
, NULL
, FormSetLevel
);
2625 if (!IsHiiHandleInBrowserContext (LocalFormSet
->HiiHandle
)) {
2627 // Remove maintain backup list after save except for the current using FormSet.
2629 RemoveEntryList (&LocalFormSet
->Link
);
2630 DestroyFormSet (LocalFormSet
);
2639 Get Question default value from AltCfg string.
2641 @param FormSet The form set.
2642 @param Question The question.
2643 @param DefaultId The default Id.
2645 @retval EFI_SUCCESS Question is reset to default value.
2649 GetDefaultValueFromAltCfg (
2650 IN FORM_BROWSER_FORMSET
*FormSet
,
2651 IN OUT FORM_BROWSER_STATEMENT
*Question
,
2655 BOOLEAN IsBufferStorage
;
2658 BROWSER_STORAGE
*Storage
;
2659 CHAR16
*ConfigRequest
;
2672 Status
= EFI_NOT_FOUND
;
2675 ConfigRequest
= NULL
;
2679 Storage
= Question
->Storage
;
2681 if ((Storage
== NULL
) ||
2682 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) ||
2683 (Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
)) {
2688 // Question Value is provided by Buffer Storage or NameValue Storage
2690 if (Question
->BufferValue
!= NULL
) {
2692 // This Question is password or orderedlist
2694 Dst
= Question
->BufferValue
;
2697 // Other type of Questions
2699 Dst
= (UINT8
*) &Question
->HiiValue
.Value
;
2702 IsBufferStorage
= (BOOLEAN
) ((Storage
->Type
== EFI_HII_VARSTORE_BUFFER
) ? TRUE
: FALSE
);
2703 IsString
= (BOOLEAN
) ((Question
->HiiValue
.Type
== EFI_IFR_TYPE_STRING
) ? TRUE
: FALSE
);
2706 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
2707 // <ConfigHdr> + "&" + <VariableName>
2709 if (IsBufferStorage
) {
2710 Length
= StrLen (Storage
->ConfigHdr
);
2711 Length
+= StrLen (Question
->BlockName
);
2713 Length
= StrLen (Storage
->ConfigHdr
);
2714 Length
+= StrLen (Question
->VariableName
) + 1;
2716 ConfigRequest
= AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
2717 ASSERT (ConfigRequest
!= NULL
);
2719 StrCpy (ConfigRequest
, Storage
->ConfigHdr
);
2720 if (IsBufferStorage
) {
2721 StrCat (ConfigRequest
, Question
->BlockName
);
2723 StrCat (ConfigRequest
, L
"&");
2724 StrCat (ConfigRequest
, Question
->VariableName
);
2727 Status
= FormSet
->ConfigAccess
->ExtractConfig (
2728 FormSet
->ConfigAccess
,
2733 if (EFI_ERROR (Status
)) {
2738 // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
2739 // Get the default configuration string according to the default ID.
2741 Status
= mHiiConfigRouting
->GetAltConfig (
2747 &DefaultId
, // it can be NULL to get the current setting.
2752 // The required setting can't be found. So, it is not required to be validated and set.
2754 if (EFI_ERROR (Status
)) {
2759 // Skip <ConfigRequest>
2761 if (IsBufferStorage
) {
2762 Value
= StrStr (ConfigResp
, L
"&VALUE");
2763 ASSERT (Value
!= NULL
);
2769 Value
= StrStr (ConfigResp
, Question
->VariableName
);
2770 ASSERT (Value
!= NULL
);
2772 Value
= Value
+ StrLen (Question
->VariableName
);
2774 if (*Value
!= '=') {
2775 Status
= EFI_NOT_FOUND
;
2779 // Skip '=', point to value
2784 // Suppress <AltResp> if any
2787 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2792 LengthStr
= StrLen (Value
);
2793 if (!IsBufferStorage
&& IsString
) {
2794 StringPtr
= (CHAR16
*) Dst
;
2795 ZeroMem (TemStr
, sizeof (TemStr
));
2796 for (Index
= 0; Index
< LengthStr
; Index
+= 4) {
2797 StrnCpy (TemStr
, Value
+ Index
, 4);
2798 StringPtr
[Index
/4] = (CHAR16
) StrHexToUint64 (TemStr
);
2801 // Add tailing L'\0' character
2803 StringPtr
[Index
/4] = L
'\0';
2805 ZeroMem (TemStr
, sizeof (TemStr
));
2806 for (Index
= 0; Index
< LengthStr
; Index
++) {
2807 TemStr
[0] = Value
[LengthStr
- Index
- 1];
2808 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
2809 if ((Index
& 1) == 0) {
2810 Dst
[Index
/2] = DigitUint8
;
2812 Dst
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Dst
[Index
/2]);
2818 if (ConfigRequest
!= NULL
){
2819 FreePool (ConfigRequest
);
2822 if (ConfigResp
!= NULL
) {
2823 FreePool (ConfigResp
);
2826 if (Result
!= NULL
) {
2834 Get default Id value used for browser.
2836 @param DefaultId The default id value used by hii.
2838 @retval Browser used default value.
2842 GetDefaultIdForCallBack (
2846 if (DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) {
2847 return EFI_BROWSER_ACTION_DEFAULT_STANDARD
;
2848 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2849 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING
;
2850 } else if (DefaultId
== EFI_HII_DEFAULT_CLASS_SAFE
) {
2851 return EFI_BROWSER_ACTION_DEFAULT_SAFE
;
2852 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
+ 0x1000) {
2853 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM
+ DefaultId
- EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN
;
2854 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
+ 0x1000) {
2855 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN
;
2856 } else if (DefaultId
>= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
&& DefaultId
< EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
+ 0x1000) {
2857 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE
+ DefaultId
- EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN
;
2864 Reset Question to its default value.
2866 @param FormSet The form set.
2867 @param Form The form.
2868 @param Question The question.
2869 @param DefaultId The Class of the default.
2871 @retval EFI_SUCCESS Question is reset to default value.
2875 GetQuestionDefault (
2876 IN FORM_BROWSER_FORMSET
*FormSet
,
2877 IN FORM_BROWSER_FORM
*Form
,
2878 IN FORM_BROWSER_STATEMENT
*Question
,
2884 QUESTION_DEFAULT
*Default
;
2885 QUESTION_OPTION
*Option
;
2886 EFI_HII_VALUE
*HiiValue
;
2888 EFI_STRING StrValue
;
2889 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2890 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
2893 Status
= EFI_NOT_FOUND
;
2897 // Statement don't have storage, skip them
2899 if (Question
->QuestionId
== 0) {
2904 // There are Five ways to specify default value for a Question:
2905 // 1, use call back function (highest priority)
2906 // 2, use ExtractConfig function
2907 // 3, use nested EFI_IFR_DEFAULT
2908 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
2909 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
2911 HiiValue
= &Question
->HiiValue
;
2914 // Get Question defaut value from call back function.
2916 ConfigAccess
= FormSet
->ConfigAccess
;
2917 Action
= GetDefaultIdForCallBack (DefaultId
);
2918 if ((Action
> 0) && ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) != 0) && (ConfigAccess
!= NULL
)) {
2919 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2920 Status
= ConfigAccess
->Callback (
2923 Question
->QuestionId
,
2928 if (!EFI_ERROR (Status
)) {
2934 // Get default value from altcfg string.
2936 if (ConfigAccess
!= NULL
) {
2937 Status
= GetDefaultValueFromAltCfg(FormSet
, Question
, DefaultId
);
2938 if (!EFI_ERROR (Status
)) {
2944 // EFI_IFR_DEFAULT has highest priority
2946 if (!IsListEmpty (&Question
->DefaultListHead
)) {
2947 Link
= GetFirstNode (&Question
->DefaultListHead
);
2948 while (!IsNull (&Question
->DefaultListHead
, Link
)) {
2949 Default
= QUESTION_DEFAULT_FROM_LINK (Link
);
2951 if (Default
->DefaultId
== DefaultId
) {
2952 if (Default
->ValueExpression
!= NULL
) {
2954 // Default is provided by an Expression, evaluate it
2956 Status
= EvaluateExpression (FormSet
, Form
, Default
->ValueExpression
);
2957 if (EFI_ERROR (Status
)) {
2961 if (Default
->ValueExpression
->Result
.Type
== EFI_IFR_TYPE_BUFFER
) {
2962 ASSERT (HiiValue
->Type
== EFI_IFR_TYPE_BUFFER
&& Question
->BufferValue
!= NULL
);
2963 if (Question
->StorageWidth
> Default
->ValueExpression
->Result
.BufferLen
) {
2964 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Default
->ValueExpression
->Result
.BufferLen
);
2965 Question
->HiiValue
.BufferLen
= Default
->ValueExpression
->Result
.BufferLen
;
2967 CopyMem (Question
->HiiValue
.Buffer
, Default
->ValueExpression
->Result
.Buffer
, Question
->StorageWidth
);
2968 Question
->HiiValue
.BufferLen
= Question
->StorageWidth
;
2970 FreePool (Default
->ValueExpression
->Result
.Buffer
);
2972 HiiValue
->Type
= Default
->ValueExpression
->Result
.Type
;
2973 CopyMem (&HiiValue
->Value
, &Default
->ValueExpression
->Result
.Value
, sizeof (EFI_IFR_TYPE_VALUE
));
2976 // Default value is embedded in EFI_IFR_DEFAULT
2978 CopyMem (HiiValue
, &Default
->Value
, sizeof (EFI_HII_VALUE
));
2981 if (HiiValue
->Type
== EFI_IFR_TYPE_STRING
) {
2982 StrValue
= HiiGetString (FormSet
->HiiHandle
, HiiValue
->Value
.string
, NULL
);
2983 if (StrValue
== NULL
) {
2984 return EFI_NOT_FOUND
;
2986 if (Question
->StorageWidth
> StrSize (StrValue
)) {
2987 CopyMem (Question
->BufferValue
, StrValue
, StrSize (StrValue
));
2989 CopyMem (Question
->BufferValue
, StrValue
, Question
->StorageWidth
);
2996 Link
= GetNextNode (&Question
->DefaultListHead
, Link
);
3001 // EFI_ONE_OF_OPTION
3003 if ((Question
->Operand
== EFI_IFR_ONE_OF_OP
) && !IsListEmpty (&Question
->OptionListHead
)) {
3004 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3006 // OneOfOption could only provide Standard and Manufacturing default
3008 Link
= GetFirstNode (&Question
->OptionListHead
);
3009 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3010 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3011 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3013 if ((Option
->SuppressExpression
!= NULL
) &&
3014 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3018 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT
) != 0)) ||
3019 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Option
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) != 0))
3021 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3030 // EFI_IFR_CHECKBOX - lowest priority
3032 if (Question
->Operand
== EFI_IFR_CHECKBOX_OP
) {
3033 if (DefaultId
<= EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3035 // Checkbox could only provide Standard and Manufacturing default
3037 if (((DefaultId
== EFI_HII_DEFAULT_CLASS_STANDARD
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) != 0)) ||
3038 ((DefaultId
== EFI_HII_DEFAULT_CLASS_MANUFACTURING
) && ((Question
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) != 0))
3040 HiiValue
->Value
.b
= TRUE
;
3042 HiiValue
->Value
.b
= FALSE
;
3050 // For Questions without default
3052 Status
= EFI_NOT_FOUND
;
3053 switch (Question
->Operand
) {
3054 case EFI_IFR_NUMERIC_OP
:
3056 // Take minimum value as numeric default value
3058 if ((HiiValue
->Value
.u64
< Question
->Minimum
) || (HiiValue
->Value
.u64
> Question
->Maximum
)) {
3059 HiiValue
->Value
.u64
= Question
->Minimum
;
3060 Status
= EFI_SUCCESS
;
3064 case EFI_IFR_ONE_OF_OP
:
3066 // Take first oneof option as oneof's default value
3068 if (ValueToOption (Question
, HiiValue
) == NULL
) {
3069 Link
= GetFirstNode (&Question
->OptionListHead
);
3070 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3071 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3072 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3074 if ((Option
->SuppressExpression
!= NULL
) &&
3075 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3079 CopyMem (HiiValue
, &Option
->Value
, sizeof (EFI_HII_VALUE
));
3080 Status
= EFI_SUCCESS
;
3086 case EFI_IFR_ORDERED_LIST_OP
:
3088 // Take option sequence in IFR as ordered list's default value
3091 Link
= GetFirstNode (&Question
->OptionListHead
);
3092 while (!IsNull (&Question
->OptionListHead
, Link
)) {
3093 Status
= EFI_SUCCESS
;
3094 Option
= QUESTION_OPTION_FROM_LINK (Link
);
3095 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
3097 if ((Option
->SuppressExpression
!= NULL
) &&
3098 EvaluateExpressionList(Option
->SuppressExpression
, FALSE
, NULL
, NULL
) != ExpressFalse
) {
3102 SetArrayData (Question
->BufferValue
, Question
->ValueType
, Index
, Option
->Value
.Value
.u64
);
3105 if (Index
>= Question
->MaxContainers
) {
3120 Reset Questions to their initial value or default value in a Form, Formset or System.
3122 GetDefaultValueScope parameter decides which questions will reset
3123 to its default value.
3125 @param FormSet FormSet data structure.
3126 @param Form Form data structure.
3127 @param DefaultId The Class of the default.
3128 @param SettingScope Setting Scope for Default action.
3129 @param GetDefaultValueScope Get default value scope.
3130 @param Storage Get default value only for this storage.
3131 @param RetrieveValueFirst Whether call the retrieve call back to
3132 get the initial value before get default
3135 @retval EFI_SUCCESS The function completed successfully.
3136 @retval EFI_UNSUPPORTED Unsupport SettingScope.
3141 IN FORM_BROWSER_FORMSET
*FormSet
,
3142 IN FORM_BROWSER_FORM
*Form
,
3143 IN UINT16 DefaultId
,
3144 IN BROWSER_SETTING_SCOPE SettingScope
,
3145 IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope
,
3146 IN BROWSER_STORAGE
*Storage OPTIONAL
,
3147 IN BOOLEAN RetrieveValueFirst
3151 LIST_ENTRY
*FormLink
;
3153 FORM_BROWSER_STATEMENT
*Question
;
3154 FORM_BROWSER_FORMSET
*BackUpFormSet
;
3155 FORM_BROWSER_FORMSET
*LocalFormSet
;
3156 EFI_HII_HANDLE
*HiiHandles
;
3160 Status
= EFI_SUCCESS
;
3163 // Check the supported setting level.
3165 if (SettingScope
>= MaxLevel
|| GetDefaultValueScope
>= GetDefaultForMax
) {
3166 return EFI_UNSUPPORTED
;
3169 if (GetDefaultValueScope
== GetDefaultForStorage
&& Storage
== NULL
) {
3170 return EFI_UNSUPPORTED
;
3173 if (SettingScope
== FormLevel
) {
3175 // Extract Form default
3177 Link
= GetFirstNode (&Form
->StatementListHead
);
3178 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3179 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3180 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3183 // If get default value only for this storage, check the storage first.
3185 if ((GetDefaultValueScope
== GetDefaultForStorage
) && (Question
->Storage
!= Storage
)) {
3190 // If get default value only for no storage question, just skip the question which has storage.
3192 if ((GetDefaultValueScope
== GetDefaultForNoStorage
) && (Question
->Storage
!= NULL
)) {
3197 // If Question is disabled, don't reset it to default
3199 if (Question
->Expression
!= NULL
) {
3200 if (EvaluateExpressionList(Question
->Expression
, TRUE
, FormSet
, Form
) == ExpressDisable
) {
3205 if (RetrieveValueFirst
) {
3207 // Call the Retrieve call back to get the initial question value.
3209 Status
= ProcessRetrieveForQuestion(FormSet
->ConfigAccess
, Question
);
3213 // If not request to get the initial value or get initial value fail, then get default value.
3215 if (!RetrieveValueFirst
|| EFI_ERROR (Status
)) {
3216 Status
= GetQuestionDefault (FormSet
, Form
, Question
, DefaultId
);
3217 if (EFI_ERROR (Status
)) {
3223 // Synchronize Buffer storage's Edit buffer
3225 if ((Question
->Storage
!= NULL
) &&
3226 (Question
->Storage
->Type
!= EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3227 SetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3229 // Update Form NV flag.
3231 Form
->NvUpdateRequired
= TRUE
;
3234 } else if (SettingScope
== FormSetLevel
) {
3235 FormLink
= GetFirstNode (&FormSet
->FormListHead
);
3236 while (!IsNull (&FormSet
->FormListHead
, FormLink
)) {
3237 Form
= FORM_BROWSER_FORM_FROM_LINK (FormLink
);
3238 ExtractDefault (FormSet
, Form
, DefaultId
, FormLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3239 FormLink
= GetNextNode (&FormSet
->FormListHead
, FormLink
);
3241 } else if (SettingScope
== SystemLevel
) {
3243 // Open all FormSet by locate HII packages.
3244 // Initiliaze the maintain FormSet to store default data as back up data.
3246 BackUpFormSet
= gOldFormSet
;
3250 // Get all the Hii handles
3252 HiiHandles
= HiiGetHiiHandles (NULL
);
3253 ASSERT (HiiHandles
!= NULL
);
3256 // Search for formset of each class type
3258 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
3260 // Check HiiHandles[Index] does exist in global maintain list.
3262 if (GetFormSetFromHiiHandle (HiiHandles
[Index
]) != NULL
) {
3267 // Initilize FormSet Setting
3269 LocalFormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
3270 ASSERT (LocalFormSet
!= NULL
);
3271 ZeroMem (&ZeroGuid
, sizeof (ZeroGuid
));
3272 Status
= InitializeFormSet (HiiHandles
[Index
], &ZeroGuid
, LocalFormSet
, FALSE
);
3273 if (EFI_ERROR (Status
) || IsListEmpty (&LocalFormSet
->FormListHead
)) {
3274 DestroyFormSet (LocalFormSet
);
3277 Status
= InitializeCurrentSetting (LocalFormSet
);
3278 if (EFI_ERROR (Status
)) {
3279 DestroyFormSet (LocalFormSet
);
3283 // Initilize Questions' Value
3285 Status
= LoadFormSetConfig (NULL
, LocalFormSet
);
3286 if (EFI_ERROR (Status
)) {
3287 DestroyFormSet (LocalFormSet
);
3292 // Add FormSet into the maintain list.
3294 InsertTailList (&gBrowserFormSetList
, &LocalFormSet
->Link
);
3298 // Free resources, and restore gOldFormSet and gClassOfVfr
3300 FreePool (HiiHandles
);
3301 gOldFormSet
= BackUpFormSet
;
3304 // Set Default Value for each FormSet in the maintain list.
3306 Link
= GetFirstNode (&gBrowserFormSetList
);
3307 while (!IsNull (&gBrowserFormSetList
, Link
)) {
3308 LocalFormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
3309 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
3310 if (!ValidateFormSet(LocalFormSet
)) {
3313 ExtractDefault (LocalFormSet
, NULL
, DefaultId
, FormSetLevel
, GetDefaultValueScope
, Storage
, RetrieveValueFirst
);
3321 Initialize Question's Edit copy from Storage.
3323 @param Selection Selection contains the information about
3324 the Selection, form and formset to be displayed.
3325 Selection action may be updated in retrieve callback.
3326 If Selection is NULL, only initialize Question value.
3327 @param FormSet FormSet data structure.
3328 @param Form Form data structure.
3330 @retval EFI_SUCCESS The function completed successfully.
3335 IN OUT UI_MENU_SELECTION
*Selection
,
3336 IN FORM_BROWSER_FORMSET
*FormSet
,
3337 IN FORM_BROWSER_FORM
*Form
3342 FORM_BROWSER_STATEMENT
*Question
;
3346 Link
= GetFirstNode (&Form
->StatementListHead
);
3347 while (!IsNull (&Form
->StatementListHead
, Link
)) {
3348 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
3351 // Initialize local copy of Value for each Question
3353 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
3354 if (EFI_ERROR (Status
)) {
3358 if ((Question
->Operand
== EFI_IFR_STRING_OP
) || (Question
->Operand
== EFI_IFR_PASSWORD_OP
)) {
3359 HiiSetString (FormSet
->HiiHandle
, Question
->HiiValue
.Value
.string
, (CHAR16
*)Question
->BufferValue
, NULL
);
3363 // Call the Retrieve call back function for all questions.
3365 if ((FormSet
->ConfigAccess
!= NULL
) && (Selection
!= NULL
) &&
3366 ((Question
->QuestionFlags
& EFI_IFR_FLAG_CALLBACK
) == EFI_IFR_FLAG_CALLBACK
)) {
3368 // Check QuestionValue does exist.
3370 StorageWidth
= Question
->StorageWidth
;
3371 if (Question
->BufferValue
!= NULL
) {
3372 BufferValue
= Question
->BufferValue
;
3374 BufferValue
= (UINT8
*) &Question
->HiiValue
.Value
;
3378 // For efivarstore storage, initial question value first.
3380 if ((Question
->Storage
!= NULL
) && (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
)) {
3381 Status
= gRT
->GetVariable (
3382 Question
->VariableName
,
3383 &Question
->Storage
->Guid
,
3390 Status
= ProcessCallBackFunction(Selection
, Question
, EFI_BROWSER_ACTION_RETRIEVE
, TRUE
);
3393 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
3400 Initialize Question's Edit copy from Storage for the whole Formset.
3402 @param Selection Selection contains the information about
3403 the Selection, form and formset to be displayed.
3404 Selection action may be updated in retrieve callback.
3405 If Selection is NULL, only initialize Question value.
3406 @param FormSet FormSet data structure.
3408 @retval EFI_SUCCESS The function completed successfully.
3413 IN OUT UI_MENU_SELECTION
*Selection
,
3414 IN FORM_BROWSER_FORMSET
*FormSet
3419 FORM_BROWSER_FORM
*Form
;
3421 Link
= GetFirstNode (&FormSet
->FormListHead
);
3422 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3423 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3426 // Initialize local copy of Value for each Form
3428 Status
= LoadFormConfig (Selection
, FormSet
, Form
);
3429 if (EFI_ERROR (Status
)) {
3433 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3440 Fill storage's edit copy with settings requested from Configuration Driver.
3442 @param FormSet FormSet data structure.
3443 @param Storage Buffer Storage.
3445 @retval EFI_SUCCESS The function completed successfully.
3450 IN FORM_BROWSER_FORMSET
*FormSet
,
3451 IN FORMSET_STORAGE
*Storage
3455 EFI_STRING Progress
;
3459 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
3463 if (Storage
->BrowserStorage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
) {
3464 Status
= gRT
->GetVariable (
3465 Storage
->BrowserStorage
->Name
,
3466 &Storage
->BrowserStorage
->Guid
,
3468 (UINTN
*)&Storage
->BrowserStorage
->Size
,
3469 Storage
->BrowserStorage
->EditBuffer
3474 if (FormSet
->ConfigAccess
== NULL
) {
3475 return EFI_NOT_FOUND
;
3478 if (Storage
->ElementCount
== 0) {
3480 // Skip if there is no RequestElement
3486 // Request current settings from Configuration Driver
3488 Status
= FormSet
->ConfigAccess
->ExtractConfig (
3489 FormSet
->ConfigAccess
,
3490 Storage
->ConfigRequest
,
3494 if (EFI_ERROR (Status
)) {
3499 // Convert Result from <ConfigAltResp> to <ConfigResp>
3501 StrPtr
= StrStr (Result
, L
"&GUID=");
3502 if (StrPtr
!= NULL
) {
3506 Status
= ConfigRespToStorage (Storage
->BrowserStorage
, Result
);
3512 Get current setting of Questions.
3514 @param FormSet FormSet data structure.
3516 @retval EFI_SUCCESS The function completed successfully.
3520 InitializeCurrentSetting (
3521 IN OUT FORM_BROWSER_FORMSET
*FormSet
3526 FORMSET_STORAGE
*Storage
;
3527 FORMSET_STORAGE
*StorageSrc
;
3528 FORMSET_STORAGE
*OldStorage
;
3529 FORM_BROWSER_FORM
*Form
;
3530 FORM_BROWSER_FORM
*Form2
;
3534 // Extract default from IFR binary for no storage questions.
3536 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForNoStorage
, NULL
, TRUE
);
3539 // Request current settings from Configuration Driver
3541 Link
= GetFirstNode (&FormSet
->StorageListHead
);
3542 while (!IsNull (&FormSet
->StorageListHead
, Link
)) {
3543 Storage
= FORMSET_STORAGE_FROM_LINK (Link
);
3546 if (gOldFormSet
!= NULL
) {
3548 // Try to find the Storage in backup formset gOldFormSet
3550 Link2
= GetFirstNode (&gOldFormSet
->StorageListHead
);
3551 while (!IsNull (&gOldFormSet
->StorageListHead
, Link2
)) {
3552 StorageSrc
= FORMSET_STORAGE_FROM_LINK (Link2
);
3554 if (StorageSrc
->VarStoreId
== Storage
->VarStoreId
) {
3555 OldStorage
= StorageSrc
;
3559 Link2
= GetNextNode (&gOldFormSet
->StorageListHead
, Link2
);
3564 // Storage is not found in backup formset and current global storage not has other driver used,
3565 // request it from ConfigDriver
3567 if (OldStorage
== NULL
&& Storage
->BrowserStorage
->ReferenceCount
== 1) {
3568 Status
= LoadStorage (FormSet
, Storage
);
3570 if (EFI_ERROR (Status
)) {
3572 // If get last time changed value failed, extract default from IFR binary
3574 ExtractDefault (FormSet
, NULL
, EFI_HII_DEFAULT_CLASS_STANDARD
, FormSetLevel
, GetDefaultForStorage
, Storage
->BrowserStorage
, TRUE
);
3576 // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
3577 // in current situation.
3579 UpdateNvInfoInForm (FormSet
, FALSE
);
3583 // Now Edit Buffer is filled with default values(lower priority) or current
3584 // settings(higher priority), sychronize it to shadow Buffer
3586 SynchronizeStorage (Storage
->BrowserStorage
, TRUE
);
3589 Link
= GetNextNode (&FormSet
->StorageListHead
, Link
);
3593 // If has old formset, get the old nv update status.
3595 if (gOldFormSet
!= NULL
) {
3596 Link
= GetFirstNode (&FormSet
->FormListHead
);
3597 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
3598 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
3600 Link2
= GetFirstNode (&gOldFormSet
->FormListHead
);
3601 while (!IsNull (&gOldFormSet
->FormListHead
, Link2
)) {
3602 Form2
= FORM_BROWSER_FORM_FROM_LINK (Link2
);
3604 if (Form
->FormId
== Form2
->FormId
) {
3605 Form
->NvUpdateRequired
= Form2
->NvUpdateRequired
;
3609 Link2
= GetNextNode (&gOldFormSet
->FormListHead
, Link2
);
3611 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
3620 Fetch the Ifr binary data of a FormSet.
3622 @param Handle PackageList Handle
3623 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3624 specified (NULL or zero GUID), take the first
3625 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3626 found in package list.
3627 On output, GUID of the formset found(if not NULL).
3628 @param BinaryLength The length of the FormSet IFR binary.
3629 @param BinaryData The buffer designed to receive the FormSet.
3631 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
3632 BufferLength was updated.
3633 @retval EFI_INVALID_PARAMETER The handle is unknown.
3634 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
3635 be found with the requested FormId.
3640 IN EFI_HII_HANDLE Handle
,
3641 IN OUT EFI_GUID
*FormSetGuid
,
3642 OUT UINTN
*BinaryLength
,
3643 OUT UINT8
**BinaryData
3647 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
3653 UINT32 PackageListLength
;
3654 EFI_HII_PACKAGE_HEADER PackageHeader
;
3656 UINT8 NumberOfClassGuid
;
3657 BOOLEAN ClassGuidMatch
;
3658 EFI_GUID
*ClassGuid
;
3659 EFI_GUID
*ComparingGuid
;
3663 ZeroMem (&PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
3666 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
3668 if (FormSetGuid
== NULL
) {
3669 ComparingGuid
= &gZeroGuid
;
3671 ComparingGuid
= FormSetGuid
;
3675 // Get HII PackageList
3678 HiiPackageList
= NULL
;
3679 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3680 if (Status
== EFI_BUFFER_TOO_SMALL
) {
3681 HiiPackageList
= AllocatePool (BufferSize
);
3682 ASSERT (HiiPackageList
!= NULL
);
3684 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
3686 if (EFI_ERROR (Status
)) {
3689 ASSERT (HiiPackageList
!= NULL
);
3692 // Get Form package from this HII package List
3694 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
3696 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
3698 ClassGuidMatch
= FALSE
;
3699 while (Offset
< PackageListLength
) {
3700 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
3701 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
3703 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
3705 // Search FormSet in this Form Package
3707 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
3708 while (Offset2
< PackageHeader
.Length
) {
3709 OpCodeData
= Package
+ Offset2
;
3711 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
3713 // Try to compare against formset GUID
3715 if (CompareGuid (FormSetGuid
, &gZeroGuid
) ||
3716 CompareGuid (ComparingGuid
, (EFI_GUID
*)(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
)))) {
3720 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
3722 // Try to compare against formset class GUID
3724 NumberOfClassGuid
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
3725 ClassGuid
= (EFI_GUID
*) (OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
3726 for (Index
= 0; Index
< NumberOfClassGuid
; Index
++) {
3727 if (CompareGuid (ComparingGuid
, ClassGuid
+ Index
)) {
3728 ClassGuidMatch
= TRUE
;
3732 if (ClassGuidMatch
) {
3735 } else if (ComparingGuid
== &gEfiHiiPlatformSetupFormsetGuid
) {
3736 ClassGuidMatch
= TRUE
;
3741 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
3744 if (Offset2
< PackageHeader
.Length
) {
3746 // Target formset found
3752 Offset
+= PackageHeader
.Length
;
3755 if (Offset
>= PackageListLength
) {
3757 // Form package not found in this Package List
3759 FreePool (HiiPackageList
);
3760 return EFI_NOT_FOUND
;
3763 if (FormSetGuid
!= NULL
) {
3765 // Return the FormSet GUID
3767 CopyMem (FormSetGuid
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
, sizeof (EFI_GUID
));
3771 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
3772 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
3773 // of the Form Package.
3775 *BinaryLength
= PackageHeader
.Length
- Offset2
;
3776 *BinaryData
= AllocateCopyPool (*BinaryLength
, OpCodeData
);
3778 FreePool (HiiPackageList
);
3780 if (*BinaryData
== NULL
) {
3781 return EFI_OUT_OF_RESOURCES
;
3789 Initialize the internal data structure of a FormSet.
3791 @param Handle PackageList Handle
3792 @param FormSetGuid On input, GUID or class GUID of a formset. If not
3793 specified (NULL or zero GUID), take the first
3794 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
3795 found in package list.
3796 On output, GUID of the formset found(if not NULL).
3797 @param FormSet FormSet data structure.
3798 @param UpdateGlobalVar Whether need to update the global variable.
3800 @retval EFI_SUCCESS The function completed successfully.
3801 @retval EFI_NOT_FOUND The specified FormSet could not be found.
3806 IN EFI_HII_HANDLE Handle
,
3807 IN OUT EFI_GUID
*FormSetGuid
,
3808 OUT FORM_BROWSER_FORMSET
*FormSet
,
3809 IN BOOLEAN UpdateGlobalVar
3813 EFI_HANDLE DriverHandle
;
3816 Status
= GetIfrBinaryData (Handle
, FormSetGuid
, &FormSet
->IfrBinaryLength
, &FormSet
->IfrBinaryData
);
3817 if (EFI_ERROR (Status
)) {
3821 FormSet
->Signature
= FORM_BROWSER_FORMSET_SIGNATURE
;
3822 FormSet
->HiiHandle
= Handle
;
3823 CopyMem (&FormSet
->Guid
, FormSetGuid
, sizeof (EFI_GUID
));
3826 // Retrieve ConfigAccess Protocol associated with this HiiPackageList
3828 Status
= mHiiDatabase
->GetPackageListHandle (mHiiDatabase
, Handle
, &DriverHandle
);
3829 if (EFI_ERROR (Status
)) {
3832 FormSet
->DriverHandle
= DriverHandle
;
3833 Status
= gBS
->HandleProtocol (
3835 &gEfiHiiConfigAccessProtocolGuid
,
3836 (VOID
**) &FormSet
->ConfigAccess
3838 if (EFI_ERROR (Status
)) {
3840 // Configuration Driver don't attach ConfigAccess protocol to its HII package
3841 // list, then there will be no configuration action required
3843 FormSet
->ConfigAccess
= NULL
;
3847 // Parse the IFR binary OpCodes
3849 Status
= ParseOpCodes (FormSet
);
3850 if (EFI_ERROR (Status
)) {
3855 // If not need to update the global variable, just return.
3857 if (!UpdateGlobalVar
) {
3862 // Set VFR type by FormSet SubClass field
3864 gClassOfVfr
= FORMSET_CLASS_PLATFORM_SETUP
;
3865 if (FormSet
->SubClass
== EFI_FRONT_PAGE_SUBCLASS
) {
3866 gClassOfVfr
= FORMSET_CLASS_FRONT_PAGE
;
3870 // Set VFR type by FormSet class guid
3872 for (Index
= 0; Index
< 3; Index
++) {
3873 if (CompareGuid (&FormSet
->ClassGuid
[Index
], &gEfiHiiPlatformSetupFormsetGuid
)) {
3874 gClassOfVfr
|= FORMSET_CLASS_PLATFORM_SETUP
;
3879 gFunctionKeySetting
= ENABLE_FUNCTION_KEY_SETTING
;
3881 if ((gClassOfVfr
& FORMSET_CLASS_FRONT_PAGE
) == FORMSET_CLASS_FRONT_PAGE
) {
3882 gFrontPageHandle
= FormSet
->HiiHandle
;
3883 gFunctionKeySetting
= NONE_FUNCTION_KEY_SETTING
;
3887 // Match GUID to find out the function key setting. If match fail, use the default setting.
3889 for (Index
= 0; Index
< sizeof (gFunctionKeySettingTable
) / sizeof (FUNCTIION_KEY_SETTING
); Index
++) {
3890 if (CompareGuid (&FormSet
->Guid
, &(gFunctionKeySettingTable
[Index
].FormSetGuid
))) {
3892 // Update the function key setting.
3894 gFunctionKeySetting
= gFunctionKeySettingTable
[Index
].KeySetting
;
3903 Save globals used by previous call to SendForm(). SendForm() may be called from
3904 HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
3905 So, save globals of previous call to SendForm() and restore them upon exit.
3909 SaveBrowserContext (
3913 BROWSER_CONTEXT
*Context
;
3915 gBrowserContextCount
++;
3916 if (gBrowserContextCount
== 1) {
3918 // This is not reentry of SendForm(), no context to save
3923 Context
= AllocatePool (sizeof (BROWSER_CONTEXT
));
3924 ASSERT (Context
!= NULL
);
3926 Context
->Signature
= BROWSER_CONTEXT_SIGNATURE
;
3929 // Save FormBrowser context
3931 Context
->BannerData
= gBannerData
;
3932 Context
->ClassOfVfr
= gClassOfVfr
;
3933 Context
->FunctionKeySetting
= gFunctionKeySetting
;
3934 Context
->ResetRequired
= gResetRequired
;
3935 Context
->Direction
= gDirection
;
3936 Context
->EnterString
= gEnterString
;
3937 Context
->EnterCommitString
= gEnterCommitString
;
3938 Context
->EnterEscapeString
= gEnterEscapeString
;
3939 Context
->EscapeString
= gEscapeString
;
3940 Context
->MoveHighlight
= gMoveHighlight
;
3941 Context
->MakeSelection
= gMakeSelection
;
3942 Context
->DecNumericInput
= gDecNumericInput
;
3943 Context
->HexNumericInput
= gHexNumericInput
;
3944 Context
->ToggleCheckBox
= gToggleCheckBox
;
3945 Context
->PromptForData
= gPromptForData
;
3946 Context
->PromptForPassword
= gPromptForPassword
;
3947 Context
->PromptForNewPassword
= gPromptForNewPassword
;
3948 Context
->ConfirmPassword
= gConfirmPassword
;
3949 Context
->ConfirmError
= gConfirmError
;
3950 Context
->PassowordInvalid
= gPassowordInvalid
;
3951 Context
->PressEnter
= gPressEnter
;
3952 Context
->EmptyString
= gEmptyString
;
3953 Context
->AreYouSure
= gAreYouSure
;
3954 Context
->YesResponse
= gYesResponse
;
3955 Context
->NoResponse
= gNoResponse
;
3956 Context
->MiniString
= gMiniString
;
3957 Context
->PlusString
= gPlusString
;
3958 Context
->MinusString
= gMinusString
;
3959 Context
->AdjustNumber
= gAdjustNumber
;
3960 Context
->SaveChanges
= gSaveChanges
;
3961 Context
->OptionMismatch
= gOptionMismatch
;
3962 Context
->FormSuppress
= gFormSuppress
;
3963 Context
->PromptBlockWidth
= gPromptBlockWidth
;
3964 Context
->OptionBlockWidth
= gOptionBlockWidth
;
3965 Context
->HelpBlockWidth
= gHelpBlockWidth
;
3966 Context
->OldFormSet
= gOldFormSet
;
3967 Context
->MenuRefreshHead
= gMenuRefreshHead
;
3968 Context
->ProtocolNotFound
= gProtocolNotFound
;
3970 CopyMem (&Context
->ScreenDimensions
, &gScreenDimensions
, sizeof (gScreenDimensions
));
3971 CopyMem (&Context
->MenuOption
, &gMenuOption
, sizeof (gMenuOption
));
3974 // Insert to FormBrowser context list
3976 InsertHeadList (&gBrowserContextList
, &Context
->Link
);
3981 Restore globals used by previous call to SendForm().
3985 RestoreBrowserContext (
3990 BROWSER_CONTEXT
*Context
;
3992 ASSERT (gBrowserContextCount
!= 0);
3993 gBrowserContextCount
--;
3994 if (gBrowserContextCount
== 0) {
3996 // This is not reentry of SendForm(), no context to restore
4001 ASSERT (!IsListEmpty (&gBrowserContextList
));
4003 Link
= GetFirstNode (&gBrowserContextList
);
4004 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4007 // Restore FormBrowser context
4009 gBannerData
= Context
->BannerData
;
4010 gClassOfVfr
= Context
->ClassOfVfr
;
4011 gFunctionKeySetting
= Context
->FunctionKeySetting
;
4012 gResetRequired
= Context
->ResetRequired
;
4013 gDirection
= Context
->Direction
;
4014 gEnterString
= Context
->EnterString
;
4015 gEnterCommitString
= Context
->EnterCommitString
;
4016 gEnterEscapeString
= Context
->EnterEscapeString
;
4017 gEscapeString
= Context
->EscapeString
;
4018 gMoveHighlight
= Context
->MoveHighlight
;
4019 gMakeSelection
= Context
->MakeSelection
;
4020 gDecNumericInput
= Context
->DecNumericInput
;
4021 gHexNumericInput
= Context
->HexNumericInput
;
4022 gToggleCheckBox
= Context
->ToggleCheckBox
;
4023 gPromptForData
= Context
->PromptForData
;
4024 gPromptForPassword
= Context
->PromptForPassword
;
4025 gPromptForNewPassword
= Context
->PromptForNewPassword
;
4026 gConfirmPassword
= Context
->ConfirmPassword
;
4027 gConfirmError
= Context
->ConfirmError
;
4028 gPassowordInvalid
= Context
->PassowordInvalid
;
4029 gPressEnter
= Context
->PressEnter
;
4030 gEmptyString
= Context
->EmptyString
;
4031 gAreYouSure
= Context
->AreYouSure
;
4032 gYesResponse
= Context
->YesResponse
;
4033 gNoResponse
= Context
->NoResponse
;
4034 gMiniString
= Context
->MiniString
;
4035 gPlusString
= Context
->PlusString
;
4036 gMinusString
= Context
->MinusString
;
4037 gAdjustNumber
= Context
->AdjustNumber
;
4038 gSaveChanges
= Context
->SaveChanges
;
4039 gOptionMismatch
= Context
->OptionMismatch
;
4040 gFormSuppress
= Context
->FormSuppress
;
4041 gPromptBlockWidth
= Context
->PromptBlockWidth
;
4042 gOptionBlockWidth
= Context
->OptionBlockWidth
;
4043 gHelpBlockWidth
= Context
->HelpBlockWidth
;
4044 gOldFormSet
= Context
->OldFormSet
;
4045 gMenuRefreshHead
= Context
->MenuRefreshHead
;
4046 gProtocolNotFound
= Context
->ProtocolNotFound
;
4048 CopyMem (&gScreenDimensions
, &Context
->ScreenDimensions
, sizeof (gScreenDimensions
));
4049 CopyMem (&gMenuOption
, &Context
->MenuOption
, sizeof (gMenuOption
));
4052 // Remove from FormBrowser context list
4054 RemoveEntryList (&Context
->Link
);
4055 gBS
->FreePool (Context
);
4059 Find the matched FormSet context in the backup maintain list based on HiiHandle.
4061 @param Handle The Hii Handle.
4063 @return the found FormSet context. If no found, NULL will return.
4066 FORM_BROWSER_FORMSET
*
4067 GetFormSetFromHiiHandle (
4068 EFI_HII_HANDLE Handle
4072 FORM_BROWSER_FORMSET
*FormSet
;
4074 Link
= GetFirstNode (&gBrowserFormSetList
);
4075 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4076 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4077 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4078 if (!ValidateFormSet(FormSet
)) {
4081 if (FormSet
->HiiHandle
== Handle
) {
4090 Check whether the input HII handle is the FormSet that is being used.
4092 @param Handle The Hii Handle.
4094 @retval TRUE HII handle is being used.
4095 @retval FALSE HII handle is not being used.
4099 IsHiiHandleInBrowserContext (
4100 EFI_HII_HANDLE Handle
4104 BROWSER_CONTEXT
*Context
;
4107 // HiiHandle is Current FormSet.
4109 if ((gOldFormSet
!= NULL
) && (gOldFormSet
->HiiHandle
== Handle
)) {
4114 // Check whether HiiHandle is in BrowserContext.
4116 Link
= GetFirstNode (&gBrowserContextList
);
4117 while (!IsNull (&gBrowserContextList
, Link
)) {
4118 Context
= BROWSER_CONTEXT_FROM_LINK (Link
);
4119 if (Context
->OldFormSet
->HiiHandle
== Handle
) {
4121 // HiiHandle is in BrowserContext
4125 Link
= GetNextNode (&gBrowserContextList
, Link
);
4132 Find the registered HotKey based on KeyData.
4134 @param[in] KeyData A pointer to a buffer that describes the keystroke
4135 information for the hot key.
4137 @return The registered HotKey context. If no found, NULL will return.
4140 GetHotKeyFromRegisterList (
4141 IN EFI_INPUT_KEY
*KeyData
4145 BROWSER_HOT_KEY
*HotKey
;
4147 Link
= GetFirstNode (&gBrowserHotKeyList
);
4148 while (!IsNull (&gBrowserHotKeyList
, Link
)) {
4149 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
4150 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
4153 Link
= GetNextNode (&gBrowserHotKeyList
, Link
);
4160 Configure what scope the hot key will impact.
4161 All hot keys have the same scope. The mixed hot keys with the different level are not supported.
4162 If no scope is set, the default scope will be FormSet level.
4163 After all registered hot keys are removed, previous Scope can reset to another level.
4165 @param[in] Scope Scope level to be set.
4167 @retval EFI_SUCCESS Scope is set correctly.
4168 @retval EFI_INVALID_PARAMETER Scope is not the valid value specified in BROWSER_SETTING_SCOPE.
4169 @retval EFI_UNSPPORTED Scope level is different from current one that the registered hot keys have.
4175 IN BROWSER_SETTING_SCOPE Scope
4178 if (Scope
>= MaxLevel
) {
4179 return EFI_INVALID_PARAMETER
;
4183 // When no hot key registered in system or on the first setting,
4184 // Scope can be set.
4186 if (mBrowserScopeFirstSet
|| IsListEmpty (&gBrowserHotKeyList
)) {
4187 gBrowserSettingScope
= Scope
;
4188 mBrowserScopeFirstSet
= FALSE
;
4189 } else if (Scope
!= gBrowserSettingScope
) {
4190 return EFI_UNSUPPORTED
;
4197 Register the hot key with its browser action, or unregistered the hot key.
4198 Only support hot key that is not printable character (control key, function key, etc.).
4199 If the action value is zero, the hot key will be unregistered if it has been registered.
4200 If the same hot key has been registered, the new action and help string will override the previous ones.
4202 @param[in] KeyData A pointer to a buffer that describes the keystroke
4203 information for the hot key. Its type is EFI_INPUT_KEY to
4204 be supported by all ConsoleIn devices.
4205 @param[in] Action Action value that describes what action will be trigged when the hot key is pressed.
4206 @param[in] DefaultId Specifies the type of defaults to retrieve, which is only for DEFAULT action.
4207 @param[in] HelpString Help string that describes the hot key information.
4208 Its value may be NULL for the unregistered hot key.
4210 @retval EFI_SUCCESS Hot key is registered or unregistered.
4211 @retval EFI_INVALID_PARAMETER KeyData is NULL or HelpString is NULL on register.
4212 @retval EFI_NOT_FOUND KeyData is not found to be unregistered.
4213 @retval EFI_UNSUPPORTED Key represents a printable character. It is conflicted with Browser.
4218 IN EFI_INPUT_KEY
*KeyData
,
4220 IN UINT16 DefaultId
,
4221 IN EFI_STRING HelpString OPTIONAL
4224 BROWSER_HOT_KEY
*HotKey
;
4227 // Check input parameters.
4229 if (KeyData
== NULL
|| KeyData
->UnicodeChar
!= CHAR_NULL
||
4230 (Action
!= BROWSER_ACTION_UNREGISTER
&& HelpString
== NULL
)) {
4231 return EFI_INVALID_PARAMETER
;
4235 // Check whether the input KeyData is in BrowserHotKeyList.
4237 HotKey
= GetHotKeyFromRegisterList (KeyData
);
4240 // Unregister HotKey
4242 if (Action
== BROWSER_ACTION_UNREGISTER
) {
4243 if (HotKey
!= NULL
) {
4245 // The registered HotKey is found.
4246 // Remove it from List, and free its resource.
4248 RemoveEntryList (&HotKey
->Link
);
4249 FreePool (HotKey
->KeyData
);
4250 FreePool (HotKey
->HelpString
);
4254 // The registered HotKey is not found.
4256 return EFI_NOT_FOUND
;
4261 // Register HotKey into List.
4263 if (HotKey
== NULL
) {
4265 // Create new Key, and add it into List.
4267 HotKey
= AllocateZeroPool (sizeof (BROWSER_HOT_KEY
));
4268 ASSERT (HotKey
!= NULL
);
4269 HotKey
->Signature
= BROWSER_HOT_KEY_SIGNATURE
;
4270 HotKey
->KeyData
= AllocateCopyPool (sizeof (EFI_INPUT_KEY
), KeyData
);
4271 InsertTailList (&gBrowserHotKeyList
, &HotKey
->Link
);
4275 // Fill HotKey information.
4277 HotKey
->Action
= Action
;
4278 HotKey
->DefaultId
= DefaultId
;
4279 if (HotKey
->HelpString
!= NULL
) {
4280 FreePool (HotKey
->HelpString
);
4282 HotKey
->HelpString
= AllocateCopyPool (StrSize (HelpString
), HelpString
);
4288 Register Exit handler function.
4289 When more than one handler function is registered, the latter one will override the previous one.
4290 When NULL handler is specified, the previous Exit handler will be unregistered.
4292 @param[in] Handler Pointer to handler function.
4297 RegiserExitHandler (
4298 IN EXIT_HANDLER Handler
4301 ExitHandlerFunction
= Handler
;
4306 Create reminder to let user to choose save or discard the changed browser data.
4307 Caller can use it to actively check the changed browser data.
4309 @retval BROWSER_NO_CHANGES No browser data is changed.
4310 @retval BROWSER_SAVE_CHANGES The changed browser data is saved.
4311 @retval BROWSER_DISCARD_CHANGES The changed browser data is discard.
4321 FORM_BROWSER_FORMSET
*FormSet
;
4322 BOOLEAN IsDataChanged
;
4323 UINT32 DataSavedAction
;
4324 CHAR16
*YesResponse
;
4326 CHAR16
*EmptyString
;
4327 CHAR16
*ChangeReminderString
;
4328 CHAR16
*SaveConfirmString
;
4331 DataSavedAction
= BROWSER_NO_CHANGES
;
4332 IsDataChanged
= FALSE
;
4333 Link
= GetFirstNode (&gBrowserFormSetList
);
4334 while (!IsNull (&gBrowserFormSetList
, Link
)) {
4335 FormSet
= FORM_BROWSER_FORMSET_FROM_LINK (Link
);
4336 Link
= GetNextNode (&gBrowserFormSetList
, Link
);
4337 if (!ValidateFormSet(FormSet
)) {
4340 if (IsNvUpdateRequired (FormSet
)) {
4341 IsDataChanged
= TRUE
;
4347 // No data is changed. No save is required.
4349 if (!IsDataChanged
) {
4350 return DataSavedAction
;
4354 // If data is changed, prompt user
4356 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
4358 YesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
4359 ASSERT (YesResponse
!= NULL
);
4360 NoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
4361 ASSERT (NoResponse
!= NULL
);
4362 EmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
4363 ChangeReminderString
= GetToken (STRING_TOKEN (CHANGE_REMINDER
), gHiiHandle
);
4364 SaveConfirmString
= GetToken (STRING_TOKEN (SAVE_CONFIRM
), gHiiHandle
);
4367 CreateDialog (4, TRUE
, 0, NULL
, &Key
, EmptyString
, ChangeReminderString
, SaveConfirmString
, EmptyString
);
4369 (((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) &&
4370 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
))
4374 // If the user hits the YesResponse key
4376 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
[0] | UPPER_LOWER_CASE_OFFSET
)) {
4377 SubmitForm (NULL
, NULL
, SystemLevel
);
4378 DataSavedAction
= BROWSER_SAVE_CHANGES
;
4380 DiscardForm (NULL
, NULL
, SystemLevel
);
4381 DataSavedAction
= BROWSER_DISCARD_CHANGES
;
4382 gResetRequired
= FALSE
;
4385 FreePool (YesResponse
);
4386 FreePool (NoResponse
);
4387 FreePool (EmptyString
);
4388 FreePool (SaveConfirmString
);
4389 FreePool (ChangeReminderString
);
4391 return DataSavedAction
;