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_VARIABLE_DEFINITION
*UiDefaultVarDef
; // Only used in CfUiDefault State
1445 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
1446 EFI_HII_VARIABLE_PACK_LIST
*NvMapListHead
;
1447 EFI_HII_VARIABLE_PACK_LIST
*NvMapListNode
;
1451 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
1453 VariableDefinition
= NULL
;
1454 Status
= EFI_SUCCESS
;
1455 FormattedString
= NULL
;
1456 OptionString
= NULL
;
1457 ScreenOperation
= UiNoOperation
;
1459 FormCallback
= NULL
;
1460 FileFormTags
= NULL
;
1461 OutputString
= NULL
;
1466 MenuRefreshEntry
= gMenuRefreshHead
;
1467 OldMenuRefreshEntry
= gMenuRefreshHead
;
1468 NextMenuOption
= NULL
;
1469 PreviousMenuOption
= NULL
;
1470 SavedMenuOption
= NULL
;
1475 ZeroMem (&Key
, sizeof (EFI_INPUT_KEY
));
1477 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
1478 TopRow
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1479 Row
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1481 TopRow
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1482 Row
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1486 Col
= LocalScreen
.LeftColumn
;
1488 Col
= LocalScreen
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
;
1491 BottomRow
= LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
- SCROLL_ARROW_HEIGHT
- 1;
1493 TopOfScreen
= Menu
.ForwardLink
;
1498 // Get user's selection
1501 NewPos
= Menu
.ForwardLink
;
1502 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
1504 UpdateStatusBar (REFRESH_STATUS_BAR
, (UINT8
) 0, TRUE
);
1506 ControlFlag
= CfInitialization
;
1509 switch (ControlFlag
) {
1510 case CfInitialization
:
1511 ControlFlag
= CfCheckSelection
;
1512 if (gExitRequired
) {
1513 ScreenOperation
= UiReset
;
1514 ControlFlag
= CfScreenOperation
;
1515 } else if (gSaveRequired
) {
1516 ScreenOperation
= UiSave
;
1517 ControlFlag
= CfScreenOperation
;
1518 } else if (IsListEmpty (&Menu
)) {
1519 ControlFlag
= CfReadKey
;
1523 case CfCheckSelection
:
1524 if (Selection
!= NULL
) {
1525 ControlFlag
= CfExit
;
1527 ControlFlag
= CfRepaint
;
1530 FileFormTags
= FileFormTagsHead
;
1534 ControlFlag
= CfRefreshHighLight
;
1540 SavedMenuOption
= MenuOption
;
1549 LocalScreen
.LeftColumn
,
1550 LocalScreen
.RightColumn
,
1551 TopRow
- SCROLL_ARROW_HEIGHT
,
1552 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1553 FIELD_TEXT
| FIELD_BACKGROUND
1556 while (gMenuRefreshHead
!= NULL
) {
1557 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
1559 FreePool (gMenuRefreshHead
);
1561 gMenuRefreshHead
= OldMenuRefreshEntry
;
1564 for (Link
= TopOfScreen
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
1565 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1566 MenuOption
->Row
= Row
;
1568 MenuOption
->Col
= Col
;
1569 MenuOption
->OptCol
= gPromptBlockWidth
+ 1 + LocalScreen
.LeftColumn
;
1572 if (MenuOption
->ThisTag
->GrayOut
) {
1573 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1575 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1576 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1580 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1584 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1585 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1586 PrintStringAt (Col
, Row
, OutputString
);
1589 // If there is more string to process print on the next row and increment the Skip value
1591 if (StrLen (&MenuOption
->Description
[Index
])) {
1597 FreePool (OutputString
);
1607 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1608 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1610 if (OptionString
!= NULL
) {
1611 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1612 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1615 // If leading spaces on OptionString - remove the spaces
1617 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++) {
1618 MenuOption
->OptCol
++;
1621 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1622 OptionString
[Count
] = OptionString
[Index
];
1626 OptionString
[Count
] = CHAR_NULL
;
1630 // If this is a date or time op-code and is used to reflect an RTC, register the op-code
1632 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1633 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
) &&
1634 (MenuOption
->ThisTag
->StorageStart
>= FileFormTags
->FormTags
.Tags
[0].NvDataSize
)) {
1636 if (gMenuRefreshHead
== NULL
) {
1637 MenuRefreshEntry
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1638 ASSERT (MenuRefreshEntry
!= NULL
);
1639 MenuRefreshEntry
->MenuOption
= MenuOption
;
1640 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1641 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1642 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1643 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1644 gMenuRefreshHead
= MenuRefreshEntry
;
1647 // Advance to the last entry
1649 for (MenuRefreshEntry
= gMenuRefreshHead
;
1650 MenuRefreshEntry
->Next
!= NULL
;
1651 MenuRefreshEntry
= MenuRefreshEntry
->Next
1654 MenuRefreshEntry
->Next
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1655 ASSERT (MenuRefreshEntry
->Next
!= NULL
);
1656 MenuRefreshEntry
= MenuRefreshEntry
->Next
;
1657 MenuRefreshEntry
->MenuOption
= MenuOption
;
1658 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1659 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1660 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1661 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1665 Width
= (UINT16
) gOptionBlockWidth
;
1669 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1670 if ((Temp2
== 0) && (Row
<= BottomRow
)) {
1671 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1674 // If there is more string to process print on the next row and increment the Skip value
1676 if (StrLen (&OptionString
[Index
])) {
1680 // Since the Number of lines for this menu entry may or may not be reflected accurately
1681 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1682 // some testing to ensure we are keeping this in-sync.
1684 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1686 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1692 FreePool (OutputString
);
1702 // If this is a text op with secondary text information
1704 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
) && (MenuOption
->ThisTag
->TextTwo
!= 0)) {
1705 StringPtr
= GetToken (MenuOption
->ThisTag
->TextTwo
, MenuOption
->Handle
);
1707 Width
= (UINT16
) gOptionBlockWidth
;
1711 for (Index
= 0; GetLineByWidth (StringPtr
, Width
, &Index
, &OutputString
) != 0x0000;) {
1712 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1713 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1716 // If there is more string to process print on the next row and increment the Skip value
1718 if (StrLen (&StringPtr
[Index
])) {
1722 // Since the Number of lines for this menu entry may or may not be reflected accurately
1723 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1724 // some testing to ensure we are keeping this in-sync.
1726 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1728 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1734 FreePool (OutputString
);
1741 FreePool (StringPtr
);
1745 // For now, assume left-justified 72 width max setup entries
1747 PrintStringAt (Col
, Row
, MenuOption
->Description
);
1750 // Tracker 6210 - need to handle the bottom of the display
1752 if (MenuOption
->Skip
> 1) {
1753 Row
+= MenuOption
->Skip
- SkipValue
;
1756 Row
+= MenuOption
->Skip
;
1759 if (Row
> BottomRow
) {
1760 if (!ValueIsScroll (FALSE
, Link
)) {
1764 Row
= BottomRow
+ 1;
1769 if (!ValueIsScroll (TRUE
, TopOfScreen
)) {
1774 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1776 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1777 TopRow
- SCROLL_ARROW_HEIGHT
,
1781 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1785 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1787 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1788 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1792 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1795 if (SavedMenuOption
!= NULL
) {
1796 MenuOption
= SavedMenuOption
;
1801 case CfRefreshHighLight
:
1802 ControlFlag
= CfUpdateHelpString
;
1804 // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
1805 // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
1807 SavedValue
= Repaint
;
1810 if (NewPos
!= NULL
) {
1811 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1813 if (gLastOpr
&& (gEntryNumber
!= -1)) {
1814 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1815 if (gEntryNumber
!= MenuOption
->EntryNumber
) {
1816 ScreenOperation
= UiDown
;
1817 ControlFlag
= CfScreenOperation
;
1824 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1825 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1826 if (OptionString
!= NULL
) {
1827 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1828 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1831 // If leading spaces on OptionString - remove the spaces
1833 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1836 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1837 OptionString
[Count
] = OptionString
[Index
];
1841 OptionString
[Count
] = CHAR_NULL
;
1844 Width
= (UINT16
) gOptionBlockWidth
;
1846 OriginalRow
= MenuOption
->Row
;
1848 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1849 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1850 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1853 // If there is more string to process print on the next row and increment the Skip value
1855 if (StrLen (&OptionString
[Index
])) {
1859 FreePool (OutputString
);
1862 MenuOption
->Row
= OriginalRow
;
1865 if (MenuOption
->ThisTag
->GrayOut
) {
1866 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1868 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1869 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1873 OriginalRow
= MenuOption
->Row
;
1874 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1876 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1877 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1878 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1881 // If there is more string to process print on the next row and increment the Skip value
1883 if (StrLen (&MenuOption
->Description
[Index
])) {
1887 FreePool (OutputString
);
1890 MenuOption
->Row
= OriginalRow
;
1891 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1895 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1896 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
1899 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1901 if ((gPriorMenuEntry
!= 0) && (MenuOption
->EntryNumber
!= gPriorMenuEntry
) && (NewPos
->ForwardLink
!= &Menu
)) {
1902 ScreenOperation
= UiDown
;
1903 ControlFlag
= CfScreenOperation
;
1906 gPriorMenuEntry
= 0;
1909 // This is only possible if we entered this page and the first menu option is
1910 // a "non-menu" item. In that case, force it UiDown
1912 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
1914 // If we previously hit an UP command and we are still sitting on a text operation
1915 // we must continue going up
1917 if (ScreenOperation
== UiUp
) {
1918 ControlFlag
= CfScreenOperation
;
1921 ScreenOperation
= UiDown
;
1922 ControlFlag
= CfScreenOperation
;
1927 // Set reverse attribute
1929 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
);
1930 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1933 // Assuming that we have a refresh linked-list created, lets annotate the
1934 // appropriate entry that we are highlighting with its new attribute. Just prior to this
1935 // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
1937 if (gMenuRefreshHead
!= NULL
) {
1938 for (MenuRefreshEntry
= gMenuRefreshHead
; MenuRefreshEntry
!= NULL
; MenuRefreshEntry
= MenuRefreshEntry
->Next
) {
1939 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1940 if (MenuRefreshEntry
->MenuOption
== MenuOption
) {
1941 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
;
1947 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1948 if (OptionString
!= NULL
) {
1949 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1950 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1953 // If leading spaces on OptionString - remove the spaces
1955 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1958 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1959 OptionString
[Count
] = OptionString
[Index
];
1963 OptionString
[Count
] = CHAR_NULL
;
1965 Width
= (UINT16
) gOptionBlockWidth
;
1967 OriginalRow
= MenuOption
->Row
;
1969 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1970 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1971 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1974 // If there is more string to process print on the next row and increment the Skip value
1976 if (StrLen (&OptionString
[Index
])) {
1980 FreePool (OutputString
);
1983 MenuOption
->Row
= OriginalRow
;
1986 OriginalRow
= MenuOption
->Row
;
1988 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1990 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1991 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1992 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1995 // If there is more string to process print on the next row and increment the Skip value
1997 if (StrLen (&MenuOption
->Description
[Index
])) {
2001 FreePool (OutputString
);
2004 MenuOption
->Row
= OriginalRow
;
2009 if (((NewPos
->ForwardLink
!= &Menu
) && (ScreenOperation
== UiDown
)) ||
2010 ((NewPos
->BackLink
!= &Menu
) && (ScreenOperation
== UiUp
)) ||
2011 (ScreenOperation
== UiNoOperation
)
2013 UpdateKeyHelp (MenuOption
, FALSE
);
2016 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2019 // Clear reverse attribute
2021 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
2024 // Repaint flag will be used when process CfUpdateHelpString, so restore its value
2025 // if we didn't break halfway when process CfRefreshHighLight.
2027 Repaint
= SavedValue
;
2030 case CfUpdateHelpString
:
2031 ControlFlag
= CfPrepareToReadKey
;
2034 (Repaint
|| NewLine
||
2035 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2036 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) &&
2037 !(gClassOfVfr
== EFI_GENERAL_APPLICATION_SUBCLASS
)) {
2039 // Don't print anything if it is a NULL help token
2041 if (MenuOption
->ThisTag
->Help
== 0x00000000) {
2042 StringPtr
= (CHAR16
*) L
"\0";
2044 StringPtr
= GetToken (MenuOption
->ThisTag
->Help
, MenuOption
->Handle
);
2047 ProcessHelpString (StringPtr
, &FormattedString
, BottomRow
- TopRow
);
2049 gST
->ConOut
->SetAttribute (gST
->ConOut
, HELP_TEXT
| FIELD_BACKGROUND
);
2051 for (Index
= 0; Index
< BottomRow
- TopRow
; Index
++) {
2053 // Pad String with spaces to simulate a clearing of the previous line
2055 for (; GetStringWidth (&FormattedString
[Index
* gHelpBlockWidth
* 2]) / 2 < gHelpBlockWidth
;) {
2056 StrCat (&FormattedString
[Index
* gHelpBlockWidth
* 2], (CHAR16
*) L
" ");
2060 LocalScreen
.RightColumn
- gHelpBlockWidth
,
2062 &FormattedString
[Index
* gHelpBlockWidth
* 2]
2067 // Reset this flag every time we finish using it.
2073 case CfPrepareToReadKey
:
2074 ControlFlag
= CfReadKey
;
2076 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
2077 FileFormTags
= FileFormTags
->NextFile
;
2080 ScreenOperation
= UiNoOperation
;
2082 Status
= gBS
->HandleProtocol (
2083 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
2084 &gEfiFormCallbackProtocolGuid
,
2085 (VOID
**) &FormCallback
2091 ControlFlag
= CfScreenOperation
;
2093 OriginalTimeOut
= FrontPageTimeOutValue
;
2095 if (FrontPageTimeOutValue
>= 0 && (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) && FrontPageTimeOutValue
!= (INT16
) -1) {
2097 // Remember that if set to 0, must immediately boot an option
2099 if (FrontPageTimeOutValue
== 0) {
2100 FrontPageTimeOutValue
= 0xFFFF;
2101 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2102 if (EFI_ERROR (Status
)) {
2103 Status
= EFI_TIMEOUT
;
2108 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, ONE_SECOND
);
2109 if (Status
== EFI_TIMEOUT
) {
2110 EFI_IFR_DATA_ENTRY
*DataEntry
;
2112 DataEntry
= (EFI_IFR_DATA_ENTRY
*) (PageData
+ 1);
2114 PageData
->EntryCount
= 1;
2115 Count
= (UINT32
) ((OriginalTimeOut
- FrontPageTimeOutValue
) * 100 / OriginalTimeOut
);
2116 CopyMem (&DataEntry
->Data
, &Count
, sizeof (UINT32
));
2118 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2119 FormCallback
->Callback (
2122 (EFI_IFR_DATA_ARRAY
*) PageData
,
2127 // Count down 1 second
2129 FrontPageTimeOutValue
--;
2132 ASSERT (!EFI_ERROR (Status
));
2133 PageData
->EntryCount
= 0;
2134 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2135 FormCallback
->Callback (
2138 (EFI_IFR_DATA_ARRAY
*) PageData
,
2143 FrontPageTimeOutValue
= 0xFFFF;
2147 // Wait for user's selection, no auto boot
2149 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
2151 } while (Status
== EFI_TIMEOUT
);
2155 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2156 DisableQuietBoot ();
2159 if (Status
== EFI_TIMEOUT
) {
2160 Key
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
2162 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2164 // if we encounter error, continue to read another key in.
2166 if (EFI_ERROR (Status
)) {
2167 ControlFlag
= CfReadKey
;
2172 switch (Key
.UnicodeChar
) {
2173 case CHAR_CARRIAGE_RETURN
:
2174 Selection
= MenuOption
;
2175 ScreenOperation
= UiSelect
;
2180 // We will push the adjustment of these numeric values directly to the input handler
2184 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2186 if (Key
.UnicodeChar
== '+') {
2187 gDirection
= SCAN_RIGHT
;
2189 gDirection
= SCAN_LEFT
;
2192 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, NULL
, &OptionString
);
2197 ScreenOperation
= UiUp
;
2202 ScreenOperation
= UiDown
;
2206 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
2208 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_CHECKBOX_OP
&& !(MenuOption
->ThisTag
->GrayOut
)) {
2209 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
2210 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2211 Selection
= MenuOption
;
2212 ScreenOperation
= UiSelect
;
2219 if (((Key
.ScanCode
== SCAN_F1
) && ((gFunctionKeySetting
& FUNCTION_ONE
) != FUNCTION_ONE
)) ||
2220 ((Key
.ScanCode
== SCAN_F2
) && ((gFunctionKeySetting
& FUNCTION_TWO
) != FUNCTION_TWO
)) ||
2221 ((Key
.ScanCode
== SCAN_F9
) && ((gFunctionKeySetting
& FUNCTION_NINE
) != FUNCTION_NINE
)) ||
2222 ((Key
.ScanCode
== SCAN_F10
) && ((gFunctionKeySetting
& FUNCTION_TEN
) != FUNCTION_TEN
))
2225 // If the function key has been disabled, just ignore the key.
2228 for (Index
= 0; Index
< sizeof (gScanCodeToOperation
) / sizeof (gScanCodeToOperation
[0]); Index
++) {
2229 if (Key
.ScanCode
== gScanCodeToOperation
[Index
].ScanCode
) {
2230 if ((Key
.ScanCode
== SCAN_F9
) || (Key
.ScanCode
== SCAN_F10
)) {
2232 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2235 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2244 case CfScreenOperation
:
2245 IfrBinary
= gBinaryDataHead
;
2248 // Advance to the Ifr we are using
2250 for (Index
= 0; Index
< gActiveIfr
; Index
++) {
2251 IfrBinary
= IfrBinary
->Next
;
2254 if (ScreenOperation
!= UiPrevious
&& ScreenOperation
!= UiReset
) {
2256 // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
2257 // ignore the selection and go back to reading keys.
2259 if (IsListEmpty (&Menu
)) {
2260 ControlFlag
= CfReadKey
;
2264 // if there is nothing logical to place a cursor on, just move on to wait for a key.
2266 for (Link
= Menu
.ForwardLink
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
2267 NextMenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2268 if (!(NextMenuOption
->ThisTag
->GrayOut
) && (NextMenuOption
->ThisTag
->Operand
!= EFI_IFR_SUBTITLE_OP
)) {
2273 if (Link
== &Menu
) {
2274 ControlFlag
= CfPrepareToReadKey
;
2280 Index
< sizeof (gScreenOperationToControlFlag
) / sizeof (gScreenOperationToControlFlag
[0]);
2283 if (ScreenOperation
== gScreenOperationToControlFlag
[Index
].ScreenOperation
) {
2284 ControlFlag
= gScreenOperationToControlFlag
[Index
].ControlFlag
;
2291 ControlFlag
= CfCheckSelection
;
2293 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2295 if (MenuOption
!= NULL
) {
2296 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2303 if (IsListEmpty (&gMenuList
)) {
2305 if (IsListEmpty (&Menu
)) {
2306 ControlFlag
= CfReadKey
;
2313 while (gMenuRefreshHead
!= NULL
) {
2314 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
2316 FreePool (gMenuRefreshHead
);
2318 gMenuRefreshHead
= OldMenuRefreshEntry
;
2321 // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag
2324 UiRemoveMenuListEntry (MenuOption
, &Selection
);
2325 Selection
->Previous
= TRUE
;
2330 gActiveIfr
= Selection
->IfrNumber
;
2334 ControlFlag
= CfCheckSelection
;
2336 ExtractRequestedNvMap (FileFormTags
, MenuOption
->ThisTag
->VariableNumber
, &VariableDefinition
);
2339 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
&&
2340 !(MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
)) ||
2341 (MenuOption
->ThisTag
->GrayOut
) ||
2342 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2343 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2349 UpdateKeyHelp (MenuOption
, TRUE
);
2350 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, PageData
, &OptionString
);
2352 if (EFI_ERROR (Status
)) {
2358 if (OptionString
!= NULL
) {
2359 PrintStringAt (LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ 1, MenuOption
->Row
, OptionString
);
2362 if (MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
2363 Selection
= MenuOption
;
2366 if (Selection
== NULL
) {
2370 Location
= (UINT8
*) &PageData
->EntryCount
;
2373 // If not a goto, dump single piece of data, otherwise dump everything
2375 if (Selection
->ThisTag
->Operand
== EFI_IFR_REF_OP
) {
2377 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2379 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2385 UiAddMenuListEntry (Selection
);
2386 gPriorMenuEntry
= 0;
2389 // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious
2391 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
2392 UiMenuList
->FormerEntryNumber
= MenuOption
->EntryNumber
;
2397 // Rewind to the beginning of the menu
2399 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2403 // Get Total Count of Menu entries
2405 for (Count
= 1; NewPos
->ForwardLink
!= &Menu
; NewPos
= NewPos
->ForwardLink
) {
2409 // Rewind to the beginning of the menu
2411 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2415 // Copy the number of entries being described to the PageData location
2417 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2419 for (Index
= 4; NewPos
->ForwardLink
!= &Menu
; Index
= Index
+ MenuOption
->ThisTag
->StorageWidth
+ 2) {
2421 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2422 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2423 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2425 &Location
[Index
+ 4],
2426 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2427 MenuOption
->ThisTag
->StorageWidth
2429 NewPos
= NewPos
->ForwardLink
;
2433 gPriorMenuEntry
= MenuOption
->EntryNumber
;
2438 // Copy the number of entries being described to the PageData location
2440 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2443 // Start at PageData[4] since the EntryCount is a UINT32
2448 // Copy data to destination
2450 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2451 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2453 &Location
[Index
+ 4],
2454 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2455 MenuOption
->ThisTag
->StorageWidth
2462 ControlFlag
= CfCheckSelection
;
2464 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
2468 // If NV flag is up, prompt user
2470 if (gNvUpdateRequired
) {
2471 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2473 YesResponse
= gYesResponse
[0];
2474 NoResponse
= gNoResponse
[0];
2477 CreateDialog (3, TRUE
, 0, NULL
, &Key
, gEmptyString
, gAreYouSure
, gEmptyString
);
2480 (Key
.ScanCode
!= SCAN_ESC
) &&
2481 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
| UPPER_LOWER_CASE_OFFSET
)) &&
2482 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
| UPPER_LOWER_CASE_OFFSET
))
2486 // If the user hits the YesResponse key
2488 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
| UPPER_LOWER_CASE_OFFSET
)) {
2496 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2498 if (MenuOption
!= NULL
) {
2499 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2507 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2508 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
2512 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2516 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2517 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2519 if (IfrBinary
->UnRegisterOnExit
) {
2520 Hii
->RemovePack (Hii
, MenuOption
->Handle
);
2526 // Clean up the allocated data buffers
2528 FreeData (FileFormTagsHead
, FormattedString
, OptionString
);
2530 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2534 ControlFlag
= CfCheckSelection
;
2535 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2536 if (MenuOption
->Skip
== 1) {
2538 // In the tail of the Date/Time op-code set, go left.
2540 NewPos
= NewPos
->BackLink
;
2543 // In the middle of the Data/Time op-code set, go left.
2545 NextMenuOption
= CR (NewPos
->ForwardLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2546 if (NextMenuOption
->Skip
== 1) {
2547 NewPos
= NewPos
->BackLink
;
2554 ControlFlag
= CfCheckSelection
;
2555 if ((MenuOption
->Skip
== 0) &&
2556 ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
))
2559 // We are in the head or middle of the Date/Time op-code set, advance right.
2561 NewPos
= NewPos
->ForwardLink
;
2566 ControlFlag
= CfCheckSelection
;
2568 if (NewPos
->BackLink
!= &Menu
) {
2571 // Adjust Date/Time position before we advance forward.
2573 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2576 // Caution that we have already rewind to the top, don't go backward in this situation.
2578 if (NewPos
->BackLink
!= &Menu
) {
2579 NewPos
= NewPos
->BackLink
;
2582 PreviousMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2585 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
2586 // to be one that back to the previous set of op-codes, we need to advance to the sencond
2587 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2588 // checking can be done.
2590 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (TRUE
, &NewPos
);
2594 // If the previous MenuOption contains a display-only op-code, skip to the next one
2596 if (PreviousMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| PreviousMenuOption
->ThisTag
->GrayOut
) {
2598 // This is ok as long as not at the end of the list
2600 if (NewPos
->BackLink
== &Menu
) {
2602 // If we are at the start of the list, then this list must start with a display only
2603 // piece of data, so do not allow the backward motion
2605 ScreenOperation
= UiDown
;
2607 if (PreviousMenuOption
->Row
<= TopRow
) {
2608 if (TopOfScreen
->BackLink
!= &Menu
) {
2609 TopOfScreen
= TopOfScreen
->BackLink
;
2614 UpdateStatusBar (INPUT_ERROR
, PreviousMenuOption
->ThisTag
->Flags
, FALSE
);
2620 // Check the previous menu entry to see if it was a zero-length advance. If it was,
2621 // don't worry about a redraw.
2623 if ((MenuOption
->Row
- PreviousMenuOption
->Skip
- DataAndTimeLineNumberPad
< TopRow
) ||
2624 (PreviousMenuOption
->Skip
> MenuOption
->Row
)
2627 if (TopOfScreen
->BackLink
== &Menu
) {
2634 // Is the current top of screen a zero-advance op-code?
2635 // If so, keep moving forward till we hit a >0 advance op-code
2637 SavedMenuOption
= CR (TopOfScreen
->BackLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2638 TopOfScreen
= TopOfScreen
->BackLink
;
2639 } while (SavedMenuOption
->Skip
== 0);
2641 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2643 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2646 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2649 SavedMenuOption
= MenuOption
;
2650 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2651 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2653 // If we are at the end of the list and sitting on a text op, we need to more forward
2655 ScreenOperation
= UiDown
;
2656 ControlFlag
= CfScreenOperation
;
2660 MenuOption
= SavedMenuOption
;
2666 ControlFlag
= CfCheckSelection
;
2668 SavedListEntry
= NewPos
;
2670 for (Index
= BottomRow
; Index
>= TopRow
+ 1; Index
-= MenuOption
->Skip
) {
2671 if (Link
->BackLink
== &Menu
) {
2673 Link
= SavedListEntry
;
2674 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2680 Link
= Link
->BackLink
;
2681 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2683 SavedListEntry
= Link
;
2689 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2690 // Don't do this when we are already in the first page.
2693 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2694 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2695 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2700 ControlFlag
= CfCheckSelection
;
2702 SavedListEntry
= NewPos
;
2704 NewPos
= TopOfScreen
;
2705 for (Index
= TopRow
; Index
<= BottomRow
- 1; Index
+= MenuOption
->Skip
) {
2706 if (NewPos
->ForwardLink
== &Menu
) {
2707 NewPos
= SavedListEntry
;
2708 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2717 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2718 NewPos
= NewPos
->ForwardLink
;
2725 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2726 // Don't do this when we are already in the last page.
2729 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2730 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2731 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2736 ControlFlag
= CfCheckSelection
;
2738 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
2739 // to be one that progresses to the next set of op-codes, we need to advance to the last
2740 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2741 // checking can be done. The only other logic we need to introduce is that if a Date/Time
2742 // op-code is the last entry in the menu, we need to rewind back to the first op-code of
2743 // the Date/Time op-code.
2745 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (FALSE
, &NewPos
);
2747 if (NewPos
->ForwardLink
!= &Menu
) {
2749 NewPos
= NewPos
->ForwardLink
;
2750 NextMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2754 // If the next MenuOption contains a display-only op-code, skip to the next one
2755 // Also if the next MenuOption is date or time,
2757 if (NextMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| NextMenuOption
->ThisTag
->GrayOut
) {
2759 // This is ok as long as not at the end of the list
2761 if (NewPos
== &Menu
) {
2763 // If we are at the end of the list, then this list must end with a display only
2764 // piece of data, so do not allow the forward motion
2766 UpdateStatusBar (INPUT_ERROR
, NextMenuOption
->ThisTag
->Flags
, FALSE
);
2767 NewPos
= NewPos
->BackLink
;
2768 ScreenOperation
= UiUp
;
2774 // An option might be multi-line, so we need to reflect that data in the overall skip value
2776 UpdateOptionSkipLines (PageData
, NextMenuOption
, FileFormTagsHead
, &OptionString
, SkipValue
);
2778 if (NextMenuOption
->Skip
> 1) {
2779 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ NextMenuOption
->Skip
- 1;
2781 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ DataAndTimeLineNumberPad
;
2784 // If we are going to scroll
2786 if (Temp
> BottomRow
) {
2789 // Is the current top of screen a zero-advance op-code?
2790 // If so, keep moving forward till we hit a >0 advance op-code
2792 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2795 // If bottom op-code is more than one line or top op-code is more than one line
2797 if ((NextMenuOption
->Skip
> 1) || (MenuOption
->Skip
> 1)) {
2799 // Is the bottom op-code greater than or equal in size to the top op-code?
2801 if ((Temp
- BottomRow
) >= (SavedMenuOption
->Skip
- OldSkipValue
)) {
2803 // Skip the top op-code
2805 TopOfScreen
= TopOfScreen
->ForwardLink
;
2806 Difference
= (Temp
- BottomRow
) - (SavedMenuOption
->Skip
- OldSkipValue
);
2808 OldSkipValue
= Difference
;
2810 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2813 // If we have a remainder, skip that many more op-codes until we drain the remainder
2816 Difference
>= (INTN
) SavedMenuOption
->Skip
;
2817 Difference
= Difference
- (INTN
) SavedMenuOption
->Skip
2820 // Since the Difference is greater than or equal to this op-code's skip value, skip it
2822 TopOfScreen
= TopOfScreen
->ForwardLink
;
2823 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2824 if (Difference
< (INTN
) SavedMenuOption
->Skip
) {
2825 Difference
= SavedMenuOption
->Skip
- Difference
- 1;
2828 if (Difference
== (INTN
) SavedMenuOption
->Skip
) {
2829 TopOfScreen
= TopOfScreen
->ForwardLink
;
2830 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2831 Difference
= SavedMenuOption
->Skip
- Difference
;
2837 // Since we will act on this op-code in the next routine, and increment the
2838 // SkipValue, set the skips to one less than what is required.
2840 SkipValue
= Difference
- 1;
2844 // Since we will act on this op-code in the next routine, and increment the
2845 // SkipValue, set the skips to one less than what is required.
2847 SkipValue
= OldSkipValue
+ (Temp
- BottomRow
) - 1;
2850 if ((OldSkipValue
+ 1) == (INTN
) SavedMenuOption
->Skip
) {
2851 TopOfScreen
= TopOfScreen
->ForwardLink
;
2854 SkipValue
= OldSkipValue
;
2858 // If the op-code at the top of the screen is more than one line, let's not skip it yet
2859 // Let's set a skip flag to smoothly scroll the top of the screen.
2861 if (SavedMenuOption
->Skip
> 1) {
2862 if (SavedMenuOption
== NextMenuOption
) {
2869 TopOfScreen
= TopOfScreen
->ForwardLink
;
2871 } while (SavedMenuOption
->Skip
== 0);
2874 OldSkipValue
= SkipValue
;
2877 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2881 SavedMenuOption
= MenuOption
;
2882 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2883 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2885 // If we are at the end of the list and sitting on a text op, we need to more forward
2887 ScreenOperation
= UiUp
;
2888 ControlFlag
= CfScreenOperation
;
2892 MenuOption
= SavedMenuOption
;
2894 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
2896 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2902 ControlFlag
= CfCheckSelection
;
2904 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2906 if (MenuOption
!= NULL
) {
2907 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2914 // If callbacks are active, and the callback has a Write method, try to use it
2916 if (FileFormTags
->VariableDefinitions
->VariableName
== NULL
) {
2917 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2918 Status
= FormCallback
->NvWrite (
2920 (CHAR16
*) L
"Setup",
2921 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2922 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2923 VariableDefinition
->VariableSize
,
2924 (VOID
*) VariableDefinition
->NvRamMap
,
2929 Status
= gRT
->SetVariable (
2930 (CHAR16
*) L
"Setup",
2931 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2932 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2933 VariableDefinition
->VariableSize
,
2934 (VOID
*) VariableDefinition
->NvRamMap
2938 VariableDefinition
= FileFormTags
->VariableDefinitions
;
2940 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
2941 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2942 Status
= FormCallback
->NvWrite (
2944 VariableDefinition
->VariableName
,
2945 &VariableDefinition
->Guid
,
2946 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2947 VariableDefinition
->VariableSize
,
2948 (VOID
*) VariableDefinition
->NvRamMap
,
2953 Status
= gRT
->SetVariable (
2954 VariableDefinition
->VariableName
,
2955 &VariableDefinition
->Guid
,
2956 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2957 VariableDefinition
->VariableSize
,
2958 (VOID
*) VariableDefinition
->NvRamMap
2964 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2965 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2969 ControlFlag
= CfCheckSelection
;
2971 NvMapListHead
= NULL
;
2973 Status
= Hii
->GetDefaultImage (Hii
, MenuOption
->Handle
, EFI_IFR_FLAG_DEFAULT
, &NvMapListHead
);
2975 if (!EFI_ERROR (Status
)) {
2976 ASSERT_EFI_ERROR (NULL
!= NvMapListHead
);
2978 NvMapListNode
= NvMapListHead
;
2980 while (NULL
!= NvMapListNode
) {
2982 for (UiDefaultVarDef
= FileFormTags
->VariableDefinitions
;
2983 UiDefaultVarDef
!= NULL
;
2984 UiDefaultVarDef
= UiDefaultVarDef
->Next
) {
2986 if (UiDefaultVarDef
->VariableId
== NvMapListNode
->VariablePack
->VariableId
) {
2987 NvMap
= (VOID
*) ((CHAR8
*) NvMapListNode
->VariablePack
+ sizeof (EFI_HII_VARIABLE_PACK
) + NvMapListNode
->VariablePack
->VariableNameLength
);
2988 NvMapSize
= NvMapListNode
->VariablePack
->Header
.Length
- sizeof (EFI_HII_VARIABLE_PACK
) - NvMapListNode
->VariablePack
->VariableNameLength
;
2990 // Free the buffer that was allocated.
2992 FreePool (UiDefaultVarDef
->NvRamMap
);
2993 FreePool (UiDefaultVarDef
->FakeNvRamMap
);
2996 // Allocate, copy the NvRamMap.
2998 UiDefaultVarDef
->VariableFakeSize
= (UINT16
) (UiDefaultVarDef
->VariableFakeSize
- UiDefaultVarDef
->VariableSize
);
2999 UiDefaultVarDef
->VariableSize
= (UINT16
) NvMapSize
;
3000 UiDefaultVarDef
->VariableFakeSize
= (UINT16
) (UiDefaultVarDef
->VariableFakeSize
+ UiDefaultVarDef
->VariableSize
);
3002 UiDefaultVarDef
->NvRamMap
= AllocateZeroPool (FileFormTags
->VariableDefinitions
->VariableSize
);
3003 ASSERT (UiDefaultVarDef
->NvRamMap
!= NULL
);
3005 UiDefaultVarDef
->FakeNvRamMap
= AllocateZeroPool (NvMapSize
+ UiDefaultVarDef
->VariableFakeSize
);
3006 ASSERT (UiDefaultVarDef
->FakeNvRamMap
!= NULL
);
3008 CopyMem (UiDefaultVarDef
->NvRamMap
, NvMap
, NvMapSize
);
3012 NvMapListNode
= NvMapListNode
->NextVariablePack
;
3015 FreePool (NvMapListHead
);
3018 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, TRUE
);
3021 // After the repaint operation, we should refresh the highlight.
3026 case CfUiNoOperation
:
3027 ControlFlag
= CfCheckSelection
;
3031 while (gMenuRefreshHead
!= NULL
) {
3032 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
3034 FreePool (gMenuRefreshHead
);
3036 gMenuRefreshHead
= OldMenuRefreshEntry
;
3039 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, 0, Row
+ 4);
3040 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
3041 gST
->ConOut
->OutputString (gST
->ConOut
, (CHAR16
*) L
"\n");
3043 gActiveIfr
= MenuOption
->IfrNumber
;
3054 IN BOOLEAN Direction
,
3055 IN LIST_ENTRY
*CurrentPos
3059 Routine Description:
3060 Determine if the menu is the last menu that can be selected.
3063 Direction - the scroll direction. False is down. True is up.
3066 FALSE -- the menu isn't the last menu that can be selected.
3067 TRUE -- the menu is the last menu that can be selected.
3071 UI_MENU_OPTION
*MenuOption
;
3074 Temp
= Direction
? CurrentPos
->BackLink
: CurrentPos
->ForwardLink
;
3076 if (Temp
== &Menu
) {
3080 for (; Temp
!= &Menu
; Temp
= Direction
? Temp
->BackLink
: Temp
->ForwardLink
) {
3081 MenuOption
= CR (Temp
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3082 if (!(MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
)) {
3091 AdjustDateAndTimePosition (
3092 IN BOOLEAN DirectionUp
,
3093 IN LIST_ENTRY
**CurrentPosition
3096 Routine Description:
3097 Adjust Data and Time tag position accordingly.
3098 Data format : [01/02/2004] [11:22:33]
3099 Line number : 0 0 1 0 0 1
3102 Direction - the up or down direction. False is down. True is up.
3103 CurrentPos - Current position.
3106 Return line number to pad. It is possible that we stand on a zero-advance
3107 data or time opcode, so pad one line when we judge if we are going to scroll outside.
3111 LIST_ENTRY
*NewPosition
;
3112 UI_MENU_OPTION
*MenuOption
;
3113 UINTN PadLineNumber
;
3116 NewPosition
= *CurrentPosition
;
3117 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3119 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
3121 // Calculate the distance from current position to the last Date/Time op-code.
3124 while (MenuOption
->ThisTag
->NumberOfLines
== 0) {
3126 NewPosition
= NewPosition
->ForwardLink
;
3127 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3131 NewPosition
= *CurrentPosition
;
3134 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
3135 // to be one that back to the previous set of op-codes, we need to advance to the first
3136 // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate
3137 // checking can be done.
3139 while (Count
++ < 2) {
3140 NewPosition
= NewPosition
->BackLink
;
3144 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
3145 // to be one that progresses to the next set of op-codes, we need to advance to the last
3146 // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate
3147 // checking can be done.
3149 while (Count
-- > 0) {
3150 NewPosition
= NewPosition
->ForwardLink
;
3154 *CurrentPosition
= NewPosition
;
3157 return PadLineNumber
;