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.
32 Set Buffer to Value for Size bytes.
36 Buffer - Memory to set.
38 Size - Number of bytes to set
40 Value - Value of the set operation.
63 Initialize Menu option list.
71 InitializeListHead (&Menu
);
81 Initialize Menu option list.
89 InitializeListHead (&gMenuList
);
93 UiRemoveMenuListEntry (
94 IN UI_MENU_OPTION
*Selection
,
95 OUT UI_MENU_OPTION
**PreviousSelection
100 Remove Menu option list.
108 UI_MENU_LIST
*UiMenuList
;
110 *PreviousSelection
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
111 ASSERT (*PreviousSelection
!= NULL
);
113 if (!IsListEmpty (&gMenuList
)) {
114 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
115 (*PreviousSelection
)->IfrNumber
= UiMenuList
->Selection
.IfrNumber
;
116 (*PreviousSelection
)->FormId
= UiMenuList
->Selection
.FormId
;
117 (*PreviousSelection
)->Tags
= UiMenuList
->Selection
.Tags
;
118 (*PreviousSelection
)->ThisTag
= UiMenuList
->Selection
.ThisTag
;
119 (*PreviousSelection
)->Handle
= UiMenuList
->Selection
.Handle
;
120 gEntryNumber
= UiMenuList
->FormerEntryNumber
;
121 RemoveEntryList (&UiMenuList
->MenuLink
);
122 FreePool (UiMenuList
);
133 Free Menu option linked list.
141 UI_MENU_LIST
*UiMenuList
;
143 while (!IsListEmpty (&gMenuList
)) {
144 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
145 RemoveEntryList (&UiMenuList
->MenuLink
);
146 FreePool (UiMenuList
);
152 IN UI_MENU_OPTION
*Selection
157 Add one menu entry to the linked lst
165 UI_MENU_LIST
*UiMenuList
;
167 UiMenuList
= AllocateZeroPool (sizeof (UI_MENU_LIST
));
168 ASSERT (UiMenuList
!= NULL
);
170 UiMenuList
->Signature
= UI_MENU_LIST_SIGNATURE
;
171 CopyMem (&UiMenuList
->Selection
, Selection
, sizeof (UI_MENU_OPTION
));
173 InsertHeadList (&gMenuList
, &UiMenuList
->MenuLink
);
183 Free Menu option linked list.
191 UI_MENU_OPTION
*MenuOption
;
193 while (!IsListEmpty (&Menu
)) {
194 MenuOption
= CR (Menu
.ForwardLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
195 RemoveEntryList (&MenuOption
->Link
);
198 // We allocated space for this description when we did a GetToken, free it here
200 FreePool (MenuOption
->Description
);
201 FreePool (MenuOption
);
213 Refresh screen with current date and/or time based on screen context
221 CHAR16
*OptionString
;
222 MENU_REFRESH_ENTRY
*MenuRefreshEntry
;
228 if (gMenuRefreshHead
!= NULL
) {
230 MenuRefreshEntry
= gMenuRefreshHead
;
233 gST
->ConOut
->SetAttribute (gST
->ConOut
, MenuRefreshEntry
->CurrentAttribute
);
234 ProcessOptions (MenuRefreshEntry
->MenuOption
, FALSE
, MenuRefreshEntry
->FileFormTagsHead
, NULL
, &OptionString
);
236 if (OptionString
!= NULL
) {
238 // If leading spaces on OptionString - remove the spaces
240 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
243 for (Loop
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
244 OptionString
[Loop
] = OptionString
[Index
];
248 OptionString
[Loop
] = CHAR_NULL
;
250 PrintStringAt (MenuRefreshEntry
->CurrentColumn
, MenuRefreshEntry
->CurrentRow
, OptionString
);
253 MenuRefreshEntry
= MenuRefreshEntry
->Next
;
255 } while (MenuRefreshEntry
!= NULL
);
258 if (OptionString
!= NULL
) {
259 FreePool (OptionString
);
264 UiWaitForSingleEvent (
266 IN UINT64 Timeout OPTIONAL
271 Wait for a given event to fire, or for an optional timeout to expire.
274 Event - The event to wait for
276 Timeout - An optional timeout value in 100 ns units.
280 EFI_SUCCESS - Event fired before Timeout expired.
281 EFI_TIME_OUT - Timout expired before Event fired.
287 EFI_EVENT TimerEvent
;
288 EFI_EVENT WaitList
[2];
292 // Create a timer event
294 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
295 if (!EFI_ERROR (Status
)) {
297 // Set the timer event
306 // Wait for the original event or the timer
309 WaitList
[1] = TimerEvent
;
310 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
311 gBS
->CloseEvent (TimerEvent
);
314 // If the timer expired, change the return to timed out
316 if (!EFI_ERROR (Status
) && Index
== 1) {
317 Status
= EFI_TIMEOUT
;
322 // Update screen every second
324 Timeout
= ONE_SECOND
;
327 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
330 // Set the timer event
339 // Wait for the original event or the timer
342 WaitList
[1] = TimerEvent
;
343 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
346 // If the timer expired, update anything that needs a refresh and keep waiting
348 if (!EFI_ERROR (Status
) && Index
== 1) {
349 Status
= EFI_TIMEOUT
;
350 UpdateDateAndTime ();
353 gBS
->CloseEvent (TimerEvent
);
354 } while (Status
== EFI_TIMEOUT
);
363 IN EFI_HII_HANDLE Handle
,
371 Add one menu option by specified description and context.
374 String - String description for this option.
375 Context - Context data for entry.
381 UI_MENU_OPTION
*MenuOption
;
383 MenuOption
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
386 MenuOption
->Signature
= UI_MENU_OPTION_SIGNATURE
;
387 MenuOption
->Description
= String
;
388 MenuOption
->Handle
= Handle
;
389 MenuOption
->FormBinary
= FormBinary
;
390 MenuOption
->IfrNumber
= IfrNumber
;
391 MenuOption
->Skip
= 1;
392 MenuOption
->Tags
= Tags
;
393 MenuOption
->TagIndex
= 0;
394 MenuOption
->ThisTag
= &(MenuOption
->Tags
[MenuOption
->TagIndex
]);
395 MenuOption
->EntryNumber
= (UINT16
) IfrNumber
;
397 InsertTailList (&Menu
, &MenuOption
->Link
);
403 IN EFI_HII_HANDLE Handle
,
407 IN UINT16 MenuItemCount
412 Add one menu option by specified description and context.
415 String - String description for this option.
416 Context - Context data for entry.
422 UI_MENU_OPTION
*MenuOption
;
424 MenuOption
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
427 MenuOption
->Signature
= UI_MENU_OPTION_SIGNATURE
;
428 MenuOption
->Description
= String
;
429 MenuOption
->Handle
= Handle
;
430 MenuOption
->Skip
= Tags
[TagIndex
].NumberOfLines
;
431 MenuOption
->IfrNumber
= gActiveIfr
;
432 MenuOption
->Tags
= Tags
;
433 MenuOption
->TagIndex
= TagIndex
;
434 MenuOption
->ThisTag
= &(MenuOption
->Tags
[MenuOption
->TagIndex
]);
435 MenuOption
->Consistency
= Tags
[TagIndex
].Consistency
;
436 MenuOption
->FormId
= FormId
;
437 MenuOption
->GrayOut
= Tags
[TagIndex
].GrayOut
;
438 MenuOption
->EntryNumber
= MenuItemCount
;
440 InsertTailList (&Menu
, &MenuOption
->Link
);
445 IN UINTN NumberOfLines
,
447 IN UINTN MaximumStringSize
,
448 OUT CHAR16
*StringBuffer
,
449 OUT EFI_INPUT_KEY
*KeyValue
,
456 Routine used to abstract a generic dialog interface and return the selected key or string
459 NumberOfLines - The number of lines for the dialog box
460 HotKey - Defines whether a single character is parsed (TRUE) and returned in KeyValue
461 or a string is returned in StringBuffer. Two special characters are considered when entering a string, a SCAN_ESC and
462 an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates string input and returns
463 MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes
464 StringBuffer - The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE
465 KeyValue - The EFI_KEY value returned if HotKey is TRUE..
466 String - Pointer to the first string in the list
467 ... - A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box
470 EFI_SUCCESS - Displayed dialog and received user interaction
471 EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE))
472 EFI_DEVICE_ERROR - User typed in an ESC character to exit the routine
481 CHAR16
*BufferedString
;
487 BOOLEAN SelectionComplete
;
489 UINTN CurrentAttribute
;
490 UINTN DimensionsWidth
;
491 UINTN DimensionsHeight
;
493 DimensionsWidth
= gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
;
494 DimensionsHeight
= gScreenDimensions
.BottomRow
- gScreenDimensions
.TopRow
;
496 SelectionComplete
= FALSE
;
498 TempString
= AllocateZeroPool (MaximumStringSize
* 2);
499 BufferedString
= AllocateZeroPool (MaximumStringSize
* 2);
500 CurrentAttribute
= gST
->ConOut
->Mode
->Attribute
;
503 ASSERT (BufferedString
);
505 VA_START (Marker
, String
);
508 // Zero the outgoing buffer
510 ZeroMem (StringBuffer
, MaximumStringSize
);
513 if (KeyValue
== NULL
) {
514 return EFI_INVALID_PARAMETER
;
517 if (StringBuffer
== NULL
) {
518 return EFI_INVALID_PARAMETER
;
524 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
526 LargestString
= (GetStringWidth (String
) / 2);
528 if (LargestString
== L
' ') {
532 // Determine the largest string in the dialog box
533 // Notice we are starting with 1 since String is the first string
535 for (Count
= 1; Count
< NumberOfLines
; Count
++) {
536 StackString
= VA_ARG (Marker
, CHAR16
*);
538 if (StackString
[0] == L
' ') {
539 InputOffset
= Count
+ 1;
542 if ((GetStringWidth (StackString
) / 2) > LargestString
) {
544 // Size of the string visually and subtract the width by one for the null-terminator
546 LargestString
= (GetStringWidth (StackString
) / 2);
550 Start
= (DimensionsWidth
- LargestString
- 2) / 2 + gScreenDimensions
.LeftColumn
+ 1;
551 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gScreenDimensions
.TopRow
- 1;
558 CreateSharedPopUp (LargestString
, NumberOfLines
, &String
);
561 // Take the first key typed and report it back?
564 WaitForKeyStroke (&Key
);
565 CopyMem (KeyValue
, &Key
, sizeof (EFI_INPUT_KEY
));
569 WaitForKeyStroke (&Key
);
571 switch (Key
.UnicodeChar
) {
573 switch (Key
.ScanCode
) {
575 FreePool (TempString
);
576 FreePool (BufferedString
);
577 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
578 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
579 return EFI_DEVICE_ERROR
;
587 case CHAR_CARRIAGE_RETURN
:
588 SelectionComplete
= TRUE
;
589 FreePool (TempString
);
590 FreePool (BufferedString
);
591 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
592 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
597 if (StringBuffer
[0] != CHAR_NULL
) {
598 for (Index
= 0; StringBuffer
[Index
] != CHAR_NULL
; Index
++) {
599 TempString
[Index
] = StringBuffer
[Index
];
602 // Effectively truncate string by 1 character
604 TempString
[Index
- 1] = CHAR_NULL
;
605 StrCpy (StringBuffer
, TempString
);
610 // If it is the beginning of the string, don't worry about checking maximum limits
612 if ((StringBuffer
[0] == CHAR_NULL
) && (Key
.UnicodeChar
!= CHAR_BACKSPACE
)) {
613 StrnCpy (StringBuffer
, &Key
.UnicodeChar
, 1);
614 StrnCpy (TempString
, &Key
.UnicodeChar
, 1);
615 } else if ((GetStringWidth (StringBuffer
) < MaximumStringSize
) && (Key
.UnicodeChar
!= CHAR_BACKSPACE
)) {
616 KeyPad
[0] = Key
.UnicodeChar
;
617 KeyPad
[1] = CHAR_NULL
;
618 StrCat (StringBuffer
, KeyPad
);
619 StrCat (TempString
, KeyPad
);
622 // If the width of the input string is now larger than the screen, we nee to
623 // adjust the index to start printing portions of the string
625 SetUnicodeMem (BufferedString
, LargestString
, L
' ');
627 PrintStringAt (Start
+ 1, Top
+ InputOffset
, BufferedString
);
629 if ((GetStringWidth (StringBuffer
) / 2) > (DimensionsWidth
- 2)) {
630 Index
= (GetStringWidth (StringBuffer
) / 2) - DimensionsWidth
+ 2;
635 for (Count
= 0; Index
+ 1 < GetStringWidth (StringBuffer
) / 2; Index
++, Count
++) {
636 BufferedString
[Count
] = StringBuffer
[Index
];
639 PrintStringAt (Start
+ 1, Top
+ InputOffset
, BufferedString
);
642 } while (!SelectionComplete
);
645 gST
->ConOut
->SetAttribute (gST
->ConOut
, CurrentAttribute
);
646 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
652 IN UINTN RequestedWidth
,
653 IN UINTN NumberOfLines
,
654 IN CHAR16
**ArrayOfStrings
666 UINTN DimensionsWidth
;
667 UINTN DimensionsHeight
;
669 DimensionsWidth
= gScreenDimensions
.RightColumn
- gScreenDimensions
.LeftColumn
;
670 DimensionsHeight
= gScreenDimensions
.BottomRow
- gScreenDimensions
.TopRow
;
674 gST
->ConOut
->SetAttribute (gST
->ConOut
, POPUP_TEXT
| POPUP_BACKGROUND
);
676 if ((RequestedWidth
+ 2) > DimensionsWidth
) {
677 RequestedWidth
= DimensionsWidth
- 2;
680 // Subtract the PopUp width from total Columns, allow for one space extra on
681 // each end plus a border.
683 Start
= (DimensionsWidth
- RequestedWidth
- 2) / 2 + gScreenDimensions
.LeftColumn
+ 1;
684 End
= Start
+ RequestedWidth
+ 1;
686 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gScreenDimensions
.TopRow
- 1;
687 Bottom
= Top
+ NumberOfLines
+ 2;
689 Character
= (CHAR16
) BOXDRAW_DOWN_RIGHT
;
690 PrintCharAt (Start
, Top
, Character
);
691 Character
= (CHAR16
) BOXDRAW_HORIZONTAL
;
692 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
693 PrintChar (Character
);
696 Character
= (CHAR16
) BOXDRAW_DOWN_LEFT
;
697 PrintChar (Character
);
698 Character
= (CHAR16
) BOXDRAW_VERTICAL
;
699 for (Index
= Top
; Index
+ 2 < Bottom
; Index
++) {
700 String
= ArrayOfStrings
[Count
];
704 // This will clear the background of the line - we never know who might have been
705 // here before us. This differs from the next clear in that it used the non-reverse
706 // video for normal printing.
708 if (GetStringWidth (String
) / 2 > 1) {
709 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, POPUP_TEXT
| POPUP_BACKGROUND
);
712 // Passing in a space results in the assumption that this is where typing will occur
714 if (String
[0] == L
' ') {
715 ClearLines (Start
+ 1, End
- 1, Index
+ 1, Index
+ 1, POPUP_INVERSE_TEXT
| POPUP_INVERSE_BACKGROUND
);
718 // Passing in a NULL results in a blank space
720 if (String
[0] == CHAR_NULL
) {
721 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, POPUP_TEXT
| POPUP_BACKGROUND
);
725 ((DimensionsWidth
- GetStringWidth (String
) / 2) / 2) + gScreenDimensions
.LeftColumn
+ 1,
729 gST
->ConOut
->SetAttribute (gST
->ConOut
, POPUP_TEXT
| POPUP_BACKGROUND
);
730 PrintCharAt (Start
, Index
+ 1, Character
);
731 PrintCharAt (End
- 1, Index
+ 1, Character
);
734 Character
= (CHAR16
) BOXDRAW_UP_RIGHT
;
735 PrintCharAt (Start
, Bottom
- 1, Character
);
736 Character
= (CHAR16
) BOXDRAW_HORIZONTAL
;
737 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
738 PrintChar (Character
);
741 Character
= (CHAR16
) BOXDRAW_UP_LEFT
;
742 PrintChar (Character
);
747 IN UINTN RequestedWidth
,
748 IN UINTN NumberOfLines
,
749 IN CHAR16
*ArrayOfStrings
,
753 CreateSharedPopUp (RequestedWidth
, NumberOfLines
, &ArrayOfStrings
);
758 IN UINTN MessageType
,
764 STATIC BOOLEAN InputError
;
765 CHAR16
*NvUpdateMessage
;
766 CHAR16
*InputErrorMessage
;
768 NvUpdateMessage
= GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE
), gHiiHandle
);
769 InputErrorMessage
= GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE
), gHiiHandle
);
771 switch (MessageType
) {
774 gST
->ConOut
->SetAttribute (gST
->ConOut
, ERROR_TEXT
);
776 gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
,
777 gScreenDimensions
.BottomRow
- 1,
782 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
);
783 for (Index
= 0; Index
< (GetStringWidth (InputErrorMessage
) - 2) / 2; Index
++) {
784 PrintAt (gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ Index
, gScreenDimensions
.BottomRow
- 1, (CHAR16
*) L
" ");
791 case NV_UPDATE_REQUIRED
:
792 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
794 gST
->ConOut
->SetAttribute (gST
->ConOut
, INFO_TEXT
);
796 gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
,
797 gScreenDimensions
.BottomRow
- 1,
800 gResetRequired
= (BOOLEAN
) (gResetRequired
| ((Flags
& EFI_IFR_FLAG_RESET_REQUIRED
) == EFI_IFR_FLAG_RESET_REQUIRED
));
802 gNvUpdateRequired
= TRUE
;
804 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
);
805 for (Index
= 0; Index
< (GetStringWidth (NvUpdateMessage
) - 2) / 2; Index
++) {
807 (gScreenDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ Index
),
808 gScreenDimensions
.BottomRow
- 1,
813 gNvUpdateRequired
= FALSE
;
818 case REFRESH_STATUS_BAR
:
820 UpdateStatusBar (INPUT_ERROR
, Flags
, TRUE
);
823 if (gNvUpdateRequired
) {
824 UpdateStatusBar (NV_UPDATE_REQUIRED
, Flags
, TRUE
);
832 FreePool (InputErrorMessage
);
833 FreePool (NvUpdateMessage
);
839 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
840 IN CHAR16
*FormattedString
,
841 IN CHAR16
*OptionString
847 Used to remove the allocated data instances
855 EFI_FILE_FORM_TAGS
*FileForm
;
856 EFI_FILE_FORM_TAGS
*PreviousFileForm
;
857 EFI_FORM_TAGS
*FormTags
;
858 EFI_FORM_TAGS
*PreviousFormTags
;
859 EFI_IFR_BINARY
*IfrBinary
;
860 EFI_IFR_BINARY
*PreviousIfrBinary
;
861 EFI_INCONSISTENCY_DATA
*Inconsistent
;
862 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
863 EFI_VARIABLE_DEFINITION
*PreviousVariableDefinition
;
867 FileForm
= FileFormTagsHead
;
869 if (FormattedString
!= NULL
) {
870 FreePool (FormattedString
);
873 if (OptionString
!= NULL
) {
874 FreePool (OptionString
);
877 for (; FileForm
!= NULL
;) {
878 PreviousFileForm
= NULL
;
881 // Advance FileForm to the last entry
883 for (; FileForm
->NextFile
!= NULL
; FileForm
= FileForm
->NextFile
) {
884 PreviousFileForm
= FileForm
;
887 FormTags
= &FileForm
->FormTags
;
889 for (; FormTags
!= NULL
;) {
890 FormTags
= &FileForm
->FormTags
;
891 PreviousFormTags
= NULL
;
894 // Advance FormTags to the last entry
896 for (; FormTags
->Next
!= NULL
; FormTags
= FormTags
->Next
) {
897 PreviousFormTags
= FormTags
;
900 // Walk through each of the tags and free the IntList allocation
902 for (Index
= 0; FormTags
->Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
; Index
++) {
904 // It is more than likely that the very last page will contain an end formset
906 if (FormTags
->Tags
[Index
].Operand
== EFI_IFR_END_FORM_SET_OP
) {
910 if (FormTags
->Tags
[Index
].IntList
!= NULL
) {
911 FreePool (FormTags
->Tags
[Index
].IntList
);
915 if (PreviousFormTags
!= NULL
) {
916 FreePool (FormTags
->Tags
);
917 FormTags
= PreviousFormTags
;
918 FreePool (FormTags
->Next
);
919 FormTags
->Next
= NULL
;
921 FreePool (FormTags
->Tags
);
926 // Last FileForm entry's Inconsistent database
928 Inconsistent
= FileForm
->InconsistentTags
;
931 // Advance Inconsistent to the last entry
933 for (; Inconsistent
->Next
!= NULL
; Inconsistent
= Inconsistent
->Next
)
936 for (; Inconsistent
!= NULL
;) {
938 // Preserve the Previous pointer
940 Buffer
= (VOID
*) Inconsistent
->Previous
;
943 // Free the current entry
945 FreePool (Inconsistent
);
948 // Restore the Previous pointer
950 Inconsistent
= (EFI_INCONSISTENCY_DATA
*) Buffer
;
953 VariableDefinition
= FileForm
->VariableDefinitions
;
955 for (; VariableDefinition
!= NULL
;) {
956 VariableDefinition
= FileForm
->VariableDefinitions
;
957 PreviousVariableDefinition
= NULL
;
960 // Advance VariableDefinitions to the last entry
962 for (; VariableDefinition
->Next
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
963 PreviousVariableDefinition
= VariableDefinition
;
966 FreePool (VariableDefinition
->VariableName
);
968 if (VariableDefinition
->NvRamMap
!= NULL
) {
969 FreePool (VariableDefinition
->NvRamMap
);
972 if (VariableDefinition
->FakeNvRamMap
!= NULL
) {
973 FreePool (VariableDefinition
->FakeNvRamMap
);
976 if (PreviousVariableDefinition
!= NULL
) {
977 VariableDefinition
= PreviousVariableDefinition
;
978 FreePool (VariableDefinition
->Next
);
979 VariableDefinition
->Next
= NULL
;
981 FreePool (VariableDefinition
);
982 VariableDefinition
= NULL
;
986 if (PreviousFileForm
!= NULL
) {
987 FileForm
= PreviousFileForm
;
988 FreePool (FileForm
->NextFile
);
989 FileForm
->NextFile
= NULL
;
996 IfrBinary
= gBinaryDataHead
;
998 for (; IfrBinary
!= NULL
;) {
999 IfrBinary
= gBinaryDataHead
;
1000 PreviousIfrBinary
= NULL
;
1003 // Advance IfrBinary to the last entry
1005 for (; IfrBinary
->Next
!= NULL
; IfrBinary
= IfrBinary
->Next
) {
1006 PreviousIfrBinary
= IfrBinary
;
1009 FreePool (IfrBinary
->IfrPackage
);
1011 if (PreviousIfrBinary
!= NULL
) {
1012 IfrBinary
= PreviousIfrBinary
;
1013 FreePool (IfrBinary
->Next
);
1014 IfrBinary
->Next
= NULL
;
1016 FreePool (IfrBinary
);
1021 FreePool (gPreviousValue
);
1022 gPreviousValue
= NULL
;
1025 // Free Browser Strings
1027 FreePool (gPressEnter
);
1028 FreePool (gConfirmError
);
1029 FreePool (gConfirmPassword
);
1030 FreePool (gPromptForNewPassword
);
1031 FreePool (gPromptForPassword
);
1032 FreePool (gToggleCheckBox
);
1033 FreePool (gNumericInput
);
1034 FreePool (gMakeSelection
);
1035 FreePool (gMoveHighlight
);
1036 FreePool (gEscapeString
);
1037 FreePool (gEnterCommitString
);
1038 FreePool (gEnterString
);
1039 FreePool (gFunctionOneString
);
1040 FreePool (gFunctionTwoString
);
1041 FreePool (gFunctionNineString
);
1042 FreePool (gFunctionTenString
);
1048 SelectionsAreValid (
1049 IN UI_MENU_OPTION
*MenuOption
,
1050 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
1054 Routine Description:
1055 Initiate late consistency checks against the current page.
1066 EFI_FILE_FORM_TAGS
*FileFormTags
;
1068 CHAR16 NullCharacter
;
1073 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1075 StringPtr
= (CHAR16
*) L
"\0";
1076 NullCharacter
= CHAR_NULL
;
1078 FileFormTags
= FileFormTagsHead
;
1080 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
1081 FileFormTags
= FileFormTags
->NextFile
;
1084 for (Link
= Menu
.ForwardLink
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
1085 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1087 Tag
= MenuOption
->ThisTag
;
1089 ExtractRequestedNvMap (FileFormTags
, Tag
->VariableNumber
, &VariableDefinition
);
1090 NvRamMap
= (UINT16
*) &VariableDefinition
->NvRamMap
[Tag
->StorageStart
];
1093 // If the op-code has a late check, ensure consistency checks are now applied
1095 if (Tag
->Flags
& EFI_IFR_FLAG_LATE_CHECK
) {
1096 if (ValueIsNotValid (TRUE
, 0, Tag
, FileFormTags
, &PopUp
)) {
1097 if (PopUp
!= 0x0000) {
1098 StringPtr
= GetToken (PopUp
, MenuOption
->Handle
);
1100 CreatePopUp (GetStringWidth (StringPtr
) / 2, 3, &NullCharacter
, StringPtr
, &NullCharacter
);
1103 WaitForKeyStroke (&Key
);
1105 switch (Key
.UnicodeChar
) {
1107 case CHAR_CARRIAGE_RETURN
:
1109 // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
1111 CopyMem (NvRamMap
, &Tag
->OldValue
, Tag
->StorageWidth
);
1112 FreePool (StringPtr
);
1118 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1132 IN EFI_HII_HANDLE Handle
1136 Routine Description:
1137 Get the supported width for a particular op-code
1140 Tag - The Tag structure passed in.
1141 Handle - The handle in the HII database being used
1144 Returns the number of CHAR16 characters that is support.
1155 // See if the second text parameter is really NULL
1157 if ((Tag
->Operand
== EFI_IFR_TEXT_OP
) && (Tag
->TextTwo
!= 0)) {
1158 String
= GetToken (Tag
->TextTwo
, Handle
);
1159 Size
= StrLen (String
);
1163 if ((Tag
->Operand
== EFI_IFR_SUBTITLE_OP
) ||
1164 (Tag
->Operand
== EFI_IFR_REF_OP
) ||
1165 (Tag
->Operand
== EFI_IFR_PASSWORD_OP
) ||
1166 (Tag
->Operand
== EFI_IFR_STRING_OP
) ||
1167 (Tag
->Operand
== EFI_IFR_INVENTORY_OP
) ||
1169 // Allow a wide display if text op-code and no secondary text op-code
1171 ((Tag
->Operand
== EFI_IFR_TEXT_OP
) && (Size
== 0x0000))
1173 return (UINT16
) (gPromptBlockWidth
+ gOptionBlockWidth
);
1175 return (UINT16
) gPromptBlockWidth
;
1181 IN CHAR16
*InputString
,
1182 IN UINT16 LineWidth
,
1183 IN OUT UINTN
*Index
,
1184 OUT CHAR16
**OutputString
1188 Routine Description:
1189 Will copy LineWidth amount of a string in the OutputString buffer and return the
1190 number of CHAR16 characters that were copied into the OutputString buffer.
1193 InputString - String description for this option.
1194 LineWidth - Width of the desired string to extract in CHAR16 characters
1195 Index - Where in InputString to start the copy process
1196 OutputString - Buffer to copy the string into
1199 Returns the number of CHAR16 characters that were copied into the OutputString buffer.
1204 static BOOLEAN Finished
;
1216 *OutputString
= AllocateZeroPool (((UINTN
) (LineWidth
+ 1) * 2));
1219 // Ensure we have got a valid buffer
1221 if (*OutputString
!= NULL
) {
1224 //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.
1225 //To avoid displaying this empty line in screen, just skip the two CHARs here.
1227 if ((InputString
[*Index
] == NARROW_CHAR
) && (InputString
[*Index
+ 1] == CHAR_CARRIAGE_RETURN
)) {
1228 *Index
= *Index
+ 2;
1232 // Fast-forward the string and see if there is a carriage-return in the string
1234 for (; (InputString
[*Index
+ Count2
] != CHAR_CARRIAGE_RETURN
) && (Count2
!= LineWidth
); Count2
++)
1238 // Copy the desired LineWidth of data to the output buffer.
1239 // Also make sure that we don't copy more than the string.
1240 // Also make sure that if there are linefeeds, we account for them.
1242 if ((StrSize (&InputString
[*Index
]) <= ((UINTN
) (LineWidth
+ 1) * 2)) &&
1243 (StrSize (&InputString
[*Index
]) <= ((UINTN
) (Count2
+ 1) * 2))
1246 // Convert to CHAR16 value and show that we are done with this operation
1248 LineWidth
= (UINT16
) ((StrSize (&InputString
[*Index
]) - 2) / 2);
1249 if (LineWidth
!= 0) {
1253 if (Count2
== LineWidth
) {
1255 // Rewind the string from the maximum size until we see a space to break the line
1257 for (; (InputString
[*Index
+ LineWidth
] != CHAR_SPACE
) && (LineWidth
!= 0); LineWidth
--)
1259 if (LineWidth
== 0) {
1267 CopyMem (*OutputString
, &InputString
[*Index
], LineWidth
* 2);
1270 // If currently pointing to a space, increment the index to the first non-space character
1273 (InputString
[*Index
+ LineWidth
] == CHAR_SPACE
) || (InputString
[*Index
+ LineWidth
] == CHAR_CARRIAGE_RETURN
);
1277 *Index
= (UINT16
) (*Index
+ LineWidth
);
1286 UpdateOptionSkipLines (
1287 IN EFI_IFR_DATA_ARRAY
*PageData
,
1288 IN UI_MENU_OPTION
*MenuOption
,
1289 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1290 IN CHAR16
**OptionalString
,
1298 CHAR16
*OutputString
;
1299 CHAR16
*OptionString
;
1302 OptionString
= *OptionalString
;
1303 OutputString
= NULL
;
1305 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1307 if (OptionString
!= NULL
) {
1308 Width
= (UINT16
) gOptionBlockWidth
;
1312 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1314 // If there is more string to process print on the next row and increment the Skip value
1316 if (StrLen (&OptionString
[Index
])) {
1317 if (SkipValue
== 0) {
1320 // Since the Number of lines for this menu entry may or may not be reflected accurately
1321 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1322 // some testing to ensure we are keeping this in-sync.
1324 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1326 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1332 FreePool (OutputString
);
1333 if (SkipValue
!= 0) {
1341 *OptionalString
= OptionString
;
1344 // Search table for UiDisplayMenu()
1346 SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation
[] = {
1348 { SCAN_DOWN
, UiDown
},
1349 { SCAN_PAGE_UP
, UiPageUp
},
1350 { SCAN_PAGE_DOWN
, UiPageDown
},
1351 { SCAN_ESC
, UiReset
},
1352 { SCAN_F2
, UiPrevious
},
1353 { SCAN_LEFT
, UiLeft
},
1354 { SCAN_RIGHT
, UiRight
},
1355 { SCAN_F9
, UiDefault
},
1356 { SCAN_F10
, UiSave
}
1359 SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag
[] = {
1360 { UiNoOperation
, CfUiNoOperation
},
1361 { UiDefault
, CfUiDefault
},
1362 { UiSelect
, CfUiSelect
},
1364 { UiDown
, CfUiDown
},
1365 { UiLeft
, CfUiLeft
},
1366 { UiRight
, CfUiRight
},
1367 { UiReset
, CfUiReset
},
1368 { UiSave
, CfUiSave
},
1369 { UiPrevious
, CfUiPrevious
},
1370 { UiPageUp
, CfUiPageUp
},
1371 { UiPageDown
, CfUiPageDown
}
1377 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1378 OUT EFI_IFR_DATA_ARRAY
*PageData
1382 Routine Description:
1383 Display menu and wait for user to select one menu option, then return it.
1384 If AutoBoot is enabled, then if user doesn't select any option,
1385 after period of time, it will automatically return the first menu option.
1388 SubMenu - Indicate is sub menu.
1389 FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure.
1390 PageData - A pointer to the EFI_IFR_DATA_ARRAY.
1393 Return the pointer of the menu which selected,
1394 otherwise return NULL.
1409 UINTN DataAndTimeLineNumberPad
;
1411 INT16 OriginalTimeOut
;
1415 CHAR16
*OptionString
;
1416 CHAR16
*OutputString
;
1417 CHAR16
*FormattedString
;
1424 UI_MENU_LIST
*UiMenuList
;
1428 LIST_ENTRY
*TopOfScreen
;
1429 LIST_ENTRY
*SavedListEntry
;
1430 UI_MENU_OPTION
*Selection
;
1431 UI_MENU_OPTION
*MenuOption
;
1432 UI_MENU_OPTION
*NextMenuOption
;
1433 UI_MENU_OPTION
*SavedMenuOption
;
1434 UI_MENU_OPTION
*PreviousMenuOption
;
1435 EFI_IFR_BINARY
*IfrBinary
;
1436 UI_CONTROL_FLAG ControlFlag
;
1437 EFI_SCREEN_DESCRIPTOR LocalScreen
;
1438 EFI_FILE_FORM_TAGS
*FileFormTags
;
1439 MENU_REFRESH_ENTRY
*MenuRefreshEntry
;
1440 MENU_REFRESH_ENTRY
*OldMenuRefreshEntry
;
1441 UI_SCREEN_OPERATION ScreenOperation
;
1442 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1443 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
1444 EFI_HII_VARIABLE_PACK_LIST
*NvMapListHead
;
1445 EFI_HII_VARIABLE_PACK_LIST
*NvMapListNode
;
1449 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
1451 VariableDefinition
= NULL
;
1452 Status
= EFI_SUCCESS
;
1453 FormattedString
= NULL
;
1454 OptionString
= NULL
;
1455 ScreenOperation
= UiNoOperation
;
1457 FormCallback
= NULL
;
1458 FileFormTags
= NULL
;
1459 OutputString
= NULL
;
1464 MenuRefreshEntry
= gMenuRefreshHead
;
1465 OldMenuRefreshEntry
= gMenuRefreshHead
;
1466 NextMenuOption
= NULL
;
1467 PreviousMenuOption
= NULL
;
1468 SavedMenuOption
= NULL
;
1473 ZeroMem (&Key
, sizeof (EFI_INPUT_KEY
));
1475 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
1476 TopRow
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1477 Row
= LocalScreen
.TopRow
+ FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1479 TopRow
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1480 Row
= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
+ SCROLL_ARROW_HEIGHT
;
1484 Col
= LocalScreen
.LeftColumn
;
1486 Col
= LocalScreen
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
;
1489 BottomRow
= LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
- SCROLL_ARROW_HEIGHT
- 1;
1491 TopOfScreen
= Menu
.ForwardLink
;
1496 // Get user's selection
1499 NewPos
= Menu
.ForwardLink
;
1500 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
1502 UpdateStatusBar (REFRESH_STATUS_BAR
, (UINT8
) 0, TRUE
);
1504 ControlFlag
= CfInitialization
;
1507 switch (ControlFlag
) {
1508 case CfInitialization
:
1509 ControlFlag
= CfCheckSelection
;
1510 if (gExitRequired
) {
1511 ScreenOperation
= UiReset
;
1512 ControlFlag
= CfScreenOperation
;
1513 } else if (gSaveRequired
) {
1514 ScreenOperation
= UiSave
;
1515 ControlFlag
= CfScreenOperation
;
1516 } else if (IsListEmpty (&Menu
)) {
1517 ControlFlag
= CfReadKey
;
1521 case CfCheckSelection
:
1522 if (Selection
!= NULL
) {
1523 ControlFlag
= CfExit
;
1525 ControlFlag
= CfRepaint
;
1528 FileFormTags
= FileFormTagsHead
;
1532 ControlFlag
= CfRefreshHighLight
;
1538 SavedMenuOption
= MenuOption
;
1547 LocalScreen
.LeftColumn
,
1548 LocalScreen
.RightColumn
,
1549 TopRow
- SCROLL_ARROW_HEIGHT
,
1550 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1551 FIELD_TEXT
| FIELD_BACKGROUND
1554 while (gMenuRefreshHead
!= NULL
) {
1555 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
1557 FreePool (gMenuRefreshHead
);
1559 gMenuRefreshHead
= OldMenuRefreshEntry
;
1562 for (Link
= TopOfScreen
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
1563 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1564 MenuOption
->Row
= Row
;
1566 MenuOption
->Col
= Col
;
1567 MenuOption
->OptCol
= gPromptBlockWidth
+ 1 + LocalScreen
.LeftColumn
;
1570 if (MenuOption
->ThisTag
->GrayOut
) {
1571 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1573 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1574 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1578 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1582 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1583 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1584 PrintStringAt (Col
, Row
, OutputString
);
1587 // If there is more string to process print on the next row and increment the Skip value
1589 if (StrLen (&MenuOption
->Description
[Index
])) {
1595 FreePool (OutputString
);
1605 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1606 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1608 if (OptionString
!= NULL
) {
1609 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1610 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1613 // If leading spaces on OptionString - remove the spaces
1615 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++) {
1616 MenuOption
->OptCol
++;
1619 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1620 OptionString
[Count
] = OptionString
[Index
];
1624 OptionString
[Count
] = CHAR_NULL
;
1628 // If this is a date or time op-code and is used to reflect an RTC, register the op-code
1630 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1631 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
) &&
1632 (MenuOption
->ThisTag
->StorageStart
>= FileFormTags
->FormTags
.Tags
[0].NvDataSize
)) {
1634 if (gMenuRefreshHead
== NULL
) {
1635 MenuRefreshEntry
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1636 ASSERT (MenuRefreshEntry
!= NULL
);
1637 MenuRefreshEntry
->MenuOption
= MenuOption
;
1638 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1639 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1640 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1641 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1642 gMenuRefreshHead
= MenuRefreshEntry
;
1645 // Advance to the last entry
1647 for (MenuRefreshEntry
= gMenuRefreshHead
;
1648 MenuRefreshEntry
->Next
!= NULL
;
1649 MenuRefreshEntry
= MenuRefreshEntry
->Next
1652 MenuRefreshEntry
->Next
= AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY
));
1653 ASSERT (MenuRefreshEntry
->Next
!= NULL
);
1654 MenuRefreshEntry
= MenuRefreshEntry
->Next
;
1655 MenuRefreshEntry
->MenuOption
= MenuOption
;
1656 MenuRefreshEntry
->FileFormTagsHead
= FileFormTagsHead
;
1657 MenuRefreshEntry
->CurrentColumn
= MenuOption
->OptCol
;
1658 MenuRefreshEntry
->CurrentRow
= MenuOption
->Row
;
1659 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1663 Width
= (UINT16
) gOptionBlockWidth
;
1667 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1668 if ((Temp2
== 0) && (Row
<= BottomRow
)) {
1669 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1672 // If there is more string to process print on the next row and increment the Skip value
1674 if (StrLen (&OptionString
[Index
])) {
1678 // Since the Number of lines for this menu entry may or may not be reflected accurately
1679 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1680 // some testing to ensure we are keeping this in-sync.
1682 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1684 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1690 FreePool (OutputString
);
1700 // If this is a text op with secondary text information
1702 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
) && (MenuOption
->ThisTag
->TextTwo
!= 0)) {
1703 StringPtr
= GetToken (MenuOption
->ThisTag
->TextTwo
, MenuOption
->Handle
);
1705 Width
= (UINT16
) gOptionBlockWidth
;
1709 for (Index
= 0; GetLineByWidth (StringPtr
, Width
, &Index
, &OutputString
) != 0x0000;) {
1710 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1711 PrintStringAt (MenuOption
->OptCol
, Row
, OutputString
);
1714 // If there is more string to process print on the next row and increment the Skip value
1716 if (StrLen (&StringPtr
[Index
])) {
1720 // Since the Number of lines for this menu entry may or may not be reflected accurately
1721 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1722 // some testing to ensure we are keeping this in-sync.
1724 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1726 if ((Row
- OriginalRow
) >= MenuOption
->Skip
) {
1732 FreePool (OutputString
);
1739 FreePool (StringPtr
);
1743 // For now, assume left-justified 72 width max setup entries
1745 PrintStringAt (Col
, Row
, MenuOption
->Description
);
1748 // Tracker 6210 - need to handle the bottom of the display
1750 if (MenuOption
->Skip
> 1) {
1751 Row
+= MenuOption
->Skip
- SkipValue
;
1754 Row
+= MenuOption
->Skip
;
1757 if (Row
> BottomRow
) {
1758 if (!ValueIsScroll (FALSE
, Link
)) {
1762 Row
= BottomRow
+ 1;
1767 if (!ValueIsScroll (TRUE
, TopOfScreen
)) {
1772 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1774 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1775 TopRow
- SCROLL_ARROW_HEIGHT
,
1779 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1783 gST
->ConOut
->SetAttribute (gST
->ConOut
, ARROW_TEXT
| ARROW_BACKGROUND
);
1785 LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
1786 BottomRow
+ SCROLL_ARROW_HEIGHT
,
1790 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1793 if (SavedMenuOption
!= NULL
) {
1794 MenuOption
= SavedMenuOption
;
1799 case CfRefreshHighLight
:
1800 ControlFlag
= CfUpdateHelpString
;
1802 // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
1803 // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
1805 SavedValue
= Repaint
;
1808 if (NewPos
!= NULL
) {
1809 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1811 if (gLastOpr
&& (gEntryNumber
!= -1)) {
1812 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1813 if (gEntryNumber
!= MenuOption
->EntryNumber
) {
1814 ScreenOperation
= UiDown
;
1815 ControlFlag
= CfScreenOperation
;
1822 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1823 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1824 if (OptionString
!= NULL
) {
1825 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1826 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1829 // If leading spaces on OptionString - remove the spaces
1831 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1834 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1835 OptionString
[Count
] = OptionString
[Index
];
1839 OptionString
[Count
] = CHAR_NULL
;
1842 Width
= (UINT16
) gOptionBlockWidth
;
1844 OriginalRow
= MenuOption
->Row
;
1846 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1847 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1848 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1851 // If there is more string to process print on the next row and increment the Skip value
1853 if (StrLen (&OptionString
[Index
])) {
1857 FreePool (OutputString
);
1860 MenuOption
->Row
= OriginalRow
;
1863 if (MenuOption
->ThisTag
->GrayOut
) {
1864 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_GRAYED
| FIELD_BACKGROUND
);
1866 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
) {
1867 gST
->ConOut
->SetAttribute (gST
->ConOut
, SUBTITLE_TEXT
| FIELD_BACKGROUND
);
1871 OriginalRow
= MenuOption
->Row
;
1872 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1874 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1875 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1876 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1879 // If there is more string to process print on the next row and increment the Skip value
1881 if (StrLen (&MenuOption
->Description
[Index
])) {
1885 FreePool (OutputString
);
1888 MenuOption
->Row
= OriginalRow
;
1889 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1893 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
1894 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
1897 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
1899 if ((gPriorMenuEntry
!= 0) && (MenuOption
->EntryNumber
!= gPriorMenuEntry
) && (NewPos
->ForwardLink
!= &Menu
)) {
1900 ScreenOperation
= UiDown
;
1901 ControlFlag
= CfScreenOperation
;
1904 gPriorMenuEntry
= 0;
1907 // This is only possible if we entered this page and the first menu option is
1908 // a "non-menu" item. In that case, force it UiDown
1910 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
1912 // If we previously hit an UP command and we are still sitting on a text operation
1913 // we must continue going up
1915 if (ScreenOperation
== UiUp
) {
1916 ControlFlag
= CfScreenOperation
;
1919 ScreenOperation
= UiDown
;
1920 ControlFlag
= CfScreenOperation
;
1925 // Set reverse attribute
1927 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
);
1928 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
1931 // Assuming that we have a refresh linked-list created, lets annotate the
1932 // appropriate entry that we are highlighting with its new attribute. Just prior to this
1933 // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
1935 if (gMenuRefreshHead
!= NULL
) {
1936 for (MenuRefreshEntry
= gMenuRefreshHead
; MenuRefreshEntry
!= NULL
; MenuRefreshEntry
= MenuRefreshEntry
->Next
) {
1937 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT
| FIELD_BACKGROUND
;
1938 if (MenuRefreshEntry
->MenuOption
== MenuOption
) {
1939 MenuRefreshEntry
->CurrentAttribute
= FIELD_TEXT_HIGHLIGHT
| FIELD_BACKGROUND_HIGHLIGHT
;
1945 ProcessOptions (MenuOption
, FALSE
, FileFormTagsHead
, PageData
, &OptionString
);
1946 if (OptionString
!= NULL
) {
1947 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
||
1948 MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
1951 // If leading spaces on OptionString - remove the spaces
1953 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++)
1956 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
1957 OptionString
[Count
] = OptionString
[Index
];
1961 OptionString
[Count
] = CHAR_NULL
;
1963 Width
= (UINT16
) gOptionBlockWidth
;
1965 OriginalRow
= MenuOption
->Row
;
1967 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &Index
, &OutputString
) != 0x0000;) {
1968 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1969 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
1972 // If there is more string to process print on the next row and increment the Skip value
1974 if (StrLen (&OptionString
[Index
])) {
1978 FreePool (OutputString
);
1981 MenuOption
->Row
= OriginalRow
;
1984 OriginalRow
= MenuOption
->Row
;
1986 Width
= GetWidth (MenuOption
->ThisTag
, MenuOption
->Handle
);
1988 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &Index
, &OutputString
) != 0x0000;) {
1989 if (MenuOption
->Row
>= TopRow
&& MenuOption
->Row
<= BottomRow
) {
1990 PrintStringAt (Col
, MenuOption
->Row
, OutputString
);
1993 // If there is more string to process print on the next row and increment the Skip value
1995 if (StrLen (&MenuOption
->Description
[Index
])) {
1999 FreePool (OutputString
);
2002 MenuOption
->Row
= OriginalRow
;
2007 if (((NewPos
->ForwardLink
!= &Menu
) && (ScreenOperation
== UiDown
)) ||
2008 ((NewPos
->BackLink
!= &Menu
) && (ScreenOperation
== UiUp
)) ||
2009 (ScreenOperation
== UiNoOperation
)
2011 UpdateKeyHelp (MenuOption
, FALSE
);
2014 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2017 // Clear reverse attribute
2019 gST
->ConOut
->SetAttribute (gST
->ConOut
, FIELD_TEXT
| FIELD_BACKGROUND
);
2022 // Repaint flag will be used when process CfUpdateHelpString, so restore its value
2023 // if we didn't break halfway when process CfRefreshHighLight.
2025 Repaint
= SavedValue
;
2028 case CfUpdateHelpString
:
2029 ControlFlag
= CfPrepareToReadKey
;
2032 (Repaint
|| NewLine
||
2033 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2034 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) &&
2035 !(gClassOfVfr
== EFI_GENERAL_APPLICATION_SUBCLASS
)) {
2037 // Don't print anything if it is a NULL help token
2039 if (MenuOption
->ThisTag
->Help
== 0x00000000) {
2040 StringPtr
= (CHAR16
*) L
"\0";
2042 StringPtr
= GetToken (MenuOption
->ThisTag
->Help
, MenuOption
->Handle
);
2045 ProcessHelpString (StringPtr
, &FormattedString
, BottomRow
- TopRow
);
2047 gST
->ConOut
->SetAttribute (gST
->ConOut
, HELP_TEXT
| FIELD_BACKGROUND
);
2049 for (Index
= 0; Index
< BottomRow
- TopRow
; Index
++) {
2051 // Pad String with spaces to simulate a clearing of the previous line
2053 for (; GetStringWidth (&FormattedString
[Index
* gHelpBlockWidth
* 2]) / 2 < gHelpBlockWidth
;) {
2054 StrCat (&FormattedString
[Index
* gHelpBlockWidth
* 2], (CHAR16
*) L
" ");
2058 LocalScreen
.RightColumn
- gHelpBlockWidth
,
2060 &FormattedString
[Index
* gHelpBlockWidth
* 2]
2065 // Reset this flag every time we finish using it.
2071 case CfPrepareToReadKey
:
2072 ControlFlag
= CfReadKey
;
2074 for (Index
= 0; Index
< MenuOption
->IfrNumber
; Index
++) {
2075 FileFormTags
= FileFormTags
->NextFile
;
2078 ScreenOperation
= UiNoOperation
;
2080 Status
= gBS
->HandleProtocol (
2081 (VOID
*) (UINTN
) FileFormTags
->FormTags
.Tags
[0].CallbackHandle
,
2082 &gEfiFormCallbackProtocolGuid
,
2083 (VOID
**) &FormCallback
2089 ControlFlag
= CfScreenOperation
;
2091 OriginalTimeOut
= FrontPageTimeOutValue
;
2093 if (FrontPageTimeOutValue
>= 0 && (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) && FrontPageTimeOutValue
!= (INT16
) -1) {
2095 // Remember that if set to 0, must immediately boot an option
2097 if (FrontPageTimeOutValue
== 0) {
2098 FrontPageTimeOutValue
= 0xFFFF;
2099 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2100 if (EFI_ERROR (Status
)) {
2101 Status
= EFI_TIMEOUT
;
2106 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, ONE_SECOND
);
2107 if (Status
== EFI_TIMEOUT
) {
2108 EFI_IFR_DATA_ENTRY
*DataEntry
;
2110 DataEntry
= (EFI_IFR_DATA_ENTRY
*) (PageData
+ 1);
2112 PageData
->EntryCount
= 1;
2113 Count
= (UINT32
) ((OriginalTimeOut
- FrontPageTimeOutValue
) * 100 / OriginalTimeOut
);
2114 CopyMem (&DataEntry
->Data
, &Count
, sizeof (UINT32
));
2116 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2117 FormCallback
->Callback (
2120 (EFI_IFR_DATA_ARRAY
*) PageData
,
2125 // Count down 1 second
2127 FrontPageTimeOutValue
--;
2130 ASSERT (!EFI_ERROR (Status
));
2131 PageData
->EntryCount
= 0;
2132 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
2133 FormCallback
->Callback (
2136 (EFI_IFR_DATA_ARRAY
*) PageData
,
2141 FrontPageTimeOutValue
= 0xFFFF;
2145 // Wait for user's selection, no auto boot
2147 Status
= UiWaitForSingleEvent (gST
->ConIn
->WaitForKey
, 0);
2149 } while (Status
== EFI_TIMEOUT
);
2153 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2154 DisableQuietBoot ();
2157 if (Status
== EFI_TIMEOUT
) {
2158 Key
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
2160 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2162 // if we encounter error, continue to read another key in.
2164 if (EFI_ERROR (Status
)) {
2165 ControlFlag
= CfReadKey
;
2170 switch (Key
.UnicodeChar
) {
2171 case CHAR_CARRIAGE_RETURN
:
2172 Selection
= MenuOption
;
2173 ScreenOperation
= UiSelect
;
2178 // We will push the adjustment of these numeric values directly to the input handler
2182 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2184 if (Key
.UnicodeChar
== '+') {
2185 gDirection
= SCAN_RIGHT
;
2187 gDirection
= SCAN_LEFT
;
2190 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, NULL
, &OptionString
);
2195 ScreenOperation
= UiUp
;
2200 ScreenOperation
= UiDown
;
2204 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
2206 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_CHECKBOX_OP
&& !(MenuOption
->ThisTag
->GrayOut
)) {
2207 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
2208 gST
->ConOut
->OutputString (gST
->ConOut
, MenuOption
->Description
);
2209 Selection
= MenuOption
;
2210 ScreenOperation
= UiSelect
;
2217 if (((Key
.ScanCode
== SCAN_F1
) && ((gFunctionKeySetting
& FUNCTION_ONE
) != FUNCTION_ONE
)) ||
2218 ((Key
.ScanCode
== SCAN_F2
) && ((gFunctionKeySetting
& FUNCTION_TWO
) != FUNCTION_TWO
)) ||
2219 ((Key
.ScanCode
== SCAN_F9
) && ((gFunctionKeySetting
& FUNCTION_NINE
) != FUNCTION_NINE
)) ||
2220 ((Key
.ScanCode
== SCAN_F10
) && ((gFunctionKeySetting
& FUNCTION_TEN
) != FUNCTION_TEN
))
2223 // If the function key has been disabled, just ignore the key.
2226 for (Index
= 0; Index
< sizeof (gScanCodeToOperation
) / sizeof (gScanCodeToOperation
[0]); Index
++) {
2227 if (Key
.ScanCode
== gScanCodeToOperation
[Index
].ScanCode
) {
2228 if ((Key
.ScanCode
== SCAN_F9
) || (Key
.ScanCode
== SCAN_F10
)) {
2230 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2233 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2242 case CfScreenOperation
:
2243 IfrBinary
= gBinaryDataHead
;
2246 // Advance to the Ifr we are using
2248 for (Index
= 0; Index
< gActiveIfr
; Index
++) {
2249 IfrBinary
= IfrBinary
->Next
;
2252 if (ScreenOperation
!= UiPrevious
&& ScreenOperation
!= UiReset
) {
2254 // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
2255 // ignore the selection and go back to reading keys.
2257 if (IsListEmpty (&Menu
)) {
2258 ControlFlag
= CfReadKey
;
2262 // if there is nothing logical to place a cursor on, just move on to wait for a key.
2264 for (Link
= Menu
.ForwardLink
; Link
!= &Menu
; Link
= Link
->ForwardLink
) {
2265 NextMenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2266 if (!(NextMenuOption
->ThisTag
->GrayOut
) && (NextMenuOption
->ThisTag
->Operand
!= EFI_IFR_SUBTITLE_OP
)) {
2271 if (Link
== &Menu
) {
2272 ControlFlag
= CfPrepareToReadKey
;
2278 Index
< sizeof (gScreenOperationToControlFlag
) / sizeof (gScreenOperationToControlFlag
[0]);
2281 if (ScreenOperation
== gScreenOperationToControlFlag
[Index
].ScreenOperation
) {
2282 ControlFlag
= gScreenOperationToControlFlag
[Index
].ControlFlag
;
2289 ControlFlag
= CfCheckSelection
;
2291 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2293 if (MenuOption
!= NULL
) {
2294 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2301 if (IsListEmpty (&gMenuList
)) {
2303 if (IsListEmpty (&Menu
)) {
2304 ControlFlag
= CfReadKey
;
2311 while (gMenuRefreshHead
!= NULL
) {
2312 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
2314 FreePool (gMenuRefreshHead
);
2316 gMenuRefreshHead
= OldMenuRefreshEntry
;
2319 // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag
2322 UiRemoveMenuListEntry (MenuOption
, &Selection
);
2323 Selection
->Previous
= TRUE
;
2328 gActiveIfr
= Selection
->IfrNumber
;
2332 ControlFlag
= CfCheckSelection
;
2334 ExtractRequestedNvMap (FileFormTags
, MenuOption
->ThisTag
->VariableNumber
, &VariableDefinition
);
2337 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_TEXT_OP
&&
2338 !(MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
)) ||
2339 (MenuOption
->ThisTag
->GrayOut
) ||
2340 (MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) ||
2341 (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2347 UpdateKeyHelp (MenuOption
, TRUE
);
2348 Status
= ProcessOptions (MenuOption
, TRUE
, FileFormTagsHead
, PageData
, &OptionString
);
2350 if (EFI_ERROR (Status
)) {
2356 if (OptionString
!= NULL
) {
2357 PrintStringAt (LocalScreen
.LeftColumn
+ gPromptBlockWidth
+ 1, MenuOption
->Row
, OptionString
);
2360 if (MenuOption
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
2361 Selection
= MenuOption
;
2364 if (Selection
== NULL
) {
2368 Location
= (UINT8
*) &PageData
->EntryCount
;
2371 // If not a goto, dump single piece of data, otherwise dump everything
2373 if (Selection
->ThisTag
->Operand
== EFI_IFR_REF_OP
) {
2375 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2377 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2383 UiAddMenuListEntry (Selection
);
2384 gPriorMenuEntry
= 0;
2387 // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious
2389 UiMenuList
= CR (gMenuList
.ForwardLink
, UI_MENU_LIST
, MenuLink
, UI_MENU_LIST_SIGNATURE
);
2390 UiMenuList
->FormerEntryNumber
= MenuOption
->EntryNumber
;
2395 // Rewind to the beginning of the menu
2397 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2401 // Get Total Count of Menu entries
2403 for (Count
= 1; NewPos
->ForwardLink
!= &Menu
; NewPos
= NewPos
->ForwardLink
) {
2407 // Rewind to the beginning of the menu
2409 for (; NewPos
->BackLink
!= &Menu
; NewPos
= NewPos
->BackLink
)
2413 // Copy the number of entries being described to the PageData location
2415 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2417 for (Index
= 4; NewPos
->ForwardLink
!= &Menu
; Index
= Index
+ MenuOption
->ThisTag
->StorageWidth
+ 2) {
2419 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2420 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2421 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2423 &Location
[Index
+ 4],
2424 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2425 MenuOption
->ThisTag
->StorageWidth
2427 NewPos
= NewPos
->ForwardLink
;
2431 gPriorMenuEntry
= MenuOption
->EntryNumber
;
2436 // Copy the number of entries being described to the PageData location
2438 CopyMem (&Location
[0], &Count
, sizeof (UINT32
));
2441 // Start at PageData[4] since the EntryCount is a UINT32
2446 // Copy data to destination
2448 Location
[Index
] = MenuOption
->ThisTag
->Operand
;
2449 Location
[Index
+ 1] = (UINT8
) (MenuOption
->ThisTag
->StorageWidth
+ 4);
2451 &Location
[Index
+ 4],
2452 &VariableDefinition
->NvRamMap
[MenuOption
->ThisTag
->StorageStart
],
2453 MenuOption
->ThisTag
->StorageWidth
2460 ControlFlag
= CfCheckSelection
;
2462 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
2466 // If NV flag is up, prompt user
2468 if (gNvUpdateRequired
) {
2469 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2471 YesResponse
= gYesResponse
[0];
2472 NoResponse
= gNoResponse
[0];
2475 CreateDialog (3, TRUE
, 0, NULL
, &Key
, gEmptyString
, gAreYouSure
, gEmptyString
);
2478 (Key
.ScanCode
!= SCAN_ESC
) &&
2479 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (NoResponse
| UPPER_LOWER_CASE_OFFSET
)) &&
2480 ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) != (YesResponse
| UPPER_LOWER_CASE_OFFSET
))
2484 // If the user hits the YesResponse key
2486 if ((Key
.UnicodeChar
| UPPER_LOWER_CASE_OFFSET
) == (YesResponse
| UPPER_LOWER_CASE_OFFSET
)) {
2494 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2496 if (MenuOption
!= NULL
) {
2497 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2505 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
2506 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
2510 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2514 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2515 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2517 if (IfrBinary
->UnRegisterOnExit
) {
2518 Hii
->RemovePack (Hii
, MenuOption
->Handle
);
2524 // Clean up the allocated data buffers
2526 FreeData (FileFormTagsHead
, FormattedString
, OptionString
);
2528 gST
->ConOut
->ClearScreen (gST
->ConOut
);
2532 ControlFlag
= CfCheckSelection
;
2533 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
2534 if (MenuOption
->Skip
== 1) {
2536 // In the tail of the Date/Time op-code set, go left.
2538 NewPos
= NewPos
->BackLink
;
2541 // In the middle of the Data/Time op-code set, go left.
2543 NextMenuOption
= CR (NewPos
->ForwardLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2544 if (NextMenuOption
->Skip
== 1) {
2545 NewPos
= NewPos
->BackLink
;
2552 ControlFlag
= CfCheckSelection
;
2553 if ((MenuOption
->Skip
== 0) &&
2554 ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
))
2557 // We are in the head or middle of the Date/Time op-code set, advance right.
2559 NewPos
= NewPos
->ForwardLink
;
2564 ControlFlag
= CfCheckSelection
;
2566 if (NewPos
->BackLink
!= &Menu
) {
2569 // Adjust Date/Time position before we advance forward.
2571 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2574 // Caution that we have already rewind to the top, don't go backward in this situation.
2576 if (NewPos
->BackLink
!= &Menu
) {
2577 NewPos
= NewPos
->BackLink
;
2580 PreviousMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2583 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
2584 // to be one that back to the previous set of op-codes, we need to advance to the sencond
2585 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2586 // checking can be done.
2588 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (TRUE
, &NewPos
);
2592 // If the previous MenuOption contains a display-only op-code, skip to the next one
2594 if (PreviousMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| PreviousMenuOption
->ThisTag
->GrayOut
) {
2596 // This is ok as long as not at the end of the list
2598 if (NewPos
->BackLink
== &Menu
) {
2600 // If we are at the start of the list, then this list must start with a display only
2601 // piece of data, so do not allow the backward motion
2603 ScreenOperation
= UiDown
;
2605 if (PreviousMenuOption
->Row
<= TopRow
) {
2606 if (TopOfScreen
->BackLink
!= &Menu
) {
2607 TopOfScreen
= TopOfScreen
->BackLink
;
2612 UpdateStatusBar (INPUT_ERROR
, PreviousMenuOption
->ThisTag
->Flags
, FALSE
);
2618 // Check the previous menu entry to see if it was a zero-length advance. If it was,
2619 // don't worry about a redraw.
2621 if ((MenuOption
->Row
- PreviousMenuOption
->Skip
- DataAndTimeLineNumberPad
< TopRow
) ||
2622 (PreviousMenuOption
->Skip
> MenuOption
->Row
)
2625 if (TopOfScreen
->BackLink
== &Menu
) {
2632 // Is the current top of screen a zero-advance op-code?
2633 // If so, keep moving forward till we hit a >0 advance op-code
2635 SavedMenuOption
= CR (TopOfScreen
->BackLink
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2636 TopOfScreen
= TopOfScreen
->BackLink
;
2637 } while (SavedMenuOption
->Skip
== 0);
2639 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2641 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2644 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2647 SavedMenuOption
= MenuOption
;
2648 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2649 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2651 // If we are at the end of the list and sitting on a text op, we need to more forward
2653 ScreenOperation
= UiDown
;
2654 ControlFlag
= CfScreenOperation
;
2658 MenuOption
= SavedMenuOption
;
2664 ControlFlag
= CfCheckSelection
;
2666 SavedListEntry
= NewPos
;
2668 for (Index
= BottomRow
; Index
>= TopRow
+ 1; Index
-= MenuOption
->Skip
) {
2669 if (Link
->BackLink
== &Menu
) {
2671 Link
= SavedListEntry
;
2672 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2678 Link
= Link
->BackLink
;
2679 MenuOption
= CR (Link
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2681 SavedListEntry
= Link
;
2687 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2688 // Don't do this when we are already in the first page.
2691 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2692 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2693 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2698 ControlFlag
= CfCheckSelection
;
2700 SavedListEntry
= NewPos
;
2702 NewPos
= TopOfScreen
;
2703 for (Index
= TopRow
; Index
<= BottomRow
- 1; Index
+= MenuOption
->Skip
) {
2704 if (NewPos
->ForwardLink
== &Menu
) {
2705 NewPos
= SavedListEntry
;
2706 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2715 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2716 NewPos
= NewPos
->ForwardLink
;
2723 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2724 // Don't do this when we are already in the last page.
2727 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2728 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2729 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2734 ControlFlag
= CfCheckSelection
;
2736 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
2737 // to be one that progresses to the next set of op-codes, we need to advance to the last
2738 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
2739 // checking can be done. The only other logic we need to introduce is that if a Date/Time
2740 // op-code is the last entry in the menu, we need to rewind back to the first op-code of
2741 // the Date/Time op-code.
2743 DataAndTimeLineNumberPad
= AdjustDateAndTimePosition (FALSE
, &NewPos
);
2745 if (NewPos
->ForwardLink
!= &Menu
) {
2747 NewPos
= NewPos
->ForwardLink
;
2748 NextMenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2752 // If the next MenuOption contains a display-only op-code, skip to the next one
2753 // Also if the next MenuOption is date or time,
2755 if (NextMenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| NextMenuOption
->ThisTag
->GrayOut
) {
2757 // This is ok as long as not at the end of the list
2759 if (NewPos
== &Menu
) {
2761 // If we are at the end of the list, then this list must end with a display only
2762 // piece of data, so do not allow the forward motion
2764 UpdateStatusBar (INPUT_ERROR
, NextMenuOption
->ThisTag
->Flags
, FALSE
);
2765 NewPos
= NewPos
->BackLink
;
2766 ScreenOperation
= UiUp
;
2772 // An option might be multi-line, so we need to reflect that data in the overall skip value
2774 UpdateOptionSkipLines (PageData
, NextMenuOption
, FileFormTagsHead
, &OptionString
, SkipValue
);
2776 if (NextMenuOption
->Skip
> 1) {
2777 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ NextMenuOption
->Skip
- 1;
2779 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ DataAndTimeLineNumberPad
;
2782 // If we are going to scroll
2784 if (Temp
> BottomRow
) {
2787 // Is the current top of screen a zero-advance op-code?
2788 // If so, keep moving forward till we hit a >0 advance op-code
2790 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2793 // If bottom op-code is more than one line or top op-code is more than one line
2795 if ((NextMenuOption
->Skip
> 1) || (MenuOption
->Skip
> 1)) {
2797 // Is the bottom op-code greater than or equal in size to the top op-code?
2799 if ((Temp
- BottomRow
) >= (SavedMenuOption
->Skip
- OldSkipValue
)) {
2801 // Skip the top op-code
2803 TopOfScreen
= TopOfScreen
->ForwardLink
;
2804 Difference
= (Temp
- BottomRow
) - (SavedMenuOption
->Skip
- OldSkipValue
);
2806 OldSkipValue
= Difference
;
2808 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2811 // If we have a remainder, skip that many more op-codes until we drain the remainder
2814 Difference
>= (INTN
) SavedMenuOption
->Skip
;
2815 Difference
= Difference
- (INTN
) SavedMenuOption
->Skip
2818 // Since the Difference is greater than or equal to this op-code's skip value, skip it
2820 TopOfScreen
= TopOfScreen
->ForwardLink
;
2821 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2822 if (Difference
< (INTN
) SavedMenuOption
->Skip
) {
2823 Difference
= SavedMenuOption
->Skip
- Difference
- 1;
2826 if (Difference
== (INTN
) SavedMenuOption
->Skip
) {
2827 TopOfScreen
= TopOfScreen
->ForwardLink
;
2828 SavedMenuOption
= CR (TopOfScreen
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2829 Difference
= SavedMenuOption
->Skip
- Difference
;
2835 // Since we will act on this op-code in the next routine, and increment the
2836 // SkipValue, set the skips to one less than what is required.
2838 SkipValue
= Difference
- 1;
2842 // Since we will act on this op-code in the next routine, and increment the
2843 // SkipValue, set the skips to one less than what is required.
2845 SkipValue
= OldSkipValue
+ (Temp
- BottomRow
) - 1;
2848 if ((OldSkipValue
+ 1) == (INTN
) SavedMenuOption
->Skip
) {
2849 TopOfScreen
= TopOfScreen
->ForwardLink
;
2852 SkipValue
= OldSkipValue
;
2856 // If the op-code at the top of the screen is more than one line, let's not skip it yet
2857 // Let's set a skip flag to smoothly scroll the top of the screen.
2859 if (SavedMenuOption
->Skip
> 1) {
2860 if (SavedMenuOption
== NextMenuOption
) {
2867 TopOfScreen
= TopOfScreen
->ForwardLink
;
2869 } while (SavedMenuOption
->Skip
== 0);
2872 OldSkipValue
= SkipValue
;
2875 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2879 SavedMenuOption
= MenuOption
;
2880 MenuOption
= CR (NewPos
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
2881 if (MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
) {
2883 // If we are at the end of the list and sitting on a text op, we need to more forward
2885 ScreenOperation
= UiUp
;
2886 ControlFlag
= CfScreenOperation
;
2890 MenuOption
= SavedMenuOption
;
2892 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
2894 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2900 ControlFlag
= CfCheckSelection
;
2902 // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
2904 if (MenuOption
!= NULL
) {
2905 if (!SelectionsAreValid (MenuOption
, FileFormTagsHead
)) {
2912 // If callbacks are active, and the callback has a Write method, try to use it
2914 if (FileFormTags
->VariableDefinitions
->VariableName
== NULL
) {
2915 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2916 Status
= FormCallback
->NvWrite (
2918 (CHAR16
*) L
"Setup",
2919 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2920 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2921 VariableDefinition
->VariableSize
,
2922 (VOID
*) VariableDefinition
->NvRamMap
,
2927 Status
= gRT
->SetVariable (
2928 (CHAR16
*) L
"Setup",
2929 &FileFormTags
->FormTags
.Tags
[0].GuidValue
,
2930 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2931 VariableDefinition
->VariableSize
,
2932 (VOID
*) VariableDefinition
->NvRamMap
2936 VariableDefinition
= FileFormTags
->VariableDefinitions
;
2938 for (; VariableDefinition
!= NULL
; VariableDefinition
= VariableDefinition
->Next
) {
2939 if ((FormCallback
!= NULL
) && (FormCallback
->NvWrite
!= NULL
)) {
2940 Status
= FormCallback
->NvWrite (
2942 VariableDefinition
->VariableName
,
2943 &VariableDefinition
->Guid
,
2944 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2945 VariableDefinition
->VariableSize
,
2946 (VOID
*) VariableDefinition
->NvRamMap
,
2951 Status
= gRT
->SetVariable (
2952 VariableDefinition
->VariableName
,
2953 &VariableDefinition
->Guid
,
2954 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
2955 VariableDefinition
->VariableSize
,
2956 (VOID
*) VariableDefinition
->NvRamMap
2962 UpdateStatusBar (INPUT_ERROR
, MenuOption
->ThisTag
->Flags
, FALSE
);
2963 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, FALSE
);
2967 ControlFlag
= CfCheckSelection
;
2969 NvMapListHead
= NULL
;
2971 Status
= Hii
->GetDefaultImage (Hii
, MenuOption
->Handle
, EFI_IFR_FLAG_DEFAULT
, &NvMapListHead
);
2973 if (!EFI_ERROR (Status
)) {
2974 ASSERT_EFI_ERROR (NULL
!= NvMapListHead
);
2976 NvMapListNode
= NvMapListHead
;
2978 while (NULL
!= NvMapListNode
) {
2979 if (FileFormTags
->VariableDefinitions
->VariableId
== NvMapListNode
->VariablePack
->VariableId
) {
2980 NvMap
= (VOID
*) ((CHAR8
*) NvMapListNode
->VariablePack
+ sizeof (EFI_HII_VARIABLE_PACK
) + NvMapListNode
->VariablePack
->VariableNameLength
);
2981 NvMapSize
= NvMapListNode
->VariablePack
->Header
.Length
- sizeof (EFI_HII_VARIABLE_PACK
) - NvMapListNode
->VariablePack
->VariableNameLength
;
2984 NvMapListNode
= NvMapListNode
->NextVariablePack
;
2988 // Free the buffer that was allocated.
2990 FreePool (FileFormTags
->VariableDefinitions
->NvRamMap
);
2991 FreePool (FileFormTags
->VariableDefinitions
->FakeNvRamMap
);
2994 // Allocate, copy the NvRamMap.
2996 FileFormTags
->VariableDefinitions
->VariableFakeSize
= (UINT16
) (FileFormTags
->VariableDefinitions
->VariableFakeSize
- FileFormTags
->VariableDefinitions
->VariableSize
);
2997 FileFormTags
->VariableDefinitions
->VariableSize
= (UINT16
) NvMapSize
;
2998 FileFormTags
->VariableDefinitions
->VariableFakeSize
= (UINT16
) (FileFormTags
->VariableDefinitions
->VariableFakeSize
+ FileFormTags
->VariableDefinitions
->VariableSize
);
3000 FileFormTags
->VariableDefinitions
->NvRamMap
= AllocateZeroPool (FileFormTags
->VariableDefinitions
->VariableSize
);
3001 ASSERT (FileFormTags
->VariableDefinitions
->NvRamMap
!= NULL
);
3003 FileFormTags
->VariableDefinitions
->FakeNvRamMap
= AllocateZeroPool (NvMapSize
+ FileFormTags
->VariableDefinitions
->VariableFakeSize
);
3004 ASSERT (FileFormTags
->VariableDefinitions
->FakeNvRamMap
!= NULL
);
3006 CopyMem (FileFormTags
->VariableDefinitions
->NvRamMap
, NvMap
, NvMapSize
);
3007 FreePool (NvMapListHead
);
3010 UpdateStatusBar (NV_UPDATE_REQUIRED
, MenuOption
->ThisTag
->Flags
, TRUE
);
3013 // After the repaint operation, we should refresh the highlight.
3018 case CfUiNoOperation
:
3019 ControlFlag
= CfCheckSelection
;
3023 while (gMenuRefreshHead
!= NULL
) {
3024 OldMenuRefreshEntry
= gMenuRefreshHead
->Next
;
3026 FreePool (gMenuRefreshHead
);
3028 gMenuRefreshHead
= OldMenuRefreshEntry
;
3031 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, 0, Row
+ 4);
3032 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
3033 gST
->ConOut
->OutputString (gST
->ConOut
, (CHAR16
*) L
"\n");
3035 gActiveIfr
= MenuOption
->IfrNumber
;
3046 IN BOOLEAN Direction
,
3047 IN LIST_ENTRY
*CurrentPos
3051 Routine Description:
3052 Determine if the menu is the last menu that can be selected.
3055 Direction - the scroll direction. False is down. True is up.
3058 FALSE -- the menu isn't the last menu that can be selected.
3059 TRUE -- the menu is the last menu that can be selected.
3063 UI_MENU_OPTION
*MenuOption
;
3066 Temp
= Direction
? CurrentPos
->BackLink
: CurrentPos
->ForwardLink
;
3068 if (Temp
== &Menu
) {
3072 for (; Temp
!= &Menu
; Temp
= Direction
? Temp
->BackLink
: Temp
->ForwardLink
) {
3073 MenuOption
= CR (Temp
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3074 if (!(MenuOption
->ThisTag
->Operand
== EFI_IFR_SUBTITLE_OP
|| MenuOption
->ThisTag
->GrayOut
)) {
3083 AdjustDateAndTimePosition (
3084 IN BOOLEAN DirectionUp
,
3085 IN LIST_ENTRY
**CurrentPosition
3088 Routine Description:
3089 Adjust Data and Time tag position accordingly.
3090 Data format : [01/02/2004] [11:22:33]
3091 Line number : 0 0 1 0 0 1
3094 Direction - the up or down direction. False is down. True is up.
3095 CurrentPos - Current position.
3098 Return line number to pad. It is possible that we stand on a zero-advance
3099 data or time opcode, so pad one line when we judge if we are going to scroll outside.
3103 LIST_ENTRY
*NewPosition
;
3104 UI_MENU_OPTION
*MenuOption
;
3105 UINTN PadLineNumber
;
3108 NewPosition
= *CurrentPosition
;
3109 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3111 if ((MenuOption
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
3113 // Calculate the distance from current position to the last Date/Time op-code.
3116 while (MenuOption
->ThisTag
->NumberOfLines
== 0) {
3118 NewPosition
= NewPosition
->ForwardLink
;
3119 MenuOption
= CR (NewPosition
, UI_MENU_OPTION
, Link
, UI_MENU_OPTION_SIGNATURE
);
3123 NewPosition
= *CurrentPosition
;
3126 // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
3127 // to be one that back to the previous set of op-codes, we need to advance to the first
3128 // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate
3129 // checking can be done.
3131 while (Count
++ < 2) {
3132 NewPosition
= NewPosition
->BackLink
;
3136 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
3137 // to be one that progresses to the next set of op-codes, we need to advance to the last
3138 // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate
3139 // checking can be done.
3141 while (Count
-- > 0) {
3142 NewPosition
= NewPosition
->ForwardLink
;
3146 *CurrentPosition
= NewPosition
;
3149 return PadLineNumber
;