2 Copyright (c) 2006 - 2007, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 Some presentation routines.
39 // For now, allocate an arbitrarily long buffer
41 Buffer
= AllocateZeroPool (0x10000);
42 ASSERT (Buffer
!= NULL
);
45 // Set foreground and background as defined
47 gST
->ConOut
->SetAttribute (gST
->ConOut
, TextAttribute
);
50 // Much faster to buffer the long string instead of print it a character at a time
52 SetUnicodeMem (Buffer
, RightColumn
- LeftColumn
, L
' ');
55 // Clear the desired area with the appropriate foreground/background
57 for (Row
= TopRow
; Row
<= BottomRow
; Row
++) {
58 PrintStringAt (LeftColumn
, Row
, Buffer
);
61 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, LeftColumn
, TopRow
);
75 for (Length
= 0; Destination
[Length
] != 0; Length
++)
79 // We now have the length of the original string
80 // We can safely assume for now that we are concatenating a narrow value to this string.
81 // For instance, the string is "XYZ" and cat'ing ">"
82 // If this assumption changes, we need to make this routine a bit more complex
84 Destination
[Length
] = (CHAR16
) NARROW_CHAR
;
87 StrCpy (Destination
+ Length
, Source
);
105 // Advance to the null-terminator or to the first width directive
108 (String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
109 Index
++, Count
= Count
+ IncrementValue
114 // We hit the null-terminator, we now have a count
116 if (String
[Index
] == 0) {
120 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
121 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
123 if (String
[Index
] == NARROW_CHAR
) {
125 // Skip to the next character
131 // Skip to the next character
136 } while (String
[Index
] != 0);
139 // Increment by one to include the null-terminator in the size
143 return Count
* sizeof (CHAR16
);
156 CHAR16
*StrFrontPageBanner
;
157 EFI_SCREEN_DESCRIPTOR LocalScreen
;
160 ZeroMem (&LocalScreen
, sizeof (EFI_SCREEN_DESCRIPTOR
));
161 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &LocalScreen
.RightColumn
, &LocalScreen
.BottomRow
);
162 ClearLines (0, LocalScreen
.RightColumn
, 0, LocalScreen
.BottomRow
, KEYHELP_BACKGROUND
);
164 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
167 // For now, allocate an arbitrarily long buffer
169 Buffer
= AllocateZeroPool (0x10000);
170 ASSERT (Buffer
!= NULL
);
172 Character
= (CHAR16
) BOXDRAW_HORIZONTAL
;
174 for (Index
= 0; Index
+ 2 < (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
); Index
++) {
175 Buffer
[Index
] = Character
;
178 if (gClassOfVfr
== EFI_FRONT_PAGE_SUBCLASS
) {
180 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
183 LocalScreen
.LeftColumn
,
184 LocalScreen
.RightColumn
,
186 FRONT_PAGE_HEADER_HEIGHT
- 1 + LocalScreen
.TopRow
,
187 BANNER_TEXT
| BANNER_BACKGROUND
190 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
192 for (Line
= (UINT8
) LocalScreen
.TopRow
; Line
< BANNER_HEIGHT
+ (UINT8
) LocalScreen
.TopRow
; Line
++) {
194 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
196 for (Alignment
= (UINT8
) LocalScreen
.LeftColumn
;
197 Alignment
< BANNER_COLUMNS
+ (UINT8
) LocalScreen
.LeftColumn
;
200 if (BannerData
->Banner
[Line
- (UINT8
) LocalScreen
.TopRow
][Alignment
- (UINT8
) LocalScreen
.LeftColumn
] != 0x0000) {
201 StrFrontPageBanner
= GetToken (
202 BannerData
->Banner
[Line
- (UINT8
) LocalScreen
.TopRow
][Alignment
- (UINT8
) LocalScreen
.LeftColumn
],
209 switch (Alignment
- LocalScreen
.LeftColumn
) {
212 // Handle left column
214 PrintStringAt (LocalScreen
.LeftColumn
, Line
, StrFrontPageBanner
);
219 // Handle center column
222 LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) / 3,
230 // Handle right column
233 LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) * 2 / 3,
240 FreePool (StrFrontPageBanner
);
246 LocalScreen
.LeftColumn
,
247 LocalScreen
.RightColumn
,
248 LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
,
249 LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- 1,
250 KEYHELP_TEXT
| KEYHELP_BACKGROUND
253 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
255 LocalScreen
.LeftColumn
,
256 LocalScreen
.RightColumn
,
258 LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
- 1,
259 TITLE_TEXT
| TITLE_BACKGROUND
262 // Print Top border line
263 // +------------------------------------------------------------------------------+
265 // +------------------------------------------------------------------------------+
267 Character
= (CHAR16
) BOXDRAW_DOWN_RIGHT
;
269 PrintChar (Character
);
270 PrintString (Buffer
);
272 Character
= (CHAR16
) BOXDRAW_DOWN_LEFT
;
273 PrintChar (Character
);
275 Character
= (CHAR16
) BOXDRAW_VERTICAL
;
276 for (Row
= LocalScreen
.TopRow
+ 1; Row
<= LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
- 2; Row
++) {
277 PrintCharAt (LocalScreen
.LeftColumn
, Row
, Character
);
278 PrintCharAt (LocalScreen
.RightColumn
- 1, Row
, Character
);
281 Character
= (CHAR16
) BOXDRAW_UP_RIGHT
;
282 PrintCharAt (LocalScreen
.LeftColumn
, LocalScreen
.TopRow
+ NONE_FRONT_PAGE_HEADER_HEIGHT
- 1, Character
);
283 PrintString (Buffer
);
285 Character
= (CHAR16
) BOXDRAW_UP_LEFT
;
286 PrintChar (Character
);
288 if (gClassOfVfr
== EFI_SETUP_APPLICATION_SUBCLASS
) {
290 // Print Bottom border line
291 // +------------------------------------------------------------------------------+
293 // +------------------------------------------------------------------------------+
295 Character
= (CHAR16
) BOXDRAW_DOWN_RIGHT
;
296 PrintCharAt (LocalScreen
.LeftColumn
, LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
, Character
);
298 PrintString (Buffer
);
300 Character
= (CHAR16
) BOXDRAW_DOWN_LEFT
;
301 PrintChar (Character
);
302 Character
= (CHAR16
) BOXDRAW_VERTICAL
;
303 for (Row
= LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- FOOTER_HEIGHT
+ 1;
304 Row
<= LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- 2;
307 PrintCharAt (LocalScreen
.LeftColumn
, Row
, Character
);
308 PrintCharAt (LocalScreen
.RightColumn
- 1, Row
, Character
);
311 Character
= (CHAR16
) BOXDRAW_UP_RIGHT
;
312 PrintCharAt (LocalScreen
.LeftColumn
, LocalScreen
.BottomRow
- STATUS_BAR_HEIGHT
- 1, Character
);
314 PrintString (Buffer
);
316 Character
= (CHAR16
) BOXDRAW_UP_LEFT
;
317 PrintChar (Character
);
326 +------------------------------------------------------------------------------+
327 ?F2=Previous Page Setup Page ?
328 +------------------------------------------------------------------------------+
346 +------------------------------------------------------------------------------+
347 ?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
348 | ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
349 +------------------------------------------------------------------------------+
354 OUT UI_MENU_OPTION
*Selection
,
355 IN UINT16 FormHandle
,
356 IN UINT16 TitleToken
,
357 IN EFI_FORM_TAGS FormTags
,
358 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
359 IN UINT8
*CallbackData
365 UINT16 MenuItemCount
;
366 EFI_HII_HANDLE Handle
;
369 EFI_FILE_FORM_TAGS
*FileFormTags
;
374 EFI_SCREEN_DESCRIPTOR LocalScreen
;
377 CHAR16
*OutputString
;
379 Handle
= Selection
->Handle
;
386 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
389 // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need
391 if (Selection
->Previous
) {
392 Selection
->Previous
= FALSE
;
398 StringPtr
= GetToken (TitleToken
, Handle
);
400 if (gClassOfVfr
!= EFI_FRONT_PAGE_SUBCLASS
) {
401 gST
->ConOut
->SetAttribute (gST
->ConOut
, TITLE_TEXT
| TITLE_BACKGROUND
);
403 (LocalScreen
.RightColumn
+ LocalScreen
.LeftColumn
- GetStringWidth (StringPtr
) / 2) / 2,
404 LocalScreen
.TopRow
+ 1,
409 if (gClassOfVfr
== EFI_SETUP_APPLICATION_SUBCLASS
) {
410 gST
->ConOut
->SetAttribute (gST
->ConOut
, KEYHELP_TEXT
| KEYHELP_BACKGROUND
);
413 // Display the infrastructure strings
415 if (!IsListEmpty (&gMenuList
)) {
416 PrintStringAt (LocalScreen
.LeftColumn
+ 2, LocalScreen
.TopRow
+ 1, gFunctionTwoString
);
419 PrintStringAt (LocalScreen
.LeftColumn
+ 2, LocalScreen
.BottomRow
- 4, gFunctionOneString
);
421 LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) / 3,
422 LocalScreen
.BottomRow
- 4,
426 LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) * 2 / 3,
427 LocalScreen
.BottomRow
- 4,
430 PrintAt (LocalScreen
.LeftColumn
+ 2, LocalScreen
.BottomRow
- 3, (CHAR16
*) L
"%c%c%s", ARROW_UP
, ARROW_DOWN
, gMoveHighlight
);
432 LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) / 3,
433 LocalScreen
.BottomRow
- 3,
438 // Remove Buffer allocated for StringPtr after it has been used.
440 FreePool (StringPtr
);
442 for (Index
= 0; FormTags
.Tags
[Index
].Operand
!= EFI_IFR_END_FORM_OP
; Index
++) {
447 FileFormTags
= FileFormTagsHead
;
449 if (FormTags
.Tags
[Index
].Operand
== EFI_IFR_FORM_OP
) {
450 FormId
= FormTags
.Tags
[Index
].Id
;
453 // This gives us visibility to the FileFormTags->NvRamMap to check things
454 // ActiveIfr is a global maintained by the menuing code to ensure that we
455 // are pointing to the correct formset's file data.
457 for (Count
= 0; Count
< gActiveIfr
; Count
++) {
458 FileFormTags
= FileFormTags
->NextFile
;
461 // GrayoutIf [SuppressIf]
466 // SuppressIf [GrayoutIf]
474 switch (FormTags
.Tags
[Index
].Operand
) {
475 case EFI_IFR_SUPPRESS_IF_OP
:
478 case EFI_IFR_GRAYOUT_IF_OP
:
483 // Advance to the next op-code
488 // We are now pointing to the beginning of the consistency checking. Let's fast forward
489 // through the AND/OR/NOT data to come up with some meaningful ID data.
492 FormTags
.Tags
[Index
].Operand
== EFI_IFR_AND_OP
||
493 FormTags
.Tags
[Index
].Operand
== EFI_IFR_OR_OP
||
494 FormTags
.Tags
[Index
].Operand
== EFI_IFR_GT_OP
||
495 FormTags
.Tags
[Index
].Operand
== EFI_IFR_GE_OP
||
496 FormTags
.Tags
[Index
].Operand
== EFI_IFR_NOT_OP
;
502 // We need to walk through the consistency checks until we hit the end of the consistency
503 // FALSE means evaluate this single expression
504 // The ConsistencyId refers to which expression in the Consistency database to use
507 Suppress
= ValueIsNotValid (
509 FormTags
.Tags
[Index
].ConsistencyId
,
510 &FormTags
.Tags
[Index
],
516 GrayOut
= ValueIsNotValid (
518 FormTags
.Tags
[Index
].ConsistencyId
,
519 &FormTags
.Tags
[Index
],
525 // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected)
528 FormTags
.Tags
[Index
].Operand
== EFI_IFR_EQ_ID_VAL_OP
||
529 FormTags
.Tags
[Index
].Operand
== EFI_IFR_EQ_VAR_VAL_OP
||
530 FormTags
.Tags
[Index
].Operand
== EFI_IFR_EQ_ID_ID_OP
||
531 FormTags
.Tags
[Index
].Operand
== EFI_IFR_EQ_ID_LIST_OP
||
532 FormTags
.Tags
[Index
].Operand
== EFI_IFR_NOT_OP
||
533 FormTags
.Tags
[Index
].Operand
== EFI_IFR_AND_OP
||
534 FormTags
.Tags
[Index
].Operand
== EFI_IFR_OR_OP
||
535 FormTags
.Tags
[Index
].Operand
== EFI_IFR_TRUE_OP
||
536 FormTags
.Tags
[Index
].Operand
== EFI_IFR_FALSE_OP
||
537 FormTags
.Tags
[Index
].Operand
== EFI_IFR_GT_OP
||
538 FormTags
.Tags
[Index
].Operand
== EFI_IFR_GE_OP
||
539 FormTags
.Tags
[Index
].Operand
== EFI_IFR_LABEL_OP
;
549 // Do this two times (at most will see a suppress and grayout combination
557 FormTags
.Tags
[Index
].GrayOut
= TRUE
;
559 FormTags
.Tags
[Index
].GrayOut
= FALSE
;
561 if (Suppress
&& FormTags
.Tags
[Index
].Operand
== EFI_IFR_ONE_OF_OPTION_OP
) {
563 // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly.
565 FormTags
.Tags
[Index
].Suppress
= TRUE
;
567 FormTags
.Tags
[Index
].Suppress
= FALSE
;
571 FormTags
.Tags
[Index
].NumberOfLines
> 0 ||
572 FormTags
.Tags
[Index
].Operand
== EFI_IFR_DATE_OP
||
573 FormTags
.Tags
[Index
].Operand
== EFI_IFR_TIME_OP
578 StringPtr
= GetToken (FormTags
.Tags
[Index
].Text
, Handle
);
580 Width
= GetWidth (&FormTags
.Tags
[Index
], Handle
);
583 // This data can be retrieved over and over again. Therefore, reset to original values
584 // before processing otherwise things will start growing linearly
586 if (FormTags
.Tags
[Index
].NumberOfLines
> 1) {
587 FormTags
.Tags
[Index
].NumberOfLines
= 1;
590 for (Count
= 0; GetLineByWidth (StringPtr
, Width
, &ArrayEntry
, &OutputString
) != 0x0000;) {
592 // If there is more string to process print on the next row and increment the Skip value
594 if (StrLen (&StringPtr
[ArrayEntry
])) {
595 FormTags
.Tags
[Index
].NumberOfLines
++;
598 FreePool (OutputString
);
604 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
607 UiAddSubMenuOption (StringPtr
, Handle
, FormTags
.Tags
, Index
, FormId
, MenuItemCount
);
611 // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if
614 } while (FormTags
.Tags
[Index
].Operand
!= EFI_IFR_END_IF_OP
&& Conditional
);
617 // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic
622 Selection
= UiDisplayMenu (TRUE
, FileFormTagsHead
, (EFI_IFR_DATA_ARRAY
*) CallbackData
);
628 InitializeBrowserStrings (
632 gFunctionOneString
= GetToken (STRING_TOKEN (FUNCTION_ONE_STRING
), gHiiHandle
);
633 gFunctionTwoString
= GetToken (STRING_TOKEN (FUNCTION_TWO_STRING
), gHiiHandle
);
634 gFunctionNineString
= GetToken (STRING_TOKEN (FUNCTION_NINE_STRING
), gHiiHandle
);
635 gFunctionTenString
= GetToken (STRING_TOKEN (FUNCTION_TEN_STRING
), gHiiHandle
);
636 gEnterString
= GetToken (STRING_TOKEN (ENTER_STRING
), gHiiHandle
);
637 gEnterCommitString
= GetToken (STRING_TOKEN (ENTER_COMMIT_STRING
), gHiiHandle
);
638 gEscapeString
= GetToken (STRING_TOKEN (ESCAPE_STRING
), gHiiHandle
);
639 gMoveHighlight
= GetToken (STRING_TOKEN (MOVE_HIGHLIGHT
), gHiiHandle
);
640 gMakeSelection
= GetToken (STRING_TOKEN (MAKE_SELECTION
), gHiiHandle
);
641 gNumericInput
= GetToken (STRING_TOKEN (NUMERIC_INPUT
), gHiiHandle
);
642 gToggleCheckBox
= GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX
), gHiiHandle
);
643 gPromptForPassword
= GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD
), gHiiHandle
);
644 gPromptForNewPassword
= GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD
), gHiiHandle
);
645 gConfirmPassword
= GetToken (STRING_TOKEN (CONFIRM_PASSWORD
), gHiiHandle
);
646 gConfirmError
= GetToken (STRING_TOKEN (CONFIRM_ERROR
), gHiiHandle
);
647 gPressEnter
= GetToken (STRING_TOKEN (PRESS_ENTER
), gHiiHandle
);
648 gEmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
649 gAreYouSure
= GetToken (STRING_TOKEN (ARE_YOU_SURE
), gHiiHandle
);
650 gYesResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_YES
), gHiiHandle
);
651 gNoResponse
= GetToken (STRING_TOKEN (ARE_YOU_SURE_NO
), gHiiHandle
);
652 gMiniString
= GetToken (STRING_TOKEN (MINI_STRING
), gHiiHandle
);
653 gPlusString
= GetToken (STRING_TOKEN (PLUS_STRING
), gHiiHandle
);
654 gMinusString
= GetToken (STRING_TOKEN (MINUS_STRING
), gHiiHandle
);
655 gAdjustNumber
= GetToken (STRING_TOKEN (ADJUST_NUMBER
), gHiiHandle
);
661 IN UI_MENU_OPTION
*Selection
,
666 Update key's help imformation
669 Selection C The form that current display
670 Selected C Whether or not a tag be selected
678 UINTN LeftColumnOfHelp
;
679 UINTN RightColumnOfHelp
;
681 UINTN BottomRowOfHelp
;
682 UINTN StartColumnOfHelp
;
683 EFI_SCREEN_DESCRIPTOR LocalScreen
;
685 CopyMem (&LocalScreen
, &gScreenDimensions
, sizeof (EFI_SCREEN_DESCRIPTOR
));
687 SecCol
= LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) / 3;
688 ThdCol
= LocalScreen
.LeftColumn
+ (LocalScreen
.RightColumn
- LocalScreen
.LeftColumn
) * 2 / 3;
690 StartColumnOfHelp
= LocalScreen
.LeftColumn
+ 2;
691 LeftColumnOfHelp
= LocalScreen
.LeftColumn
+ 1;
692 RightColumnOfHelp
= LocalScreen
.RightColumn
- 2;
693 TopRowOfHelp
= LocalScreen
.BottomRow
- 4;
694 BottomRowOfHelp
= LocalScreen
.BottomRow
- 3;
696 if (gClassOfVfr
== EFI_GENERAL_APPLICATION_SUBCLASS
) {
700 gST
->ConOut
->SetAttribute (gST
->ConOut
, KEYHELP_TEXT
| KEYHELP_BACKGROUND
);
702 switch (Selection
->ThisTag
->Operand
) {
703 case EFI_IFR_ORDERED_LIST_OP
:
704 case EFI_IFR_ONE_OF_OP
:
705 case EFI_IFR_NUMERIC_OP
:
706 case EFI_IFR_TIME_OP
:
707 case EFI_IFR_DATE_OP
:
708 ClearLines (LeftColumnOfHelp
, RightColumnOfHelp
, TopRowOfHelp
, BottomRowOfHelp
, KEYHELP_TEXT
| KEYHELP_BACKGROUND
);
711 if (gClassOfVfr
== EFI_SETUP_APPLICATION_SUBCLASS
) {
712 PrintStringAt (StartColumnOfHelp
, TopRowOfHelp
, gFunctionOneString
);
713 PrintStringAt (SecCol
, TopRowOfHelp
, gFunctionNineString
);
714 PrintStringAt (ThdCol
, TopRowOfHelp
, gFunctionTenString
);
715 PrintStringAt (ThdCol
, BottomRowOfHelp
, gEscapeString
);
719 if ((Selection
->ThisTag
->Operand
== EFI_IFR_DATE_OP
) || (Selection
->ThisTag
->Operand
== EFI_IFR_TIME_OP
)) {
723 (CHAR16
*) L
"%c%c%c%c%s",
730 PrintStringAt (SecCol
, BottomRowOfHelp
, gAdjustNumber
);
732 PrintAt (StartColumnOfHelp
, BottomRowOfHelp
, (CHAR16
*) L
"%c%c%s", ARROW_UP
, ARROW_DOWN
, gMoveHighlight
);
733 PrintStringAt (SecCol
, BottomRowOfHelp
, gEnterString
);
736 PrintStringAt (SecCol
, BottomRowOfHelp
, gEnterCommitString
);
739 // If it is a selected numeric with manual input, display different message
741 if ((Selection
->ThisTag
->Operand
== EFI_IFR_NUMERIC_OP
) && (Selection
->ThisTag
->Step
== 0)) {
742 PrintStringAt (SecCol
, TopRowOfHelp
, gNumericInput
);
743 } else if (Selection
->ThisTag
->Operand
!= EFI_IFR_ORDERED_LIST_OP
) {
744 PrintAt (StartColumnOfHelp
, BottomRowOfHelp
, L
"%c%c%s", ARROW_UP
, ARROW_DOWN
, gMoveHighlight
);
747 if (Selection
->ThisTag
->Operand
== EFI_IFR_ORDERED_LIST_OP
) {
748 PrintStringAt (StartColumnOfHelp
, TopRowOfHelp
, gPlusString
);
749 PrintStringAt (ThdCol
, TopRowOfHelp
, gMinusString
);
752 PrintStringAt (ThdCol
, BottomRowOfHelp
, gEscapeString
);
756 case EFI_IFR_CHECKBOX_OP
:
757 ClearLines (LeftColumnOfHelp
, RightColumnOfHelp
, TopRowOfHelp
, BottomRowOfHelp
, KEYHELP_TEXT
| KEYHELP_BACKGROUND
);
759 if (gClassOfVfr
== EFI_SETUP_APPLICATION_SUBCLASS
) {
760 PrintStringAt (StartColumnOfHelp
, TopRowOfHelp
, gFunctionOneString
);
761 PrintStringAt (SecCol
, TopRowOfHelp
, gFunctionNineString
);
762 PrintStringAt (ThdCol
, TopRowOfHelp
, gFunctionTenString
);
763 PrintStringAt (ThdCol
, BottomRowOfHelp
, gEscapeString
);
766 PrintAt (StartColumnOfHelp
, BottomRowOfHelp
, (CHAR16
*) L
"%c%c%s", ARROW_UP
, ARROW_DOWN
, gMoveHighlight
);
767 PrintStringAt (SecCol
, BottomRowOfHelp
, gToggleCheckBox
);
771 case EFI_IFR_PASSWORD_OP
:
772 case EFI_IFR_STRING_OP
:
773 ClearLines (LeftColumnOfHelp
, RightColumnOfHelp
, TopRowOfHelp
, BottomRowOfHelp
, KEYHELP_TEXT
| KEYHELP_BACKGROUND
);
776 if (gClassOfVfr
== EFI_SETUP_APPLICATION_SUBCLASS
) {
777 PrintStringAt (StartColumnOfHelp
, TopRowOfHelp
, gFunctionOneString
);
778 PrintStringAt (SecCol
, TopRowOfHelp
, gFunctionNineString
);
779 PrintStringAt (ThdCol
, TopRowOfHelp
, gFunctionTenString
);
780 PrintStringAt (ThdCol
, BottomRowOfHelp
, gEscapeString
);
783 PrintAt (StartColumnOfHelp
, BottomRowOfHelp
, (CHAR16
*) L
"%c%c%s", ARROW_UP
, ARROW_DOWN
, gMoveHighlight
);
784 PrintStringAt (SecCol
, BottomRowOfHelp
, gEnterString
);
786 if (Selection
->ThisTag
->Operand
!= EFI_IFR_REF_OP
) {
788 (LocalScreen
.RightColumn
- GetStringWidth (gEnterCommitString
) / 2) / 2,
792 PrintStringAt (ThdCol
, BottomRowOfHelp
, gEscapeString
);
803 IN UI_MENU_OPTION
*Selection
,
804 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
806 OUT UINT16
*FormHandle
,
807 OUT UINT16
*TitleToken
,
808 OUT EFI_FORM_TAGS
*FormTags
812 EFI_FILE_FORM_TAGS
*FileFormTags
;
813 EFI_FORM_TAGS LocalTags
;
815 FileFormTags
= FileFormTagsHead
;
818 // Advance FileFormTags to the correct file's tag information.
819 // For instance, if Selection->IfrNumber is 3, that means the 4th
820 // file (0-based) in the FileFormTags linked-list contains the tag
823 for (Index
= 0; Index
< Selection
->IfrNumber
; Index
++) {
824 FileFormTags
= FileFormTags
->NextFile
;
827 LocalTags
= FileFormTags
->FormTags
;
831 // Advance Index to the first FormOp tag information
833 for (Index
= 0; FileFormTags
->FormTags
.Tags
[Index
].Operand
!= EFI_IFR_FORM_OP
; Index
++)
837 // Advance Index to the FormOp with the correct ID value
839 for (; LocalTags
.Next
!= NULL
; LocalTags
= *LocalTags
.Next
) {
840 for (Index
= 0; LocalTags
.Tags
[Index
].Operand
!= EFI_IFR_FORM_OP
; Index
++)
842 if (LocalTags
.Tags
[Index
].Id
== IdValue
) {
848 // return the Form Id, Text, and the File's FormTags structure
850 *FormHandle
= LocalTags
.Tags
[Index
].Id
;
851 *TitleToken
= LocalTags
.Tags
[Index
].Text
;
852 *FormTags
= LocalTags
;
860 IN UINT16 ConsistencyId
,
861 IN UINT16 CurrentVariable
,
862 IN EFI_FORM_TAGS
*FormTags
,
863 OUT EFI_FILE_FORM_TAGS
*FileFormTags
868 UINT16 QuestionIndex
;
876 // Initialize some Index variable and Status
882 Status
= EFI_SUCCESS
;
886 // Determine the number of tags for the first form
888 GetTagCount (&FormData
[Index
], &NumberOfTags
);
891 // Allocate memory for our tags on the first form
893 FormTags
->Tags
= AllocateZeroPool (NumberOfTags
* sizeof (EFI_TAG
));
894 ASSERT (FormTags
->Tags
!= NULL
);
896 for (CurrTag
= 0; FormData
[Index
] != EFI_IFR_END_FORM_SET_OP
; CurrTag
++) {
898 // Operand = IFR OpCode
900 FormTags
->Tags
[CurrTag
].Operand
= FormData
[Index
];
903 // Assume for now 0 lines occupied by this OpCode
905 FormTags
->Tags
[CurrTag
].NumberOfLines
= 0;
908 // Determine the length of the Tag so we can later skip to the next tag in the form
913 TagLength
= FormData
[Index
+ 1];
915 // Operate on the Found OpCode
917 switch (FormData
[Index
]) {
919 case EFI_IFR_FORM_OP
:
920 case EFI_IFR_SUBTITLE_OP
:
921 case EFI_IFR_TEXT_OP
:
923 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
926 case EFI_IFR_VARSTORE_SELECT_OP
:
927 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
928 CopyMem (&CurrentVariable
, &((EFI_IFR_VARSTORE_SELECT
*) &FormData
[Index
])->VarId
, sizeof (UINT16
));
931 case EFI_IFR_END_FORM_OP
:
932 FormTags
->Tags
[CurrTag
].Operand
= FormData
[Index
];
933 FormTags
->Tags
[CurrTag
].NumberOfLines
= 0;
938 case EFI_IFR_ORDERED_LIST_OP
:
939 case EFI_IFR_ONE_OF_OP
:
940 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], FormData
, Index
, FileFormTags
, CurrentVariable
);
943 // Store away the CurrTag since what follows will be the answer that we
944 // need to place into the appropriate location in the tag array
947 // record for setting default later
949 QuestionIndex
= (UINT16
) CurrTag
;
952 case EFI_IFR_ONE_OF_OPTION_OP
:
953 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
954 FormTags
->Tags
[QuestionIndex
].Key
= ((EFI_IFR_ONE_OF_OPTION
*) &FormData
[Index
])->Key
;
955 FormTags
->Tags
[QuestionIndex
].ResetRequired
= (BOOLEAN
) (FormTags
->Tags
[QuestionIndex
].Flags
& EFI_IFR_FLAG_RESET_REQUIRED
);
958 case EFI_IFR_CHECKBOX_OP
:
959 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], FormData
, Index
, FileFormTags
, CurrentVariable
);
960 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
963 case EFI_IFR_NUMERIC_OP
:
964 GetNumericHeader (&FormTags
->Tags
[CurrTag
], FormData
, Index
, (UINT16
) 1, FileFormTags
, CurrentVariable
);
965 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
968 case EFI_IFR_DATE_OP
:
970 // Date elements come in as a Year, Month, Day. We need to process them as a country-based
971 // Order. It is much easier to do it here than anywhere else.
973 // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2
976 &FormTags
->Tags
[CurrTag
],
978 (UINT16
) (Index
+ TagLength
),
985 // The current language selected + the Date operand
987 FormTags
->Tags
[CurrTag
+ 1].Operand
= FormData
[Index
];
989 &FormTags
->Tags
[CurrTag
+ 1],
991 (UINT16
) (Index
+ TagLength
+ FormData
[Index
+ TagLength
+ 1]),
998 // The current language selected + the Date operand
1000 FormTags
->Tags
[CurrTag
+ 2].Operand
= FormData
[Index
];
1001 GetNumericHeader (&FormTags
->Tags
[CurrTag
+ 2], FormData
, Index
, (UINT16
) 1, FileFormTags
, CurrentVariable
);
1003 CurrTag
= (INT16
) (CurrTag
+ 2);
1005 Index
= (UINT16
) (Index
+ TagLength
);
1009 TagLength
= FormData
[Index
+ 1];
1010 Index
= (UINT16
) (Index
+ TagLength
);
1014 TagLength
= FormData
[Index
+ 1];
1017 case EFI_IFR_TIME_OP
:
1018 GetNumericHeader (&FormTags
->Tags
[CurrTag
], FormData
, Index
, (UINT16
) 0, FileFormTags
, CurrentVariable
);
1022 // Override the GetQuestionHeader information - date/time are treated very differently
1024 FormTags
->Tags
[CurrTag
].NumberOfLines
= 1;
1028 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
1029 // associated with them, and the third has 1 line to allow to space beyond the choice.
1035 case EFI_IFR_PASSWORD_OP
:
1036 case EFI_IFR_STRING_OP
:
1037 GetQuestionHeader (&FormTags
->Tags
[CurrTag
], FormData
, Index
, FileFormTags
, CurrentVariable
);
1038 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
1041 case EFI_IFR_INCONSISTENT_IF_OP
:
1042 case EFI_IFR_SUPPRESS_IF_OP
:
1043 case EFI_IFR_GRAYOUT_IF_OP
:
1047 case EFI_IFR_EQ_ID_VAL_OP
:
1048 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
1049 FormTags
->Tags
[CurrTag
].ConsistencyId
= ConsistencyId
;
1052 case EFI_IFR_EQ_VAR_VAL_OP
:
1053 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
1054 FormTags
->Tags
[CurrTag
].ConsistencyId
= ConsistencyId
;
1057 case EFI_IFR_EQ_ID_ID_OP
:
1058 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
1059 FormTags
->Tags
[CurrTag
].ConsistencyId
= ConsistencyId
;
1062 case EFI_IFR_AND_OP
:
1064 case EFI_IFR_NOT_OP
:
1065 case EFI_IFR_TRUE_OP
:
1066 case EFI_IFR_FALSE_OP
:
1069 FormTags
->Tags
[CurrTag
].ConsistencyId
= ConsistencyId
;
1072 case EFI_IFR_EQ_ID_LIST_OP
:
1073 IfrToFormTag (FormData
[Index
], &FormTags
->Tags
[CurrTag
], (VOID
*) &FormData
[Index
], NULL
);
1075 FormTags
->Tags
[CurrTag
].ConsistencyId
= ConsistencyId
;
1088 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1090 Index
= (UINT16
) (Index
+ TagLength
);
1100 ExtractDynamicFormHandle (
1101 IN UI_MENU_OPTION
*Selection
,
1102 IN UINT8
*CallbackData
,
1103 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1105 OUT UINT16
*FormHandle
,
1106 OUT UINT16
*TitleToken
,
1107 OUT EFI_FORM_TAGS
*FormTags
1111 Routine Description:
1113 The function does the most of the works when the EFI_TAG that
1114 user selects on is EFI_IFR_FLAG_INTERACTIVE or EFI_IFR_PASSWORD_OP:
1115 invoke CallBack, update the new form data.
1119 Selection - The current selection of the form.
1120 CallbackData - The pointer to host the data passed back by the callback function.
1121 FileFormTagsHead - Prompt string token of the one-of box
1122 IdValue - The current page number.
1123 FormHandle - Output the the handle of the form.
1124 TitleToken - Output the TitleToken of the new page.
1125 FormTags - Output the FormFags of the new page.
1134 EFI_FILE_FORM_TAGS
*FileFormTags
;
1135 EFI_FORM_TAGS
*LocalTags
;
1136 EFI_FORM_CALLBACK_PROTOCOL
*FormCallback
;
1140 EFI_PHYSICAL_ADDRESS CallbackHandle
;
1143 EFI_HII_CALLBACK_PACKET
*Packet
;
1145 CHAR16 NullCharacter
;
1147 UINT16 ConsistencyId
;
1148 UINT16 CurrentVariable
;
1149 EFI_VARIABLE_DEFINITION
*VariableDefinition
;
1150 EFI_IFR_DATA_ENTRY
*DataEntry
;
1152 VariableDefinition
= NULL
;
1153 NullCharacter
= CHAR_NULL
;
1155 CurrentVariable
= 0;
1156 FileFormTags
= FileFormTagsHead
;
1159 TargetPage
= (UINT16
) IdValue
;
1164 // Advance FileFormTags to the correct file's tag information.
1165 // For instance, if Selection->IfrNumber is 3, that means the 4th
1166 // file (0-based) in the FileFormTags linked-list contains the tag
1169 for (Index
= 0; Index
< Selection
->IfrNumber
; Index
++) {
1170 FileFormTags
= FileFormTags
->NextFile
;
1173 LocalTags
= &FileFormTags
->FormTags
;
1176 // Advance Index to the FormOp with the correct ID value
1178 for (; LocalTags
->Next
!= NULL
; LocalTags
= LocalTags
->Next
) {
1179 if ((LocalTags
->Tags
[0].CallbackHandle
!= 0) && (CallbackHandle
== 0)) {
1180 CallbackHandle
= LocalTags
->Tags
[0].CallbackHandle
;
1181 CopyMem (&TagGuid
, &LocalTags
->Tags
[0].GuidValue
, sizeof (EFI_GUID
));
1184 for (Index
= 0; LocalTags
->Tags
[Index
].Operand
!= EFI_IFR_FORM_OP
; Index
++)
1186 if (LocalTags
->Tags
[Index
].Id
== IdValue
) {
1191 // If we are going to callback on a non-goto opcode, make sure we don't change pages
1193 if (Selection
->ThisTag
->Operand
!= EFI_IFR_REF_OP
) {
1194 TargetPage
= Selection
->FormId
;
1197 // The first tag below should be the form op-code. We need to store away the
1198 // current variable setting to ensure if we have to reload the page, that we
1199 // can correctly restore the values for the active variable
1201 CurrentVariable
= Selection
->Tags
[0].VariableNumber
;
1204 // Remember that dynamic pages in an environment where all pages are not
1205 // dynamic require us to call back to the user to give them an opportunity
1206 // to register fresh information in the HII database so that we can extract it.
1208 Status
= gBS
->HandleProtocol (
1209 (VOID
*) (UINTN
) CallbackHandle
,
1210 &gEfiFormCallbackProtocolGuid
,
1211 (VOID
**) &FormCallback
1214 if (EFI_ERROR (Status
)) {
1215 FreePool (LocalTags
->Tags
);
1219 ExtractRequestedNvMap (FileFormTags
, CurrentVariable
, &VariableDefinition
);
1221 if (Selection
->ThisTag
->Flags
& (EFI_IFR_FLAG_INTERACTIVE
| EFI_IFR_FLAG_NV_ACCESS
)) {
1222 ((EFI_IFR_DATA_ARRAY
*) CallbackData
)->NvRamMap
= VariableDefinition
->NvRamMap
;
1224 ((EFI_IFR_DATA_ARRAY
*) CallbackData
)->NvRamMap
= NULL
;
1227 if ((FormCallback
!= NULL
) && (FormCallback
->Callback
!= NULL
)) {
1228 Status
= FormCallback
->Callback (
1230 Selection
->ThisTag
->Key
,
1231 (EFI_IFR_DATA_ARRAY
*) CallbackData
,
1236 if (EFI_ERROR (Status
)) {
1238 // Restore Previous Value
1241 &VariableDefinition
->NvRamMap
[Selection
->ThisTag
->StorageStart
],
1243 Selection
->ThisTag
->StorageWidth
1246 if (Packet
!= NULL
) {
1248 // Upon error, we will likely receive a string to print out
1250 ScreenSize
= GetStringWidth (Packet
->String
) / 2;
1253 // Display error popup
1255 CreatePopUp (ScreenSize
, 3, &NullCharacter
, Packet
->String
, &NullCharacter
);
1258 Status
= WaitForKeyStroke (&Key
);
1259 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1261 UpdateStatusBar (INPUT_ERROR
, (UINT8
) 0, TRUE
);
1265 if (Packet
!= NULL
) {
1267 // We need to on a non-error, look in the outbound Packet for information and update the NVRAM
1268 // location associated with the op-code specified there. This is used on single op-code instances
1269 // and not for when a hyperlink sent us a whole page of data.
1271 DataEntry
= (EFI_IFR_DATA_ENTRY
*) (&Packet
->DataArray
+ 1);
1272 if (Packet
->DataArray
.EntryCount
== 1) {
1273 switch (DataEntry
->OpCode
) {
1274 case EFI_IFR_STRING_OP
:
1275 case EFI_IFR_NUMERIC_OP
:
1276 case EFI_IFR_ORDERED_LIST_OP
:
1277 case EFI_IFR_ONE_OF_OP
:
1278 case EFI_IFR_CHECKBOX_OP
:
1280 &VariableDefinition
->NvRamMap
[Selection
->ThisTag
->StorageStart
],
1282 Selection
->ThisTag
->StorageWidth
1286 case EFI_IFR_NV_ACCESS_COMMAND
:
1288 &VariableDefinition
->NvRamMap
[((EFI_IFR_NV_DATA
*) Packet
)->QuestionId
],
1289 ((EFI_IFR_NV_DATA
*) Packet
) + 1,
1290 ((EFI_IFR_NV_DATA
*) Packet
)->StorageWidth
1296 if (DataEntry
->Flags
& RESET_REQUIRED
) {
1297 gResetRequired
= TRUE
;
1300 if (DataEntry
->Flags
& EXIT_REQUIRED
) {
1301 gExitRequired
= TRUE
;
1304 if (DataEntry
->Flags
& SAVE_REQUIRED
) {
1305 gSaveRequired
= TRUE
;
1308 if (DataEntry
->Flags
& NV_CHANGED
) {
1309 gNvUpdateRequired
= TRUE
;
1312 if (DataEntry
->Flags
& NV_NOT_CHANGED
) {
1313 gNvUpdateRequired
= FALSE
;
1319 if (Packet
!= NULL
) {
1323 for (BackupIndex
= 0; LocalTags
->Tags
[BackupIndex
].Operand
!= EFI_IFR_END_FORM_OP
; BackupIndex
++) {
1324 switch (LocalTags
->Tags
[BackupIndex
].Operand
) {
1325 case EFI_IFR_EQ_VAR_VAL_OP
:
1326 case EFI_IFR_EQ_ID_VAL_OP
:
1327 case EFI_IFR_EQ_ID_ID_OP
:
1328 case EFI_IFR_AND_OP
:
1330 case EFI_IFR_NOT_OP
:
1331 case EFI_IFR_TRUE_OP
:
1332 case EFI_IFR_FALSE_OP
:
1335 case EFI_IFR_EQ_ID_LIST_OP
:
1337 // If we encountered a ConsistencyId value, on this page they will be incremental
1338 // So register the first value we encounter. We will pass this in when we re-create this page
1340 if ((LocalTags
->Tags
[BackupIndex
].ConsistencyId
!= 0) && (ConsistencyId
== 0)) {
1341 ConsistencyId
= (UINT16
) (LocalTags
->Tags
[BackupIndex
].ConsistencyId
- 1);
1347 // Delete the buffer associated with previous dynamic page
1348 // We will re-allocate a buffer....
1350 FreePool (LocalTags
->Tags
);
1353 Buffer
= AllocateZeroPool (Length
);
1354 ASSERT (Buffer
!= NULL
);
1357 // Get the form that was updated by the callback
1368 // Ok, we have the new page.....now we must purge the old page and re-allocate
1369 // the tag page with the new data
1380 // return the Form Id, Text, and the File's FormTags structure
1382 *FormHandle
= LocalTags
->Tags
[0].Id
;
1383 *TitleToken
= LocalTags
->Tags
[0].Text
;
1384 *FormTags
= *LocalTags
;
1386 FormTags
->Tags
[0].CallbackHandle
= CallbackHandle
;
1387 CopyMem (&FormTags
->Tags
[0].GuidValue
, &TagGuid
, sizeof (EFI_GUID
));
1394 IN UI_MENU_OPTION
*Selection
,
1395 IN BOOLEAN Callback
,
1396 IN EFI_FILE_FORM_TAGS
*FileFormTagsHead
,
1397 IN UINT8
*CallbackData
1402 EFI_FORM_TAGS FormTags
;
1407 // Displays the Header and Footer borders
1409 DisplayPageFrame ();
1412 // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR
1414 ExtractFormHandle (Selection
, FileFormTagsHead
, 0, &FormHandle
, &TitleToken
, &FormTags
);
1416 Selection
= DisplayForm (Selection
, FormHandle
, TitleToken
, FormTags
, FileFormTagsHead
, CallbackData
);
1419 // If selection is null use the former selection
1421 if (Selection
== NULL
) {
1429 while (Selection
->Tags
!= NULL
) {
1430 if (Selection
->Previous
) {
1431 ExtractFormHandle (Selection
, FileFormTagsHead
, Selection
->FormId
, &FormHandle
, &TitleToken
, &FormTags
);
1434 // True if a hyperlink/jump is selected
1436 if (Selection
->ThisTag
->Operand
== EFI_IFR_REF_OP
&& Selection
->ThisTag
->Id
!= 0x0000) {
1437 if (Selection
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) {
1438 ExtractDynamicFormHandle (
1442 Selection
->ThisTag
->Id
,
1449 ExtractFormHandle (Selection
, FileFormTagsHead
, Selection
->ThisTag
->Id
, &FormHandle
, &TitleToken
, &FormTags
);
1454 if ((Selection
->ThisTag
->Flags
& EFI_IFR_FLAG_INTERACTIVE
) &&
1455 (Selection
->ThisTag
->Operand
!= EFI_IFR_PASSWORD_OP
)
1457 ExtractDynamicFormHandle (
1467 ExtractFormHandle (Selection
, FileFormTagsHead
, Selection
->FormId
, &FormHandle
, &TitleToken
, &FormTags
);
1473 // Displays the Header and Footer borders
1475 DisplayPageFrame ();
1477 Selection
= DisplayForm (Selection
, FormHandle
, TitleToken
, FormTags
, FileFormTagsHead
, CallbackData
);
1479 if (Selection
== NULL
) {