4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. 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.
33 Set Buffer to Value for Size bytes.
37 Buffer - Memory to set.
39 Size - Number of bytes to set
41 Value - Value of the set operation.
64 Initialize Menu option list.
72 InitializeListHead (&Menu
);
82 Initialize Menu option list.
90 InitializeListHead (&gMenuList
);
94 UiRemoveMenuListEntry (
95 IN UI_MENU_OPTION
*Selection
,
96 OUT UI_MENU_OPTION
**PreviousSelection
101 Remove Menu option list.
109 UI_MENU_LIST
*UiMenuList
;
111 *PreviousSelection
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
112 ASSERT (*PreviousSelection
!= NULL
);
114 if (!IsListEmpty (&gMenuList
)) {
115 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
116 (*PreviousSelection
)->IfrNumber
= UiMenuList
->Selection
.IfrNumber
;
117 (*PreviousSelection
)->FormId
= UiMenuList
->Selection
.FormId
;
118 (*PreviousSelection
)->Tags
= UiMenuList
->Selection
.Tags
;
119 (*PreviousSelection
)->ThisTag
= UiMenuList
->Selection
.ThisTag
;
120 (*PreviousSelection
)->Handle
= UiMenuList
->Selection
.Handle
;
121 gEntryNumber
= UiMenuList
->FormerEntryNumber
;
122 RemoveEntryList (&UiMenuList
->MenuLink
);
123 FreePool (UiMenuList
);
134 Free Menu option linked list.
142 UI_MENU_LIST
*UiMenuList
;
144 while (!IsListEmpty (&gMenuList
)) {
145 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
146 RemoveEntryList (&UiMenuList
->MenuLink
);
147 FreePool (UiMenuList
);
153 IN UI_MENU_OPTION
*Selection
158 Add one menu entry to the linked lst
166 UI_MENU_LIST
*UiMenuList
;
168 UiMenuList
= AllocateZeroPool (sizeof (UI_MENU_LIST
));
169 ASSERT (UiMenuList
!= NULL
);
171 UiMenuList
->Signature
= UI_MENU_LIST_SIGNATURE
;
172 CopyMem (&UiMenuList
->Selection
, Selection
, sizeof (UI_MENU_OPTION
));
174 InsertHeadList (&gMenuList
, &UiMenuList
->MenuLink
);
184 Free Menu option linked list.
192 UI_MENU_OPTION
*MenuOption
;
194 while (!IsListEmpty (&Menu
)) {
195 MenuOption
= CR (Menu
.ForwardLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
196 RemoveEntryList (&MenuOption
->Link
);
199 // We allocated space for this description when we did a GetToken, free it here
201 FreePool (MenuOption
->Description
);
202 FreePool (MenuOption
);
214 Refresh screen with current date and/or time based on screen context
222 CHAR16
*OptionString
;
223 MENU_REFRESH_ENTRY
*MenuRefreshEntry
;
229 if (gMenuRefreshHead
!= NULL
) {
231 MenuRefreshEntry
= gMenuRefreshHead
;
234 gST
->ConOut
->SetAttribute (gST
->ConOut
, MenuRefreshEntry
->CurrentAttribute
);
235 ProcessOptions (MenuRefreshEntry
->MenuOption
, FALSE
, MenuRefreshEntry
->FileFormTagsHead
, NULL
, &OptionString
);
237 if (OptionString
!= NULL
) {
239 // If leading spaces on OptionString - remove the spaces
241 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
244 for (Loop
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
245 OptionString
[Loop
] = OptionString
[Index
];
249 OptionString
[Loop
] = CHAR_NULL
;
251 PrintStringAt (MenuRefreshEntry
->CurrentColumn
, MenuRefreshEntry
->CurrentRow
, OptionString
);
254 MenuRefreshEntry
= MenuRefreshEntry
->Next
;
256 } while (MenuRefreshEntry
!= NULL
);
259 if (OptionString
!= NULL
) {
260 FreePool (OptionString
);
265 UiWaitForSingleEvent (
267 IN UINT64 Timeout OPTIONAL
272 Wait for a given event to fire, or for an optional timeout to expire.
275 Event - The event to wait for
277 Timeout - An optional timeout value in 100 ns units.
281 EFI_SUCCESS - Event fired before Timeout expired.
282 EFI_TIME_OUT - Timout expired before Event fired.
288 EFI_EVENT TimerEvent
;
289 EFI_EVENT WaitList
[2];
293 // Create a timer event
295 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
296 if (!EFI_ERROR (Status
)) {
298 // Set the timer event
307 // Wait for the original event or the timer
310 WaitList
[1] = TimerEvent
;
311 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
312 gBS
->CloseEvent (TimerEvent
);
315 // If the timer expired, change the return to timed out
317 if (!EFI_ERROR (Status
) && Index
== 1) {
318 Status
= EFI_TIMEOUT
;
323 // Update screen every second
325 Timeout
= ONE_SECOND
;
328 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
331 // Set the timer event
340 // Wait for the original event or the timer
343 WaitList
[1] = TimerEvent
;
344 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
347 // If the timer expired, update anything that needs a refresh and keep waiting
349 if (!EFI_ERROR (Status
) && Index
== 1) {
350 Status
= EFI_TIMEOUT
;
351 UpdateDateAndTime ();
354 gBS
->CloseEvent (TimerEvent
);
355 } while (Status
== EFI_TIMEOUT
);
364 IN EFI_HII_HANDLE Handle
,
372 Add one menu option by specified description and context.
375 String - String description for this option.
376 Context - Context data for entry.
382 UI_MENU_OPTION
*MenuOption
;
384 MenuOption
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
387 MenuOption
->Signature
= UI_MENU_OPTION_SIGNATURE
;
388 MenuOption
->Description
= String
;
389 MenuOption
->Handle
= Handle
;
390 MenuOption
->FormBinary
= FormBinary
;
391 MenuOption
->IfrNumber
= IfrNumber
;
392 MenuOption
->Skip
= 1;
393 MenuOption
->Tags
= Tags
;
394 MenuOption
->TagIndex
= 0;
395 MenuOption
->ThisTag
= &(MenuOption
->Tags
[MenuOption
->TagIndex
]);
396 MenuOption
->EntryNumber
= (UINT16
) IfrNumber
;
398 InsertTailList (&Menu
, &MenuOption
->Link
);
404 IN EFI_HII_HANDLE Handle
,
408 IN UINT16 MenuItemCount
413 Add one menu option by specified description and context.
416 String - String description for this option.
417 Context - Context data for entry.
423 UI_MENU_OPTION
*MenuOption
;
425 MenuOption
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
428 MenuOption
->Signature
= UI_MENU_OPTION_SIGNATURE
;
429 MenuOption
->Description
= String
;
430 MenuOption
->Handle
= Handle
;
431 MenuOption
->Skip
= Tags
[TagIndex
].NumberOfLines
;
432 MenuOption
->IfrNumber
= gActiveIfr
;
433 MenuOption
->Tags
= Tags
;
434 MenuOption
->TagIndex
= TagIndex
;
435 MenuOption
->ThisTag
= &(MenuOption
->Tags
[MenuOption
->TagIndex
]);
436 MenuOption
->Consistency
= Tags
[TagIndex
].Consistency
;
437 MenuOption
->FormId
= FormId
;
438 MenuOption
->GrayOut
= Tags
[TagIndex
].GrayOut
;
439 MenuOption
->EntryNumber
= MenuItemCount
;
441 InsertTailList (&Menu
, &MenuOption
->Link
);
446 IN UINTN NumberOfLines
,
448 IN UINTN MaximumStringSize
,
449 OUT CHAR16
*StringBuffer
,
450 OUT EFI_INPUT_KEY
*KeyValue
,
457 Routine used to abstract a generic dialog interface and return the selected key or string
460 NumberOfLines - The number of lines for the dialog box
461 HotKey - Defines whether a single character is parsed (TRUE) and returned in KeyValue
462 or a string is returned in StringBuffer. Two special characters are considered when entering a string, a SCAN_ESC and
463 an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates string input and returns
464 MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes
465 StringBuffer - The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE
466 KeyValue - The EFI_KEY value returned if HotKey is TRUE..
467 String - Pointer to the first string in the list
468 ... - A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box
471 EFI_SUCCESS - Displayed dialog and received user interaction
472 EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE))
473 EFI_DEVICE_ERROR - User typed in an ESC character to exit the routine
482 CHAR16
*BufferedString
;
488 BOOLEAN SelectionComplete
;
490 UINTN CurrentAttribute
;
491 UINTN DimensionsWidth
;
492 UINTN DimensionsHeight
;
494 DimensionsWidth
= gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
;
495 DimensionsHeight
= gScreenDimensions
.BottomRow
- gScreenDimensions
.TopRow
;
497 SelectionComplete
= FALSE
;
499 TempString
= AllocateZeroPool (MaximumStringSize
* 2);
500 BufferedString
= AllocateZeroPool (MaximumStringSize
* 2);
501 CurrentAttribute
= gST
->ConOut
->Mode
->Attribute
;
504 ASSERT (BufferedString
);
506 VA_START (Marker
, String
);
509 // Zero the outgoing buffer
511 ZeroMem (StringBuffer
, MaximumStringSize
);
514 if (KeyValue
== NULL
) {
515 return EFI_INVALID_PARAMETER
;
518 if (StringBuffer
== NULL
) {
519 return EFI_INVALID_PARAMETER
;
525 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
527 LargestString
= (GetStringWidth (String
) / 2);
529 if (LargestString
== L
' ') {
533 // Determine the largest string in the dialog box
534 // Notice we are starting with 1 since String is the first string
536 for (Count
= 1; Count
< NumberOfLines
; Count
++) {
537 StackString
= VA_ARG (Marker
, CHAR16
*);
539 if (StackString
[0] == L
' ') {
540 InputOffset
= Count
+ 1;
543 if ((GetStringWidth (StackString
) / 2) > LargestString
) {
545 // Size of the string visually and subtract the width by one for the null-terminator
547 LargestString
= (GetStringWidth (StackString
) / 2);
551 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + gScreenDimensions
.LeftColumn
+ 1;
552 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gScreenDimensions
.TopRow
- 1;
559 CreateSharedPopUp (LargestString
, NumberOfLines
, &String
);
562 // Take the first key typed and report it back?
565 WaitForKeyStroke (&Key
);
566 CopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
570 WaitForKeyStroke (&Key
);
572 switch (Key
.UnicodeChar
) {
574 switch (Key
.ScanCode
) {
576 FreePool (TempString
);
577 FreePool (BufferedString
);
578 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
579 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
580 return EFI_DEVICE_ERROR
;
588 case CHAR_CARRIAGE_RETURN
:
589 SelectionComplete
= TRUE
;
590 FreePool (TempString
);
591 FreePool (BufferedString
);
592 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
593 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
598 if (StringBuffer
[0] != CHAR_NULL
) {
599 for (Index
= 0; StringBuffer
[Index
] != CHAR_NULL
; Index
++) {
600 TempString
[Index
] = StringBuffer
[Index
];
603 // Effectively truncate string by 1 character
605 TempString
[Index
- 1] = CHAR_NULL
;
606 StrCpy (StringBuffer
, TempString
);
611 // If it is the beginning of the string, don't worry about checking maximum limits
613 if ((StringBuffer
[0] == CHAR_NULL
) && (Key
.UnicodeChar
!= CHAR_BACKSPACE
)) {
614 StrnCpy (StringBuffer
, &Key
.UnicodeChar
, 1);
615 StrnCpy (TempString
, &Key
.UnicodeChar
, 1);
616 } else if ((GetStringWidth (StringBuffer
) < MaximumStringSize
) && (Key
.UnicodeChar
!= CHAR_BACKSPACE
)) {
617 KeyPad
[0] = Key
.UnicodeChar
;
618 KeyPad
[1] = CHAR_NULL
;
619 StrCat (StringBuffer
, KeyPad
);
620 StrCat (TempString
, KeyPad
);
623 // If the width of the input string is now larger than the screen, we nee to
624 // adjust the index to start printing portions of the string
626 SetUnicodeMem (BufferedString
, LargestString
, L
' ');
628 PrintStringAt (Start
+ 1, Top
+ InputOffset
, BufferedString
);
630 if ((GetStringWidth (StringBuffer
) / 2) > (DimensionsWidth
- 2)) {
631 Index
= (GetStringWidth (StringBuffer
) / 2) - DimensionsWidth
+ 2;
636 for (Count
= 0; Index
+ 1 < GetStringWidth (StringBuffer
) / 2; Index
++, Count
++) {
637 BufferedString
[Count
] = StringBuffer
[Index
];
640 PrintStringAt (Start
+ 1, Top
+ InputOffset
, BufferedString
);
643 } while (!SelectionComplete
);
646 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
647 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
653 IN UINTN RequestedWidth
,
654 IN UINTN NumberOfLines
,
655 IN CHAR16
**ArrayOfStrings
667 UINTN DimensionsWidth
;
668 UINTN DimensionsHeight
;
670 DimensionsWidth
= gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
;
671 DimensionsHeight
= gScreenDimensions
.BottomRow
- gScreenDimensions
.TopRow
;
675 gST
->ConOut
->SetAttribute (gST
->ConOut
, POPUP_TEXT
| POPUP_BACKGROUND
);
677 if ((RequestedWidth
+ 2) > DimensionsWidth
) {
678 RequestedWidth
= DimensionsWidth
- 2;
681 // Subtract the PopUp width from total Columns, allow for one space extra on
682 // each end plus a border.
684 Start
= (DimensionsWidth
- RequestedWidth
- 2) / 2 + gScreenDimensions
.LeftColumn
+ 1;
685 End
= Start
+ RequestedWidth
+ 1;
687 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gScreenDimensions
.TopRow
- 1;
688 Bottom
= Top
+ NumberOfLines
+ 2;
690 Character
= (CHAR16
) BOXDRAW_DOWN_RIGHT
;
691 PrintCharAt (Start
, Top
, Character
);
692 Character
= (CHAR16
) BOXDRAW_HORIZONTAL
;
693 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
694 PrintChar (Character
);
697 Character
= (CHAR16
) BOXDRAW_DOWN_LEFT
;
698 PrintChar (Character
);
699 Character
= (CHAR16
) BOXDRAW_VERTICAL
;
700 for (Index
= Top
; Index
+ 2 < Bottom
; Index
++) {
701 String
= ArrayOfStrings
[Count
];
705 // This will clear the background of the line - we never know who might have been
706 // here before us. This differs from the next clear in that it used the non-reverse
707 // video for normal printing.
709 if (GetStringWidth (String
) / 2 > 1) {
710 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, POPUP_TEXT
| POPUP_BACKGROUND
);
713 // Passing in a space results in the assumption that this is where typing will occur
715 if (String
[0] == L
' ') {
716 ClearLines (Start
+ 1, End
- 1, Index
+ 1, Index
+ 1, POPUP_INVERSE_TEXT
| POPUP_INVERSE_BACKGROUND
);
719 // Passing in a NULL results in a blank space
721 if (String
[0] == CHAR_NULL
) {
722 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, POPUP_TEXT
| POPUP_BACKGROUND
);
726 ((DimensionsWidth
- GetStringWidth (String
) / 2) / 2) + gScreenDimensions
.LeftColumn
+ 1,
730 gST
->ConOut
->SetAttribute (gST
->ConOut
, POPUP_TEXT
| POPUP_BACKGROUND
);
731 PrintCharAt (Start
, Index
+ 1, Character
);
732 PrintCharAt (End
- 1, Index
+ 1, Character
);
735 Character
= (CHAR16
) BOXDRAW_UP_RIGHT
;
736 PrintCharAt (Start
, Bottom
- 1, Character
);
737 Character
= (CHAR16
) BOXDRAW_HORIZONTAL
;
738 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
739 PrintChar (Character
);
742 Character
= (CHAR16
) BOXDRAW_UP_LEFT
;
743 PrintChar (Character
);
748 IN UINTN RequestedWidth
,
749 IN UINTN NumberOfLines
,
750 IN CHAR16
*ArrayOfStrings
,
754 CreateSharedPopUp (RequestedWidth
, NumberOfLines
, &ArrayOfStrings
);
759 IN UINTN MessageType
,
765 STATIC BOOLEAN InputError
;
766 CHAR16
*NvUpdateMessage
;
767 CHAR16
*InputErrorMessage
;
769 NvUpdateMessage
= GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE
), gHiiHandle
);
770 InputErrorMessage
= GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE
), gHiiHandle
);
772 switch (MessageType
) {
775 gST
->ConOut
->SetAttribute (gST
->ConOut
, ERROR_TEXT
);
777 gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
,
778 gScreenDimensions
.BottomRow
- 1,
783 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
);
784 for (Index
= 0; Index
< (GetStringWidth (InputErrorMessage
) - 2) / 2; Index
++) {
785 PrintAt (gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ Index
, gScreenDimensions
.BottomRow
- 1, (CHAR16
*) L
" ");
792 case NV_UPDATE_REQUIRED
:
793 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
795 gST
->ConOut
->SetAttribute (gST
->ConOut
, INFO_TEXT
);
797 gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
,
798 gScreenDimensions
.BottomRow
- 1,
801 gResetRequired
= (BOOLEAN
) (gResetRequired
| ((Flags
& EFI_IFR_FLAG_RESET_REQUIRED
) == EFI_IFR_FLAG_RESET_REQUIRED
));
803 gNvUpdateRequired
= TRUE
;
805 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
);
806 for (Index
= 0; Index
< (GetStringWidth (NvUpdateMessage
) - 2) / 2; Index
++) {
808 (gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ Index
),
809 gScreenDimensions
.BottomRow
- 1,
814 gNvUpdateRequired
= FALSE
;
819 case REFRESH_STATUS_BAR
:
821 UpdateStatusBar (INPUT_ERROR
, Flags
, TRUE
);
824 if (gNvUpdateRequired
) {
825 UpdateStatusBar (NV_UPDATE_REQUIRED
, Flags
, TRUE
);
833 FreePool (InputErrorMessage
);
834 FreePool (NvUpdateMessage
);
840 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
841 IN CHAR16
*FormattedString
,
842 IN CHAR16
*OptionString
848 Used to remove the allocated data instances
856 EFI_FILE_FORM_TAGS
*FileForm
;
857 EFI_FILE_FORM_TAGS
*PreviousFileForm
;
858 EFI_FORM_TAGS
*FormTags
;
859 EFI_FORM_TAGS
*PreviousFormTags
;
860 EFI_IFR_BINARY
*IfrBinary
;
861 EFI_IFR_BINARY
*PreviousIfrBinary
;
862 EFI_INCONSISTENCY_DATA
*Inconsistent
;
863 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
864 EFI_VARIABLE_DEFINITION
*PreviousVariableDefinition
;
868 FileForm
= FileFormTagsHead
;
870 if (FormattedString
!= NULL
) {
871 FreePool (FormattedString
);
874 if (OptionString
!= NULL
) {
875 FreePool (OptionString
);
878 for (; FileForm
!= NULL
;) {
879 PreviousFileForm
= NULL
;
882 // Advance FileForm to the last entry
884 for (; FileForm
->NextFile
!= NULL
; FileForm
= FileForm
->NextFile
) {
885 PreviousFileForm
= FileForm
;
888 FormTags
= &FileForm
->FormTags
;
890 for (; FormTags
!= NULL
;) {
891 FormTags
= &FileForm
->FormTags
;
892 PreviousFormTags
= NULL
;
895 // Advance FormTags to the last entry
897 for (; FormTags
->Next
!= NULL
; FormTags
= FormTags
->Next
) {
898 PreviousFormTags
= FormTags
;
901 // Walk through each of the tags and free the IntList allocation
903 for (Index
= 0; FormTags
->Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
; Index
++) {
905 // It is more than likely that the very last page will contain an end formset
907 if (FormTags
->Tags
[Index
].Operand
== EFI_IFR_END_FORM_SET_OP
) {
911 if (FormTags
->Tags
[Index
].IntList
!= NULL
) {
912 FreePool (FormTags
->Tags
[Index
].IntList
);
916 if (PreviousFormTags
!= NULL
) {
917 FreePool (FormTags
->Tags
);
918 FormTags
= PreviousFormTags
;
919 FreePool (FormTags
->Next
);
920 FormTags
->Next
= NULL
;
922 FreePool (FormTags
->Tags
);
927 // Last FileForm entry's Inconsistent database
929 Inconsistent
= FileForm
->InconsistentTags
;
932 // Advance Inconsistent to the last entry
934 for (; Inconsistent
->Next
!= NULL
; Inconsistent
= Inconsistent
->Next
)
937 for (; Inconsistent
!= NULL
;) {
939 // Preserve the Previous pointer
941 Buffer
= (VOID
*) Inconsistent
->Previous
;
944 // Free the current entry
946 FreePool (Inconsistent
);
949 // Restore the Previous pointer
951 Inconsistent
= (EFI_INCONSISTENCY_DATA
*) Buffer
;
954 VariableDefinition
= FileForm
->VariableDefinitions
;
956 for (; VariableDefinition
!= NULL
;) {
957 VariableDefinition
= FileForm
->VariableDefinitions
;
958 PreviousVariableDefinition
= NULL
;
961 // Advance VariableDefinitions to the last entry
963 for (; VariableDefinition
->Next
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
964 PreviousVariableDefinition
= VariableDefinition
;
967 FreePool (VariableDefinition
->VariableName
);
969 if (VariableDefinition
->NvRamMap
!= NULL
) {
970 FreePool (VariableDefinition
->NvRamMap
);
973 if (VariableDefinition
->FakeNvRamMap
!= NULL
) {
974 FreePool (VariableDefinition
->FakeNvRamMap
);
977 if (PreviousVariableDefinition
!= NULL
) {
978 VariableDefinition
= PreviousVariableDefinition
;
979 FreePool (VariableDefinition
->Next
);
980 VariableDefinition
->Next
= NULL
;
982 FreePool (VariableDefinition
);
983 VariableDefinition
= NULL
;
987 if (PreviousFileForm
!= NULL
) {
988 FileForm
= PreviousFileForm
;
989 FreePool (FileForm
->NextFile
);
990 FileForm
->NextFile
= NULL
;
997 IfrBinary
= gBinaryDataHead
;
999 for (; IfrBinary
!= NULL
;) {
1000 IfrBinary
= gBinaryDataHead
;
1001 PreviousIfrBinary
= NULL
;
1004 // Advance IfrBinary to the last entry
1006 for (; IfrBinary
->Next
!= NULL
; IfrBinary
= IfrBinary
->Next
) {
1007 PreviousIfrBinary
= IfrBinary
;
1010 FreePool (IfrBinary
->IfrPackage
);
1012 if (PreviousIfrBinary
!= NULL
) {
1013 IfrBinary
= PreviousIfrBinary
;
1014 FreePool (IfrBinary
->Next
);
1015 IfrBinary
->Next
= NULL
;
1017 FreePool (IfrBinary
);
1022 FreePool (gPreviousValue
);
1023 gPreviousValue
= NULL
;
1026 // Free Browser Strings
1028 FreePool (gPressEnter
);
1029 FreePool (gConfirmError
);
1030 FreePool (gConfirmPassword
);
1031 FreePool (gPromptForNewPassword
);
1032 FreePool (gPromptForPassword
);
1033 FreePool (gToggleCheckBox
);
1034 FreePool (gNumericInput
);
1035 FreePool (gMakeSelection
);
1036 FreePool (gMoveHighlight
);
1037 FreePool (gEscapeString
);
1038 FreePool (gEnterCommitString
);
1039 FreePool (gEnterString
);
1040 FreePool (gFunctionOneString
);
1041 FreePool (gFunctionTwoString
);
1042 FreePool (gFunctionNineString
);
1043 FreePool (gFunctionTenString
);
1049 SelectionsAreValid (
1050 IN UI_MENU_OPTION
*MenuOption
,
1051 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
1055 Routine Description:
1056 Initiate late consistency checks against the current page.
1067 EFI_FILE_FORM_TAGS
*FileFormTags
;
1069 CHAR16 NullCharacter
;
1074 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1076 StringPtr
= (CHAR16
*) L
"\0";
1077 NullCharacter
= CHAR_NULL
;
1079 FileFormTags
= FileFormTagsHead
;
1081 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
1082 FileFormTags
= FileFormTags
->NextFile
;
1085 for (Link
= Menu
.ForwardLink
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
1086 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1088 Tag
= MenuOption
->ThisTag
;
1090 ExtractRequestedNvMap (FileFormTags
, Tag
->VariableNumber
, &VariableDefinition
);
1091 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1094 // If the op-code has a late check, ensure consistency checks are now applied
1096 if (Tag
->Flags
& EFI_IFR_FLAG_LATE_CHECK
) {
1097 if (ValueIsNotValid (TRUE
, 0, Tag
, FileFormTags
, &PopUp
)) {
1098 if (PopUp
!= 0x0000) {
1099 StringPtr
= GetToken (PopUp
, MenuOption
->Handle
);
1101 CreatePopUp (GetStringWidth (StringPtr
) / 2, 3, &NullCharacter
, StringPtr
, &NullCharacter
);
1104 WaitForKeyStroke (&Key
);
1106 switch (Key
.UnicodeChar
) {
1108 case CHAR_CARRIAGE_RETURN
:
1110 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
1112 CopyMem (NvRamMap
, &Tag
->OldValue
, Tag
->StorageWidth
);
1113 FreePool (StringPtr
);
1119 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1133 IN EFI_HII_HANDLE Handle
1137 Routine Description:
1138 Get the supported width for a particular op-code
1141 Tag - The Tag structure passed in.
1142 Handle - The handle in the HII database being used
1145 Returns the number of CHAR16 characters that is support.
1156 // See if the second text parameter is really NULL
1158 if ((Tag
->Operand
== EFI_IFR_TEXT_OP
) && (Tag
->TextTwo
!= 0)) {
1159 String
= GetToken (Tag
->TextTwo
, Handle
);
1160 Size
= StrLen (String
);
1164 if ((Tag
->Operand
== EFI_IFR_SUBTITLE_OP
) ||
1165 (Tag
->Operand
== EFI_IFR_REF_OP
) ||
1166 (Tag
->Operand
== EFI_IFR_PASSWORD_OP
) ||
1167 (Tag
->Operand
== EFI_IFR_STRING_OP
) ||
1168 (Tag
->Operand
== EFI_IFR_INVENTORY_OP
) ||
1170 // Allow a wide display if text op-code and no secondary text op-code
1172 ((Tag
->Operand
== EFI_IFR_TEXT_OP
) && (Size
== 0x0000))
1174 return (UINT16
) (gPromptBlockWidth
+ gOptionBlockWidth
);
1176 return (UINT16
) gPromptBlockWidth
;
1182 IN CHAR16
*InputString
,
1183 IN UINT16 LineWidth
,
1184 IN OUT UINTN
*Index
,
1185 OUT CHAR16
**OutputString
1189 Routine Description:
1190 Will copy LineWidth amount of a string in the OutputString buffer and return the
1191 number of CHAR16 characters that were copied into the OutputString buffer.
1194 InputString - String description for this option.
1195 LineWidth - Width of the desired string to extract in CHAR16 characters
1196 Index - Where in InputString to start the copy process
1197 OutputString - Buffer to copy the string into
1200 Returns the number of CHAR16 characters that were copied into the OutputString buffer.
1205 static BOOLEAN Finished
;
1217 *OutputString
= AllocateZeroPool (((UINTN
) (LineWidth
+ 1) * 2));
1220 // Ensure we have got a valid buffer
1222 if (*OutputString
!= NULL
) {
1225 //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.
1226 //To avoid displaying this empty line in screen, just skip the two CHARs here.
1228 if ((InputString
[*Index
] == NARROW_CHAR
) && (InputString
[*Index
+ 1] == CHAR_CARRIAGE_RETURN
)) {
1229 *Index
= *Index
+ 2;
1233 // Fast-forward the string and see if there is a carriage-return in the string
1235 for (; (InputString
[*Index
+ Count2
] != CHAR_CARRIAGE_RETURN
) && (Count2
!= LineWidth
); Count2
++)
1239 // Copy the desired LineWidth of data to the output buffer.
1240 // Also make sure that we don't copy more than the string.
1241 // Also make sure that if there are linefeeds, we account for them.
1243 if ((StrSize (&InputString
[*Index
]) <= ((UINTN
) (LineWidth
+ 1) * 2)) &&
1244 (StrSize (&InputString
[*Index
]) <= ((UINTN
) (Count2
+ 1) * 2))
1247 // Convert to CHAR16 value and show that we are done with this operation
1249 LineWidth
= (UINT16
) ((StrSize (&InputString
[*Index
]) - 2) / 2);
1250 if (LineWidth
!= 0) {
1254 if (Count2
== LineWidth
) {
1256 // Rewind the string from the maximum size until we see a space to break the line
1258 for (; (InputString
[*Index
+ LineWidth
] != CHAR_SPACE
) && (LineWidth
!= 0); LineWidth
--)
1260 if (LineWidth
== 0) {
1268 CopyMem (*OutputString
, &InputString
[*Index
], LineWidth
* 2);
1271 // If currently pointing to a space, increment the index to the first non-space character
1274 (InputString
[*Index
+ LineWidth
] == CHAR_SPACE
) || (InputString
[*Index
+ LineWidth
] == CHAR_CARRIAGE_RETURN
);
1278 *Index
= (UINT16
) (*Index
+ LineWidth
);
1287 UpdateOptionSkipLines (
1288 IN EFI_IFR_DATA_ARRAY
*PageData
,
1289 IN UI_MENU_OPTION
*MenuOption
,
1290 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1291 IN CHAR16
**OptionalString
,
1299 CHAR16
*OutputString
;
1300 CHAR16
*OptionString
;
1303 OptionString
= *OptionalString
;
1304 OutputString
= NULL
;
1306 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1308 if (OptionString
!= NULL
) {
1309 Width
= (UINT16
) gOptionBlockWidth
;
1313 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1315 // If there is more string to process print on the next row and increment the Skip value
1317 if (StrLen (&OptionString
[Index
])) {
1318 if (SkipValue
== 0) {
1321 // Since the Number of lines for this menu entry may or may not be reflected accurately
1322 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1323 // some testing to ensure we are keeping this in-sync.
1325 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1327 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1333 FreePool (OutputString
);
1334 if (SkipValue
!= 0) {
1342 *OptionalString
= OptionString
;
1345 // Search table for UiDisplayMenu()
1347 SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation
[] = {
1349 { SCAN_DOWN
, UiDown
},
1350 { SCAN_PAGE_UP
, UiPageUp
},
1351 { SCAN_PAGE_DOWN
, UiPageDown
},
1352 { SCAN_ESC
, UiReset
},
1353 { SCAN_F2
, UiPrevious
},
1354 { SCAN_LEFT
, UiLeft
},
1355 { SCAN_RIGHT
, UiRight
},
1356 { SCAN_F9
, UiDefault
},
1357 { SCAN_F10
, UiSave
}
1360 SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag
[] = {
1361 { UiNoOperation
, CfUiNoOperation
},
1362 { UiDefault
, CfUiDefault
},
1363 { UiSelect
, CfUiSelect
},
1365 { UiDown
, CfUiDown
},
1366 { UiLeft
, CfUiLeft
},
1367 { UiRight
, CfUiRight
},
1368 { UiReset
, CfUiReset
},
1369 { UiSave
, CfUiSave
},
1370 { UiPrevious
, CfUiPrevious
},
1371 { UiPageUp
, CfUiPageUp
},
1372 { UiPageDown
, CfUiPageDown
}
1378 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1379 OUT EFI_IFR_DATA_ARRAY
*PageData
1383 Routine Description:
1384 Display menu and wait for user to select one menu option, then return it.
1385 If AutoBoot is enabled, then if user doesn't select any option,
1386 after period of time, it will automatically return the first menu option.
1389 SubMenu - Indicate is sub menu.
1390 FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure.
1391 PageData - A pointer to the EFI_IFR_DATA_ARRAY.
1394 Return the pointer of the menu which selected,
1395 otherwise return NULL.
1410 UINTN DataAndTimeLineNumberPad
;
1412 INT16 OriginalTimeOut
;
1416 CHAR16
*OptionString
;
1417 CHAR16
*OutputString
;
1418 CHAR16
*FormattedString
;
1425 UI_MENU_LIST
*UiMenuList
;
1429 LIST_ENTRY
*TopOfScreen
;
1430 LIST_ENTRY
*SavedListEntry
;
1431 UI_MENU_OPTION
*Selection
;
1432 UI_MENU_OPTION
*MenuOption
;
1433 UI_MENU_OPTION
*NextMenuOption
;
1434 UI_MENU_OPTION
*SavedMenuOption
;
1435 UI_MENU_OPTION
*PreviousMenuOption
;
1436 EFI_IFR_BINARY
*IfrBinary
;
1437 UI_CONTROL_FLAG ControlFlag
;
1438 EFI_SCREEN_DESCRIPTOR LocalScreen
;
1439 EFI_FILE_FORM_TAGS
*FileFormTags
;
1440 MENU_REFRESH_ENTRY
*MenuRefreshEntry
;
1441 MENU_REFRESH_ENTRY
*OldMenuRefreshEntry
;
1442 UI_SCREEN_OPERATION ScreenOperation
;
1443 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1444 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
1445 EFI_HII_VARIABLE_PACK_LIST
*NvMapListHead
;
1446 EFI_HII_VARIABLE_PACK_LIST
*NvMapListNode
;
1450 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
1452 VariableDefinition
= NULL
;
1453 Status
= EFI_SUCCESS
;
1454 FormattedString
= NULL
;
1455 OptionString
= NULL
;
1456 ScreenOperation
= UiNoOperation
;
1458 FormCallback
= NULL
;
1459 FileFormTags
= NULL
;
1460 OutputString
= NULL
;
1465 MenuRefreshEntry
= gMenuRefreshHead
;
1466 OldMenuRefreshEntry
= gMenuRefreshHead
;
1467 NextMenuOption
= NULL
;
1468 PreviousMenuOption
= NULL
;
1469 SavedMenuOption
= NULL
;
1474 ZeroMem (&Key
, sizeof (EFI_INPUT_KEY
));
1476 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
1477 TopRow
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1478 Row
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1480 TopRow
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1481 Row
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1485 Col
= LocalScreen
.LeftColumn
;
1487 Col
= LocalScreen
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
;
1490 BottomRow
= LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
- SCROLL_ARROW_HEIGHT
- 1;
1492 TopOfScreen
= Menu
.ForwardLink
;
1497 // Get user's selection
1500 NewPos
= Menu
.ForwardLink
;
1501 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
1503 UpdateStatusBar (REFRESH_STATUS_BAR
, (UINT8
) 0, TRUE
);
1505 ControlFlag
= CfInitialization
;
1508 switch (ControlFlag
) {
1509 case CfInitialization
:
1510 ControlFlag
= CfCheckSelection
;
1511 if (gExitRequired
) {
1512 ScreenOperation
= UiReset
;
1513 ControlFlag
= CfScreenOperation
;
1514 } else if (gSaveRequired
) {
1515 ScreenOperation
= UiSave
;
1516 ControlFlag
= CfScreenOperation
;
1517 } else if (IsListEmpty (&Menu
)) {
1518 ControlFlag
= CfReadKey
;
1522 case CfCheckSelection
:
1523 if (Selection
!= NULL
) {
1524 ControlFlag
= CfExit
;
1526 ControlFlag
= CfRepaint
;
1529 FileFormTags
= FileFormTagsHead
;
1533 ControlFlag
= CfRefreshHighLight
;
1539 SavedMenuOption
= MenuOption
;
1548 LocalScreen
.LeftColumn
,
1549 LocalScreen
.RightColumn
,
1550 TopRow
- SCROLL_ARROW_HEIGHT
,
1551 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1552 FIELD_TEXT
| FIELD_BACKGROUND
1555 while (gMenuRefreshHead
!= NULL
) {
1556 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
1558 FreePool (gMenuRefreshHead
);
1560 gMenuRefreshHead
= OldMenuRefreshEntry
;
1563 for (Link
= TopOfScreen
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
1564 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1565 MenuOption
->Row
= Row
;
1567 MenuOption
->Col
= Col
;
1568 MenuOption
->OptCol
= gPromptBlockWidth
+ 1 + LocalScreen
.LeftColumn
;
1571 if (MenuOption
->ThisTag
->GrayOut
) {
1572 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1574 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1575 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1579 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1583 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1584 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1585 PrintStringAt (Col
, Row
, OutputString
);
1588 // If there is more string to process print on the next row and increment the Skip value
1590 if (StrLen (&MenuOption
->Description
[Index
])) {
1596 FreePool (OutputString
);
1606 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1607 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1609 if (OptionString
!= NULL
) {
1610 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1611 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1614 // If leading spaces on OptionString - remove the spaces
1616 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++) {
1617 MenuOption
->OptCol
++;
1620 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1621 OptionString
[Count
] = OptionString
[Index
];
1625 OptionString
[Count
] = CHAR_NULL
;
1629 // If this is a date or time op-code and is used to reflect an RTC, register the op-code
1631 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1632 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
) &&
1633 (MenuOption
->ThisTag
->StorageStart
>= FileFormTags
->FormTags
.Tags
[0].NvDataSize
)) {
1635 if (gMenuRefreshHead
== NULL
) {
1636 MenuRefreshEntry
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1637 ASSERT (MenuRefreshEntry
!= NULL
);
1638 MenuRefreshEntry
->MenuOption
= MenuOption
;
1639 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1640 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1641 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1642 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1643 gMenuRefreshHead
= MenuRefreshEntry
;
1646 // Advance to the last entry
1648 for (MenuRefreshEntry
= gMenuRefreshHead
;
1649 MenuRefreshEntry
->Next
!= NULL
;
1650 MenuRefreshEntry
= MenuRefreshEntry
->Next
1653 MenuRefreshEntry
->Next
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1654 ASSERT (MenuRefreshEntry
->Next
!= NULL
);
1655 MenuRefreshEntry
= MenuRefreshEntry
->Next
;
1656 MenuRefreshEntry
->MenuOption
= MenuOption
;
1657 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1658 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1659 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1660 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1664 Width
= (UINT16
) gOptionBlockWidth
;
1668 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1669 if ((Temp2
== 0) && (Row
<= BottomRow
)) {
1670 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1673 // If there is more string to process print on the next row and increment the Skip value
1675 if (StrLen (&OptionString
[Index
])) {
1679 // Since the Number of lines for this menu entry may or may not be reflected accurately
1680 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1681 // some testing to ensure we are keeping this in-sync.
1683 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1685 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1691 FreePool (OutputString
);
1701 // If this is a text op with secondary text information
1703 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
) && (MenuOption
->ThisTag
->TextTwo
!= 0)) {
1704 StringPtr
= GetToken (MenuOption
->ThisTag
->TextTwo
, MenuOption
->Handle
);
1706 Width
= (UINT16
) gOptionBlockWidth
;
1710 for (Index
= 0; GetLineByWidth (StringPtr
, Width
, &Index
, &OutputString
) != 0x0000;) {
1711 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1712 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1715 // If there is more string to process print on the next row and increment the Skip value
1717 if (StrLen (&StringPtr
[Index
])) {
1721 // Since the Number of lines for this menu entry may or may not be reflected accurately
1722 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1723 // some testing to ensure we are keeping this in-sync.
1725 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1727 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1733 FreePool (OutputString
);
1740 FreePool (StringPtr
);
1744 // For now, assume left-justified 72 width max setup entries
1746 PrintStringAt (Col
, Row
, MenuOption
->Description
);
1749 // Tracker 6210 - need to handle the bottom of the display
1751 if (MenuOption
->Skip
> 1) {
1752 Row
+= MenuOption
->Skip
- SkipValue
;
1755 Row
+= MenuOption
->Skip
;
1758 if (Row
> BottomRow
) {
1759 if (!ValueIsScroll (FALSE
, Link
)) {
1763 Row
= BottomRow
+ 1;
1768 if (!ValueIsScroll (TRUE
, TopOfScreen
)) {
1773 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1775 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1776 TopRow
- SCROLL_ARROW_HEIGHT
,
1780 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1784 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1786 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1787 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1791 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1794 if (SavedMenuOption
!= NULL
) {
1795 MenuOption
= SavedMenuOption
;
1800 case CfRefreshHighLight
:
1801 ControlFlag
= CfUpdateHelpString
;
1803 // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
1804 // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
1806 SavedValue
= Repaint
;
1809 if (NewPos
!= NULL
) {
1810 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1812 if (gLastOpr
&& (gEntryNumber
!= -1)) {
1813 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1814 if (gEntryNumber
!= MenuOption
->EntryNumber
) {
1815 ScreenOperation
= UiDown
;
1816 ControlFlag
= CfScreenOperation
;
1823 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1824 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1825 if (OptionString
!= NULL
) {
1826 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1827 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1830 // If leading spaces on OptionString - remove the spaces
1832 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1835 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1836 OptionString
[Count
] = OptionString
[Index
];
1840 OptionString
[Count
] = CHAR_NULL
;
1843 Width
= (UINT16
) gOptionBlockWidth
;
1845 OriginalRow
= MenuOption
->Row
;
1847 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1848 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1849 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1852 // If there is more string to process print on the next row and increment the Skip value
1854 if (StrLen (&OptionString
[Index
])) {
1858 FreePool (OutputString
);
1861 MenuOption
->Row
= OriginalRow
;
1864 if (MenuOption
->ThisTag
->GrayOut
) {
1865 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1867 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1868 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1872 OriginalRow
= MenuOption
->Row
;
1873 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1875 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1876 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1877 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1880 // If there is more string to process print on the next row and increment the Skip value
1882 if (StrLen (&MenuOption
->Description
[Index
])) {
1886 FreePool (OutputString
);
1889 MenuOption
->Row
= OriginalRow
;
1890 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1894 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1895 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
1898 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1900 if ((gPriorMenuEntry
!= 0) && (MenuOption
->EntryNumber
!= gPriorMenuEntry
) && (NewPos
->ForwardLink
!= &Menu
)) {
1901 ScreenOperation
= UiDown
;
1902 ControlFlag
= CfScreenOperation
;
1905 gPriorMenuEntry
= 0;
1908 // This is only possible if we entered this page and the first menu option is
1909 // a "non-menu" item. In that case, force it UiDown
1911 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
1913 // If we previously hit an UP command and we are still sitting on a text operation
1914 // we must continue going up
1916 if (ScreenOperation
== UiUp
) {
1917 ControlFlag
= CfScreenOperation
;
1920 ScreenOperation
= UiDown
;
1921 ControlFlag
= CfScreenOperation
;
1926 // Set reverse attribute
1928 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
);
1929 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1932 // Assuming that we have a refresh linked-list created, lets annotate the
1933 // appropriate entry that we are highlighting with its new attribute. Just prior to this
1934 // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
1936 if (gMenuRefreshHead
!= NULL
) {
1937 for (MenuRefreshEntry
= gMenuRefreshHead
; MenuRefreshEntry
!= NULL
; MenuRefreshEntry
= MenuRefreshEntry
->Next
) {
1938 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1939 if (MenuRefreshEntry
->MenuOption
== MenuOption
) {
1940 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
;
1946 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1947 if (OptionString
!= NULL
) {
1948 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1949 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1952 // If leading spaces on OptionString - remove the spaces
1954 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1957 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1958 OptionString
[Count
] = OptionString
[Index
];
1962 OptionString
[Count
] = CHAR_NULL
;
1964 Width
= (UINT16
) gOptionBlockWidth
;
1966 OriginalRow
= MenuOption
->Row
;
1968 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1969 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1970 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1973 // If there is more string to process print on the next row and increment the Skip value
1975 if (StrLen (&OptionString
[Index
])) {
1979 FreePool (OutputString
);
1982 MenuOption
->Row
= OriginalRow
;
1985 OriginalRow
= MenuOption
->Row
;
1987 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1989 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1990 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1991 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1994 // If there is more string to process print on the next row and increment the Skip value
1996 if (StrLen (&MenuOption
->Description
[Index
])) {
2000 FreePool (OutputString
);
2003 MenuOption
->Row
= OriginalRow
;
2008 if (((NewPos
->ForwardLink
!= &Menu
) && (ScreenOperation
== UiDown
)) ||
2009 ((NewPos
->BackLink
!= &Menu
) && (ScreenOperation
== UiUp
)) ||
2010 (ScreenOperation
== UiNoOperation
)
2012 UpdateKeyHelp (MenuOption
, FALSE
);
2015 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2018 // Clear reverse attribute
2020 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
2023 // Repaint flag will be used when process CfUpdateHelpString, so restore its value
2024 // if we didn't break halfway when process CfRefreshHighLight.
2026 Repaint
= SavedValue
;
2029 case CfUpdateHelpString
:
2030 ControlFlag
= CfPrepareToReadKey
;
2033 (Repaint
|| NewLine
||
2034 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2035 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) &&
2036 !(gClassOfVfr
== EFI_GENERAL_APPLICATION_SUBCLASS
)) {
2038 // Don't print anything if it is a NULL help token
2040 if (MenuOption
->ThisTag
->Help
== 0x00000000) {
2041 StringPtr
= (CHAR16
*) L
"\0";
2043 StringPtr
= GetToken (MenuOption
->ThisTag
->Help
, MenuOption
->Handle
);
2046 ProcessHelpString (StringPtr
, &FormattedString
, BottomRow
- TopRow
);
2048 gST
->ConOut
->SetAttribute (gST
->ConOut
, HELP_TEXT
| FIELD_BACKGROUND
);
2050 for (Index
= 0; Index
< BottomRow
- TopRow
; Index
++) {
2052 // Pad String with spaces to simulate a clearing of the previous line
2054 for (; GetStringWidth (&FormattedString
[Index
* gHelpBlockWidth
* 2]) / 2 < gHelpBlockWidth
;) {
2055 StrCat (&FormattedString
[Index
* gHelpBlockWidth
* 2], (CHAR16
*) L
" ");
2059 LocalScreen
.RightColumn
- gHelpBlockWidth
,
2061 &FormattedString
[Index
* gHelpBlockWidth
* 2]
2066 // Reset this flag every time we finish using it.
2072 case CfPrepareToReadKey
:
2073 ControlFlag
= CfReadKey
;
2075 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
2076 FileFormTags
= FileFormTags
->NextFile
;
2079 ScreenOperation
= UiNoOperation
;
2081 Status
= gBS
->HandleProtocol (
2082 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
2083 &gEfiFormCallbackProtocolGuid
,
2084 (VOID
**) &FormCallback
2090 ControlFlag
= CfScreenOperation
;
2092 OriginalTimeOut
= FrontPageTimeOutValue
;
2094 if (FrontPageTimeOutValue
>= 0 && (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) && FrontPageTimeOutValue
!= (INT16
) -1) {
2096 // Remember that if set to 0, must immediately boot an option
2098 if (FrontPageTimeOutValue
== 0) {
2099 FrontPageTimeOutValue
= 0xFFFF;
2100 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2101 if (EFI_ERROR (Status
)) {
2102 Status
= EFI_TIMEOUT
;
2107 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, ONE_SECOND
);
2108 if (Status
== EFI_TIMEOUT
) {
2109 EFI_IFR_DATA_ENTRY
*DataEntry
;
2111 DataEntry
= (EFI_IFR_DATA_ENTRY
*) (PageData
+ 1);
2113 PageData
->EntryCount
= 1;
2114 Count
= (UINT32
) ((OriginalTimeOut
- FrontPageTimeOutValue
) * 100 / OriginalTimeOut
);
2115 CopyMem (&DataEntry
->Data
, &Count
, sizeof (UINT32
));
2117 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2118 FormCallback
->Callback (
2121 (EFI_IFR_DATA_ARRAY
*) PageData
,
2126 // Count down 1 second
2128 FrontPageTimeOutValue
--;
2131 ASSERT (!EFI_ERROR (Status
));
2132 PageData
->EntryCount
= 0;
2133 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2134 FormCallback
->Callback (
2137 (EFI_IFR_DATA_ARRAY
*) PageData
,
2142 FrontPageTimeOutValue
= 0xFFFF;
2146 // Wait for user's selection, no auto boot
2148 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
2150 } while (Status
== EFI_TIMEOUT
);
2154 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2155 DisableQuietBoot ();
2158 if (Status
== EFI_TIMEOUT
) {
2159 Key
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
2161 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2163 // if we encounter error, continue to read another key in.
2165 if (EFI_ERROR (Status
)) {
2166 ControlFlag
= CfReadKey
;
2171 switch (Key
.UnicodeChar
) {
2172 case CHAR_CARRIAGE_RETURN
:
2173 Selection
= MenuOption
;
2174 ScreenOperation
= UiSelect
;
2179 // We will push the adjustment of these numeric values directly to the input handler
2183 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2185 if (Key
.UnicodeChar
== '+') {
2186 gDirection
= SCAN_RIGHT
;
2188 gDirection
= SCAN_LEFT
;
2191 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, NULL
, &OptionString
);
2196 ScreenOperation
= UiUp
;
2201 ScreenOperation
= UiDown
;
2205 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
2207 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_CHECKBOX_OP
&& !(MenuOption
->ThisTag
->GrayOut
)) {
2208 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
2209 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2210 Selection
= MenuOption
;
2211 ScreenOperation
= UiSelect
;
2218 if (((Key
.ScanCode
== SCAN_F1
) && ((gFunctionKeySetting
& FUNCTION_ONE
) != FUNCTION_ONE
)) ||
2219 ((Key
.ScanCode
== SCAN_F2
) && ((gFunctionKeySetting
& FUNCTION_TWO
) != FUNCTION_TWO
)) ||
2220 ((Key
.ScanCode
== SCAN_F9
) && ((gFunctionKeySetting
& FUNCTION_NINE
) != FUNCTION_NINE
)) ||
2221 ((Key
.ScanCode
== SCAN_F10
) && ((gFunctionKeySetting
& FUNCTION_TEN
) != FUNCTION_TEN
))
2224 // If the function key has been disabled, just ignore the key.
2227 for (Index
= 0; Index
< sizeof (gScanCodeToOperation
) / sizeof (gScanCodeToOperation
[0]); Index
++) {
2228 if (Key
.ScanCode
== gScanCodeToOperation
[Index
].ScanCode
) {
2229 if ((Key
.ScanCode
== SCAN_F9
) || (Key
.ScanCode
== SCAN_F10
)) {
2231 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2234 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2243 case CfScreenOperation
:
2244 IfrBinary
= gBinaryDataHead
;
2247 // Advance to the Ifr we are using
2249 for (Index
= 0; Index
< gActiveIfr
; Index
++) {
2250 IfrBinary
= IfrBinary
->Next
;
2253 if (ScreenOperation
!= UiPrevious
&& ScreenOperation
!= UiReset
) {
2255 // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
2256 // ignore the selection and go back to reading keys.
2258 if (IsListEmpty (&Menu
)) {
2259 ControlFlag
= CfReadKey
;
2263 // if there is nothing logical to place a cursor on, just move on to wait for a key.
2265 for (Link
= Menu
.ForwardLink
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
2266 NextMenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2267 if (!(NextMenuOption
->ThisTag
->GrayOut
) && (NextMenuOption
->ThisTag
->Operand
!= EFI_IFR_SUBTITLE_OP
)) {
2272 if (Link
== &Menu
) {
2273 ControlFlag
= CfPrepareToReadKey
;
2279 Index
< sizeof (gScreenOperationToControlFlag
) / sizeof (gScreenOperationToControlFlag
[0]);
2282 if (ScreenOperation
== gScreenOperationToControlFlag
[Index
].ScreenOperation
) {
2283 ControlFlag
= gScreenOperationToControlFlag
[Index
].ControlFlag
;
2290 ControlFlag
= CfCheckSelection
;
2292 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2294 if (MenuOption
!= NULL
) {
2295 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2302 if (IsListEmpty (&gMenuList
)) {
2304 if (IsListEmpty (&Menu
)) {
2305 ControlFlag
= CfReadKey
;
2312 while (gMenuRefreshHead
!= NULL
) {
2313 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
2315 FreePool (gMenuRefreshHead
);
2317 gMenuRefreshHead
= OldMenuRefreshEntry
;
2320 // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag
2323 UiRemoveMenuListEntry (MenuOption
, &Selection
);
2324 Selection
->Previous
= TRUE
;
2329 gActiveIfr
= Selection
->IfrNumber
;
2333 ControlFlag
= CfCheckSelection
;
2335 ExtractRequestedNvMap (FileFormTags
, MenuOption
->ThisTag
->VariableNumber
, &VariableDefinition
);
2338 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
&&
2339 !(MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
)) ||
2340 (MenuOption
->ThisTag
->GrayOut
) ||
2341 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2342 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2348 UpdateKeyHelp (MenuOption
, TRUE
);
2349 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, PageData
, &OptionString
);
2351 if (EFI_ERROR (Status
)) {
2357 if (OptionString
!= NULL
) {
2358 PrintStringAt (LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ 1, MenuOption
->Row
, OptionString
);
2361 if (MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
2362 Selection
= MenuOption
;
2365 if (Selection
== NULL
) {
2369 Location
= (UINT8
*) &PageData
->EntryCount
;
2372 // If not a goto, dump single piece of data, otherwise dump everything
2374 if (Selection
->ThisTag
->Operand
== EFI_IFR_REF_OP
) {
2376 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2378 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2384 UiAddMenuListEntry (Selection
);
2385 gPriorMenuEntry
= 0;
2388 // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious
2390 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
2391 UiMenuList
->FormerEntryNumber
= MenuOption
->EntryNumber
;
2396 // Rewind to the beginning of the menu
2398 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2402 // Get Total Count of Menu entries
2404 for (Count
= 1; NewPos
->ForwardLink
!= &Menu
; NewPos
= NewPos
->ForwardLink
) {
2408 // Rewind to the beginning of the menu
2410 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2414 // Copy the number of entries being described to the PageData location
2416 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2418 for (Index
= 4; NewPos
->ForwardLink
!= &Menu
; Index
= Index
+ MenuOption
->ThisTag
->StorageWidth
+ 2) {
2420 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2421 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2422 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2424 &Location
[Index
+ 4],
2425 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2426 MenuOption
->ThisTag
->StorageWidth
2428 NewPos
= NewPos
->ForwardLink
;
2432 gPriorMenuEntry
= MenuOption
->EntryNumber
;
2437 // Copy the number of entries being described to the PageData location
2439 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2442 // Start at PageData[4] since the EntryCount is a UINT32
2447 // Copy data to destination
2449 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2450 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2452 &Location
[Index
+ 4],
2453 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2454 MenuOption
->ThisTag
->StorageWidth
2461 ControlFlag
= CfCheckSelection
;
2463 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
2467 // If NV flag is up, prompt user
2469 if (gNvUpdateRequired
) {
2470 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2472 YesResponse
= gYesResponse
[0];
2473 NoResponse
= gNoResponse
[0];
2476 CreateDialog (3, TRUE
, 0, NULL
, &Key
, gEmptyString
, gAreYouSure
, gEmptyString
);
2479 (Key
.ScanCode
!= SCAN_ESC
) &&
2480 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
| UPPER_LOWER_CASE_OFFSET
)) &&
2481 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
| UPPER_LOWER_CASE_OFFSET
))
2485 // If the user hits the YesResponse key
2487 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
| UPPER_LOWER_CASE_OFFSET
)) {
2495 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2497 if (MenuOption
!= NULL
) {
2498 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2506 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2507 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
2511 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2515 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2516 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2518 if (IfrBinary
->UnRegisterOnExit
) {
2519 Hii
->RemovePack (Hii
, MenuOption
->Handle
);
2525 // Clean up the allocated data buffers
2527 FreeData (FileFormTagsHead
, FormattedString
, OptionString
);
2529 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2533 ControlFlag
= CfCheckSelection
;
2534 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2535 if (MenuOption
->Skip
== 1) {
2537 // In the tail of the Date/Time op-code set, go left.
2539 NewPos
= NewPos
->BackLink
;
2542 // In the middle of the Data/Time op-code set, go left.
2544 NextMenuOption
= CR (NewPos
->ForwardLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2545 if (NextMenuOption
->Skip
== 1) {
2546 NewPos
= NewPos
->BackLink
;
2553 ControlFlag
= CfCheckSelection
;
2554 if ((MenuOption
->Skip
== 0) &&
2555 ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
))
2558 // We are in the head or middle of the Date/Time op-code set, advance right.
2560 NewPos
= NewPos
->ForwardLink
;
2565 ControlFlag
= CfCheckSelection
;
2567 if (NewPos
->BackLink
!= &Menu
) {
2570 // Adjust Date/Time position before we advance forward.
2572 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2575 // Caution that we have already rewind to the top, don't go backward in this situation.
2577 if (NewPos
->BackLink
!= &Menu
) {
2578 NewPos
= NewPos
->BackLink
;
2581 PreviousMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2584 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
2585 // to be one that back to the previous set of op-codes, we need to advance to the sencond
2586 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2587 // checking can be done.
2589 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (TRUE
, &NewPos
);
2593 // If the previous MenuOption contains a display-only op-code, skip to the next one
2595 if (PreviousMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| PreviousMenuOption
->ThisTag
->GrayOut
) {
2597 // This is ok as long as not at the end of the list
2599 if (NewPos
->BackLink
== &Menu
) {
2601 // If we are at the start of the list, then this list must start with a display only
2602 // piece of data, so do not allow the backward motion
2604 ScreenOperation
= UiDown
;
2606 if (PreviousMenuOption
->Row
<= TopRow
) {
2607 if (TopOfScreen
->BackLink
!= &Menu
) {
2608 TopOfScreen
= TopOfScreen
->BackLink
;
2613 UpdateStatusBar (INPUT_ERROR
, PreviousMenuOption
->ThisTag
->Flags
, FALSE
);
2619 // Check the previous menu entry to see if it was a zero-length advance. If it was,
2620 // don't worry about a redraw.
2622 if ((MenuOption
->Row
- PreviousMenuOption
->Skip
- DataAndTimeLineNumberPad
< TopRow
) ||
2623 (PreviousMenuOption
->Skip
> MenuOption
->Row
)
2626 if (TopOfScreen
->BackLink
== &Menu
) {
2633 // Is the current top of screen a zero-advance op-code?
2634 // If so, keep moving forward till we hit a >0 advance op-code
2636 SavedMenuOption
= CR (TopOfScreen
->BackLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2637 TopOfScreen
= TopOfScreen
->BackLink
;
2638 } while (SavedMenuOption
->Skip
== 0);
2640 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2642 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2645 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2648 SavedMenuOption
= MenuOption
;
2649 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2650 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2652 // If we are at the end of the list and sitting on a text op, we need to more forward
2654 ScreenOperation
= UiDown
;
2655 ControlFlag
= CfScreenOperation
;
2659 MenuOption
= SavedMenuOption
;
2665 ControlFlag
= CfCheckSelection
;
2667 SavedListEntry
= NewPos
;
2669 for (Index
= BottomRow
; Index
>= TopRow
+ 1; Index
-= MenuOption
->Skip
) {
2670 if (Link
->BackLink
== &Menu
) {
2672 Link
= SavedListEntry
;
2673 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2679 Link
= Link
->BackLink
;
2680 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2682 SavedListEntry
= Link
;
2688 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2689 // Don't do this when we are already in the first page.
2692 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2693 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2694 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2699 ControlFlag
= CfCheckSelection
;
2701 SavedListEntry
= NewPos
;
2703 NewPos
= TopOfScreen
;
2704 for (Index
= TopRow
; Index
<= BottomRow
- 1; Index
+= MenuOption
->Skip
) {
2705 if (NewPos
->ForwardLink
== &Menu
) {
2706 NewPos
= SavedListEntry
;
2707 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2716 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2717 NewPos
= NewPos
->ForwardLink
;
2724 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2725 // Don't do this when we are already in the last page.
2728 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2729 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2730 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2735 ControlFlag
= CfCheckSelection
;
2737 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
2738 // to be one that progresses to the next set of op-codes, we need to advance to the last
2739 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2740 // checking can be done. The only other logic we need to introduce is that if a Date/Time
2741 // op-code is the last entry in the menu, we need to rewind back to the first op-code of
2742 // the Date/Time op-code.
2744 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (FALSE
, &NewPos
);
2746 if (NewPos
->ForwardLink
!= &Menu
) {
2748 NewPos
= NewPos
->ForwardLink
;
2749 NextMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2753 // If the next MenuOption contains a display-only op-code, skip to the next one
2754 // Also if the next MenuOption is date or time,
2756 if (NextMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| NextMenuOption
->ThisTag
->GrayOut
) {
2758 // This is ok as long as not at the end of the list
2760 if (NewPos
== &Menu
) {
2762 // If we are at the end of the list, then this list must end with a display only
2763 // piece of data, so do not allow the forward motion
2765 UpdateStatusBar (INPUT_ERROR
, NextMenuOption
->ThisTag
->Flags
, FALSE
);
2766 NewPos
= NewPos
->BackLink
;
2767 ScreenOperation
= UiUp
;
2773 // An option might be multi-line, so we need to reflect that data in the overall skip value
2775 UpdateOptionSkipLines (PageData
, NextMenuOption
, FileFormTagsHead
, &OptionString
, SkipValue
);
2777 if (NextMenuOption
->Skip
> 1) {
2778 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ NextMenuOption
->Skip
- 1;
2780 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ DataAndTimeLineNumberPad
;
2783 // If we are going to scroll
2785 if (Temp
> BottomRow
) {
2788 // Is the current top of screen a zero-advance op-code?
2789 // If so, keep moving forward till we hit a >0 advance op-code
2791 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2794 // If bottom op-code is more than one line or top op-code is more than one line
2796 if ((NextMenuOption
->Skip
> 1) || (MenuOption
->Skip
> 1)) {
2798 // Is the bottom op-code greater than or equal in size to the top op-code?
2800 if ((Temp
- BottomRow
) >= (SavedMenuOption
->Skip
- OldSkipValue
)) {
2802 // Skip the top op-code
2804 TopOfScreen
= TopOfScreen
->ForwardLink
;
2805 Difference
= (Temp
- BottomRow
) - (SavedMenuOption
->Skip
- OldSkipValue
);
2807 OldSkipValue
= Difference
;
2809 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2812 // If we have a remainder, skip that many more op-codes until we drain the remainder
2815 Difference
>= (INTN
) SavedMenuOption
->Skip
;
2816 Difference
= Difference
- (INTN
) SavedMenuOption
->Skip
2819 // Since the Difference is greater than or equal to this op-code's skip value, skip it
2821 TopOfScreen
= TopOfScreen
->ForwardLink
;
2822 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2823 if (Difference
< (INTN
) SavedMenuOption
->Skip
) {
2824 Difference
= SavedMenuOption
->Skip
- Difference
- 1;
2827 if (Difference
== (INTN
) SavedMenuOption
->Skip
) {
2828 TopOfScreen
= TopOfScreen
->ForwardLink
;
2829 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2830 Difference
= SavedMenuOption
->Skip
- Difference
;
2836 // Since we will act on this op-code in the next routine, and increment the
2837 // SkipValue, set the skips to one less than what is required.
2839 SkipValue
= Difference
- 1;
2843 // Since we will act on this op-code in the next routine, and increment the
2844 // SkipValue, set the skips to one less than what is required.
2846 SkipValue
= OldSkipValue
+ (Temp
- BottomRow
) - 1;
2849 if ((OldSkipValue
+ 1) == (INTN
) SavedMenuOption
->Skip
) {
2850 TopOfScreen
= TopOfScreen
->ForwardLink
;
2853 SkipValue
= OldSkipValue
;
2857 // If the op-code at the top of the screen is more than one line, let's not skip it yet
2858 // Let's set a skip flag to smoothly scroll the top of the screen.
2860 if (SavedMenuOption
->Skip
> 1) {
2861 if (SavedMenuOption
== NextMenuOption
) {
2868 TopOfScreen
= TopOfScreen
->ForwardLink
;
2870 } while (SavedMenuOption
->Skip
== 0);
2873 OldSkipValue
= SkipValue
;
2876 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2880 SavedMenuOption
= MenuOption
;
2881 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2882 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2884 // If we are at the end of the list and sitting on a text op, we need to more forward
2886 ScreenOperation
= UiUp
;
2887 ControlFlag
= CfScreenOperation
;
2891 MenuOption
= SavedMenuOption
;
2893 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
2895 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2901 ControlFlag
= CfCheckSelection
;
2903 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2905 if (MenuOption
!= NULL
) {
2906 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2913 // If callbacks are active, and the callback has a Write method, try to use it
2915 if (FileFormTags
->VariableDefinitions
->VariableName
== NULL
) {
2916 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2917 Status
= FormCallback
->NvWrite (
2919 (CHAR16
*) L
"Setup",
2920 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2921 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2922 VariableDefinition
->VariableSize
,
2923 (VOID
*) VariableDefinition
->NvRamMap
,
2928 Status
= gRT
->SetVariable (
2929 (CHAR16
*) L
"Setup",
2930 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2931 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2932 VariableDefinition
->VariableSize
,
2933 (VOID
*) VariableDefinition
->NvRamMap
2937 VariableDefinition
= FileFormTags
->VariableDefinitions
;
2939 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
2940 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2941 Status
= FormCallback
->NvWrite (
2943 VariableDefinition
->VariableName
,
2944 &VariableDefinition
->Guid
,
2945 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2946 VariableDefinition
->VariableSize
,
2947 (VOID
*) VariableDefinition
->NvRamMap
,
2952 Status
= gRT
->SetVariable (
2953 VariableDefinition
->VariableName
,
2954 &VariableDefinition
->Guid
,
2955 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2956 VariableDefinition
->VariableSize
,
2957 (VOID
*) VariableDefinition
->NvRamMap
2963 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2964 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2968 ControlFlag
= CfCheckSelection
;
2970 NvMapListHead
= NULL
;
2972 Status
= Hii
->GetDefaultImage (Hii
, MenuOption
->Handle
, EFI_IFR_FLAG_DEFAULT
, &NvMapListHead
);
2974 if (!EFI_ERROR (Status
)) {
2975 ASSERT_EFI_ERROR (NULL
!= NvMapListHead
);
2977 NvMapListNode
= NvMapListHead
;
2979 while (NULL
!= NvMapListNode
) {
2980 if (FileFormTags
->VariableDefinitions
->VariableId
== NvMapListNode
->VariablePack
->VariableId
) {
2981 NvMap
= (VOID
*) ((CHAR8
*) NvMapListNode
->VariablePack
+ sizeof (EFI_HII_VARIABLE_PACK
) + NvMapListNode
->VariablePack
->VariableNameLength
);
2982 NvMapSize
= NvMapListNode
->VariablePack
->Header
.Length
- sizeof (EFI_HII_VARIABLE_PACK
) - NvMapListNode
->VariablePack
->VariableNameLength
;
2985 NvMapListNode
= NvMapListNode
->NextVariablePack
;
2989 // Free the buffer that was allocated.
2991 FreePool (FileFormTags
->VariableDefinitions
->NvRamMap
);
2992 FreePool (FileFormTags
->VariableDefinitions
->FakeNvRamMap
);
2995 // Allocate, copy the NvRamMap.
2997 FileFormTags
->VariableDefinitions
->VariableFakeSize
= (UINT16
) (FileFormTags
->VariableDefinitions
->VariableFakeSize
- FileFormTags
->VariableDefinitions
->VariableSize
);
2998 FileFormTags
->VariableDefinitions
->VariableSize
= (UINT16
) NvMapSize
;
2999 FileFormTags
->VariableDefinitions
->VariableFakeSize
= (UINT16
) (FileFormTags
->VariableDefinitions
->VariableFakeSize
+ FileFormTags
->VariableDefinitions
->VariableSize
);
3001 FileFormTags
->VariableDefinitions
->NvRamMap
= AllocateZeroPool (FileFormTags
->VariableDefinitions
->VariableSize
);
3002 ASSERT (FileFormTags
->VariableDefinitions
->NvRamMap
!= NULL
);
3004 FileFormTags
->VariableDefinitions
->FakeNvRamMap
= AllocateZeroPool (NvMapSize
+ FileFormTags
->VariableDefinitions
->VariableFakeSize
);
3005 ASSERT (FileFormTags
->VariableDefinitions
->FakeNvRamMap
!= NULL
);
3007 CopyMem (FileFormTags
->VariableDefinitions
->NvRamMap
, NvMap
, NvMapSize
);
3008 FreePool (NvMapListHead
);
3011 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, TRUE
);
3014 // After the repaint operation, we should refresh the highlight.
3019 case CfUiNoOperation
:
3020 ControlFlag
= CfCheckSelection
;
3024 while (gMenuRefreshHead
!= NULL
) {
3025 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
3027 FreePool (gMenuRefreshHead
);
3029 gMenuRefreshHead
= OldMenuRefreshEntry
;
3032 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, 0, Row
+ 4);
3033 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
3034 gST
->ConOut
->OutputString (gST
->ConOut
, (CHAR16
*) L
"\n");
3036 gActiveIfr
= MenuOption
->IfrNumber
;
3047 IN BOOLEAN Direction
,
3048 IN LIST_ENTRY
*CurrentPos
3052 Routine Description:
3053 Determine if the menu is the last menu that can be selected.
3056 Direction - the scroll direction. False is down. True is up.
3059 FALSE -- the menu isn't the last menu that can be selected.
3060 TRUE -- the menu is the last menu that can be selected.
3064 UI_MENU_OPTION
*MenuOption
;
3067 Temp
= Direction
? CurrentPos
->BackLink
: CurrentPos
->ForwardLink
;
3069 if (Temp
== &Menu
) {
3073 for (; Temp
!= &Menu
; Temp
= Direction
? Temp
->BackLink
: Temp
->ForwardLink
) {
3074 MenuOption
= CR (Temp
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3075 if (!(MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
)) {
3084 AdjustDateAndTimePosition (
3085 IN BOOLEAN DirectionUp
,
3086 IN LIST_ENTRY
**CurrentPosition
3089 Routine Description:
3090 Adjust Data and Time tag position accordingly.
3091 Data format : [01/02/2004] [11:22:33]
3092 Line number : 0 0 1 0 0 1
3095 Direction - the up or down direction. False is down. True is up.
3096 CurrentPos - Current position.
3099 Return line number to pad. It is possible that we stand on a zero-advance
3100 data or time opcode, so pad one line when we judge if we are going to scroll outside.
3104 LIST_ENTRY
*NewPosition
;
3105 UI_MENU_OPTION
*MenuOption
;
3106 UINTN PadLineNumber
;
3109 NewPosition
= *CurrentPosition
;
3110 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3112 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
3114 // Calculate the distance from current position to the last Date/Time op-code.
3117 while (MenuOption
->ThisTag
->NumberOfLines
== 0) {
3119 NewPosition
= NewPosition
->ForwardLink
;
3120 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3124 NewPosition
= *CurrentPosition
;
3127 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
3128 // to be one that back to the previous set of op-codes, we need to advance to the first
3129 // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate
3130 // checking can be done.
3132 while (Count
++ < 2) {
3133 NewPosition
= NewPosition
->BackLink
;
3137 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
3138 // to be one that progresses to the next set of op-codes, we need to advance to the last
3139 // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate
3140 // checking can be done.
3142 while (Count
-- > 0) {
3143 NewPosition
= NewPosition
->ForwardLink
;
3147 *CurrentPosition
= NewPosition
;
3150 return PadLineNumber
;