Port DriverSample.inf, HiiDatabase.inf and SetupBrowser.inf
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / SetupBrowserDxe / Presentation.c
1 /*++
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
7
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.
10
11 Module Name:
12 Presentation.c
13
14 Abstract:
15
16 Some presentation routines.
17
18 Revision History:
19
20 --*/
21
22 //
23 // Include common header file for this module.
24 //
25 #include "CommonHeader.h"
26
27 #include "Setup.h"
28 #include "Ui.h"
29 #include "Colors.h"
30
31 VOID
32 ClearLines (
33 UINTN LeftColumn,
34 UINTN RightColumn,
35 UINTN TopRow,
36 UINTN BottomRow,
37 UINTN TextAttribute
38 )
39 {
40 CHAR16 *Buffer;
41 UINTN Row;
42
43 //
44 // For now, allocate an arbitrarily long buffer
45 //
46 Buffer = AllocateZeroPool (0x10000);
47 ASSERT (Buffer != NULL);
48
49 //
50 // Set foreground and background as defined
51 //
52 gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
53
54 //
55 // Much faster to buffer the long string instead of print it a character at a time
56 //
57 SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
58
59 //
60 // Clear the desired area with the appropriate foreground/background
61 //
62 for (Row = TopRow; Row <= BottomRow; Row++) {
63 PrintStringAt (LeftColumn, Row, Buffer);
64 }
65
66 gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
67
68 FreePool (Buffer);
69 return ;
70 }
71
72 VOID
73 NewStrCat (
74 CHAR16 *Destination,
75 CHAR16 *Source
76 )
77 {
78 UINTN Length;
79
80 for (Length = 0; Destination[Length] != 0; Length++)
81 ;
82
83 //
84 // We now have the length of the original string
85 // We can safely assume for now that we are concatenating a narrow value to this string.
86 // For instance, the string is "XYZ" and cat'ing ">"
87 // If this assumption changes, we need to make this routine a bit more complex
88 //
89 Destination[Length] = (CHAR16) NARROW_CHAR;
90 Length++;
91
92 StrCpy (Destination + Length, Source);
93 }
94
95 UINTN
96 GetStringWidth (
97 CHAR16 *String
98 )
99 {
100 UINTN Index;
101 UINTN Count;
102 UINTN IncrementValue;
103
104 Index = 0;
105 Count = 0;
106 IncrementValue = 1;
107
108 do {
109 //
110 // Advance to the null-terminator or to the first width directive
111 //
112 for (;
113 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
114 Index++, Count = Count + IncrementValue
115 )
116 ;
117
118 //
119 // We hit the null-terminator, we now have a count
120 //
121 if (String[Index] == 0) {
122 break;
123 }
124 //
125 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
126 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
127 //
128 if (String[Index] == NARROW_CHAR) {
129 //
130 // Skip to the next character
131 //
132 Index++;
133 IncrementValue = 1;
134 } else {
135 //
136 // Skip to the next character
137 //
138 Index++;
139 IncrementValue = 2;
140 }
141 } while (String[Index] != 0);
142
143 //
144 // Increment by one to include the null-terminator in the size
145 //
146 Count++;
147
148 return Count * sizeof (CHAR16);
149 }
150
151 VOID
152 DisplayPageFrame (
153 VOID
154 )
155 {
156 UINTN Index;
157 UINT8 Line;
158 UINT8 Alignment;
159 CHAR16 Character;
160 CHAR16 *Buffer;
161 CHAR16 *StrFrontPageBanner;
162 EFI_SCREEN_DESCRIPTOR LocalScreen;
163 UINTN Row;
164
165 ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
166 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
167 ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
168
169 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
170
171 //
172 // For now, allocate an arbitrarily long buffer
173 //
174 Buffer = AllocateZeroPool (0x10000);
175 ASSERT (Buffer != NULL);
176
177 Character = (CHAR16) BOXDRAW_HORIZONTAL;
178
179 for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
180 Buffer[Index] = Character;
181 }
182
183 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
184 //
185 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
186 //
187 ClearLines (
188 LocalScreen.LeftColumn,
189 LocalScreen.RightColumn,
190 LocalScreen.TopRow,
191 FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
192 BANNER_TEXT | BANNER_BACKGROUND
193 );
194 //
195 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
196 //
197 for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
198 //
199 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
200 //
201 for (Alignment = (UINT8) LocalScreen.LeftColumn;
202 Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
203 Alignment++
204 ) {
205 if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
206 StrFrontPageBanner = GetToken (
207 BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
208 FrontPageHandle
209 );
210 } else {
211 continue;
212 }
213
214 switch (Alignment - LocalScreen.LeftColumn) {
215 case 0:
216 //
217 // Handle left column
218 //
219 PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
220 break;
221
222 case 1:
223 //
224 // Handle center column
225 //
226 PrintStringAt (
227 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
228 Line,
229 StrFrontPageBanner
230 );
231 break;
232
233 case 2:
234 //
235 // Handle right column
236 //
237 PrintStringAt (
238 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
239 Line,
240 StrFrontPageBanner
241 );
242 break;
243 }
244
245 FreePool (StrFrontPageBanner);
246 }
247 }
248 }
249
250 ClearLines (
251 LocalScreen.LeftColumn,
252 LocalScreen.RightColumn,
253 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
254 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
255 KEYHELP_TEXT | KEYHELP_BACKGROUND
256 );
257
258 if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
259 ClearLines (
260 LocalScreen.LeftColumn,
261 LocalScreen.RightColumn,
262 LocalScreen.TopRow,
263 LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
264 TITLE_TEXT | TITLE_BACKGROUND
265 );
266 //
267 // Print Top border line
268 // +------------------------------------------------------------------------------+
269 // ? ?
270 // +------------------------------------------------------------------------------+
271 //
272 Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
273
274 PrintChar (Character);
275 PrintString (Buffer);
276
277 Character = (CHAR16) BOXDRAW_DOWN_LEFT;
278 PrintChar (Character);
279
280 Character = (CHAR16) BOXDRAW_VERTICAL;
281 for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
282 PrintCharAt (LocalScreen.LeftColumn, Row, Character);
283 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
284 }
285
286 Character = (CHAR16) BOXDRAW_UP_RIGHT;
287 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
288 PrintString (Buffer);
289
290 Character = (CHAR16) BOXDRAW_UP_LEFT;
291 PrintChar (Character);
292
293 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
294 //
295 // Print Bottom border line
296 // +------------------------------------------------------------------------------+
297 // ? ?
298 // +------------------------------------------------------------------------------+
299 //
300 Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
301 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
302
303 PrintString (Buffer);
304
305 Character = (CHAR16) BOXDRAW_DOWN_LEFT;
306 PrintChar (Character);
307 Character = (CHAR16) BOXDRAW_VERTICAL;
308 for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
309 Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
310 Row++
311 ) {
312 PrintCharAt (LocalScreen.LeftColumn, Row, Character);
313 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
314 }
315
316 Character = (CHAR16) BOXDRAW_UP_RIGHT;
317 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
318
319 PrintString (Buffer);
320
321 Character = (CHAR16) BOXDRAW_UP_LEFT;
322 PrintChar (Character);
323 }
324 }
325
326 FreePool (Buffer);
327
328 }
329
330 /*
331 +------------------------------------------------------------------------------+
332 ?F2=Previous Page Setup Page ?
333 +------------------------------------------------------------------------------+
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 +------------------------------------------------------------------------------+
352 ?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
353 | ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
354 +------------------------------------------------------------------------------+
355 */
356 STATIC
357 UI_MENU_OPTION *
358 DisplayForm (
359 OUT UI_MENU_OPTION *Selection,
360 IN UINT16 FormHandle,
361 IN UINT16 TitleToken,
362 IN EFI_FORM_TAGS FormTags,
363 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
364 IN UINT8 *CallbackData
365 )
366 {
367 CHAR16 *StringPtr;
368 UINTN Index;
369 UINTN Count;
370 UINT16 MenuItemCount;
371 EFI_HII_HANDLE Handle;
372 UINT16 FormId;
373 STRING_REF String;
374 EFI_FILE_FORM_TAGS *FileFormTags;
375 BOOLEAN SuppressIf;
376 BOOLEAN Suppress;
377 BOOLEAN GrayOut;
378 BOOLEAN Conditional;
379 EFI_SCREEN_DESCRIPTOR LocalScreen;
380 UINT16 Width;
381 UINTN ArrayEntry;
382 CHAR16 *OutputString;
383
384 Handle = Selection->Handle;
385 FormId = 0;
386 String = 0;
387 MenuItemCount = 0;
388 ArrayEntry = 0;
389 OutputString = NULL;
390
391 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
392
393 //
394 // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need
395 //
396 if (Selection->Previous) {
397 Selection->Previous = FALSE;
398 } else {
399 UiFreeMenu ();
400 UiInitMenu ();
401 }
402
403 StringPtr = GetToken (TitleToken, Handle);
404
405 if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
406 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
407 PrintStringAt (
408 (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
409 LocalScreen.TopRow + 1,
410 StringPtr
411 );
412 }
413
414 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
415 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
416
417 //
418 // Display the infrastructure strings
419 //
420 if (!IsListEmpty (&gMenuList)) {
421 PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
422 }
423
424 PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
425 PrintStringAt (
426 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
427 LocalScreen.BottomRow - 4,
428 gFunctionNineString
429 );
430 PrintStringAt (
431 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
432 LocalScreen.BottomRow - 4,
433 gFunctionTenString
434 );
435 PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
436 PrintStringAt (
437 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
438 LocalScreen.BottomRow - 3,
439 gEscapeString
440 );
441 }
442 //
443 // Remove Buffer allocated for StringPtr after it has been used.
444 //
445 FreePool (StringPtr);
446
447 for (Index = 0; FormTags.Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
448 GrayOut = FALSE;
449 Suppress = FALSE;
450 SuppressIf = FALSE;
451 Conditional = FALSE;
452 FileFormTags = FileFormTagsHead;
453
454 if (FormTags.Tags[Index].Operand == EFI_IFR_FORM_OP) {
455 FormId = FormTags.Tags[Index].Id;
456 }
457 //
458 // This gives us visibility to the FileFormTags->NvRamMap to check things
459 // ActiveIfr is a global maintained by the menuing code to ensure that we
460 // are pointing to the correct formset's file data.
461 //
462 for (Count = 0; Count < gActiveIfr; Count++) {
463 FileFormTags = FileFormTags->NextFile;
464 }
465 //
466 // GrayoutIf [SuppressIf]
467 // <BOOLEANS>
468 // OpCode(s)
469 // EndIf
470 //
471 // SuppressIf [GrayoutIf]
472 // <BOOLEANS>
473 // OpCode(s)
474 // EndIf
475 //
476 Count = 0;
477
478 do {
479 switch (FormTags.Tags[Index].Operand) {
480 case EFI_IFR_SUPPRESS_IF_OP:
481 SuppressIf = TRUE;
482
483 case EFI_IFR_GRAYOUT_IF_OP:
484
485 Conditional = TRUE;
486
487 //
488 // Advance to the next op-code
489 //
490 Index++;
491
492 //
493 // We are now pointing to the beginning of the consistency checking. Let's fast forward
494 // through the AND/OR/NOT data to come up with some meaningful ID data.
495 //
496 for (;
497 FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
498 FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
499 FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
500 FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
501 FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP;
502 Index++
503 )
504 ;
505
506 //
507 // We need to walk through the consistency checks until we hit the end of the consistency
508 // FALSE means evaluate this single expression
509 // The ConsistencyId refers to which expression in the Consistency database to use
510 //
511 if (SuppressIf) {
512 Suppress = ValueIsNotValid (
513 FALSE,
514 FormTags.Tags[Index].ConsistencyId,
515 &FormTags.Tags[Index],
516 FileFormTags,
517 &String
518 );
519 SuppressIf = FALSE;
520 } else {
521 GrayOut = ValueIsNotValid (
522 FALSE,
523 FormTags.Tags[Index].ConsistencyId,
524 &FormTags.Tags[Index],
525 FileFormTags,
526 &String
527 );
528 }
529 //
530 // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected)
531 //
532 for (;
533 FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_VAL_OP ||
534 FormTags.Tags[Index].Operand == EFI_IFR_EQ_VAR_VAL_OP ||
535 FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_ID_OP ||
536 FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_LIST_OP ||
537 FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP ||
538 FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
539 FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
540 FormTags.Tags[Index].Operand == EFI_IFR_TRUE_OP ||
541 FormTags.Tags[Index].Operand == EFI_IFR_FALSE_OP ||
542 FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
543 FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
544 FormTags.Tags[Index].Operand == EFI_IFR_LABEL_OP;
545 Index++
546 )
547 ;
548 break;
549
550 default:
551 goto GetOut;
552 }
553 //
554 // Do this two times (at most will see a suppress and grayout combination
555 //
556 Count++;
557 } while (Count < 2);
558
559 GetOut:
560 do {
561 if (GrayOut) {
562 FormTags.Tags[Index].GrayOut = TRUE;
563 } else {
564 FormTags.Tags[Index].GrayOut = FALSE;
565 }
566 if (Suppress && FormTags.Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
567 //
568 // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly.
569 //
570 FormTags.Tags[Index].Suppress = TRUE;
571 } else {
572 FormTags.Tags[Index].Suppress = FALSE;
573 }
574
575 if ((
576 FormTags.Tags[Index].NumberOfLines > 0 ||
577 FormTags.Tags[Index].Operand == EFI_IFR_DATE_OP ||
578 FormTags.Tags[Index].Operand == EFI_IFR_TIME_OP
579 ) &&
580 !Suppress
581 ) {
582
583 StringPtr = GetToken (FormTags.Tags[Index].Text, Handle);
584
585 Width = GetWidth (&FormTags.Tags[Index], Handle);
586
587 //
588 // This data can be retrieved over and over again. Therefore, reset to original values
589 // before processing otherwise things will start growing linearly
590 //
591 if (FormTags.Tags[Index].NumberOfLines > 1) {
592 FormTags.Tags[Index].NumberOfLines = 1;
593 }
594
595 for (Count = 0; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
596 //
597 // If there is more string to process print on the next row and increment the Skip value
598 //
599 if (StrLen (&StringPtr[ArrayEntry])) {
600 FormTags.Tags[Index].NumberOfLines++;
601 }
602
603 FreePool (OutputString);
604 }
605
606 ArrayEntry = 0;
607
608 //
609 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
610 // it in UiFreeMenu.
611 //
612 UiAddSubMenuOption (StringPtr, Handle, FormTags.Tags, Index, FormId, MenuItemCount);
613 MenuItemCount++;
614 }
615 //
616 // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if
617 //
618 Index++;
619 } while (FormTags.Tags[Index].Operand != EFI_IFR_END_IF_OP && Conditional);
620
621 //
622 // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic
623 //
624 Index--;
625 }
626
627 Selection = UiDisplayMenu (TRUE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
628
629 return Selection;
630 }
631
632 VOID
633 InitializeBrowserStrings (
634 VOID
635 )
636 {
637 gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
638 gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
639 gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
640 gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
641 gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
642 gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
643 gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
644 gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
645 gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
646 gNumericInput = GetToken (STRING_TOKEN (NUMERIC_INPUT), gHiiHandle);
647 gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
648 gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
649 gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
650 gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
651 gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
652 gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
653 gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
654 gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
655 gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
656 gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
657 gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
658 gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
659 gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
660 gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
661 return ;
662 }
663
664 VOID
665 UpdateKeyHelp (
666 IN UI_MENU_OPTION *Selection,
667 IN BOOLEAN Selected
668 )
669 /*++
670 Routine Description:
671 Update key's help imformation
672
673 Arguments:
674 Selection C The form that current display
675 Selected C Whether or not a tag be selected
676
677 Returns:
678 None
679 --*/
680 {
681 UINTN SecCol;
682 UINTN ThdCol;
683 UINTN LeftColumnOfHelp;
684 UINTN RightColumnOfHelp;
685 UINTN TopRowOfHelp;
686 UINTN BottomRowOfHelp;
687 UINTN StartColumnOfHelp;
688 EFI_SCREEN_DESCRIPTOR LocalScreen;
689
690 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
691
692 SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
693 ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
694
695 StartColumnOfHelp = LocalScreen.LeftColumn + 2;
696 LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
697 RightColumnOfHelp = LocalScreen.RightColumn - 2;
698 TopRowOfHelp = LocalScreen.BottomRow - 4;
699 BottomRowOfHelp = LocalScreen.BottomRow - 3;
700
701 if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
702 return ;
703 }
704
705 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
706
707 switch (Selection->ThisTag->Operand) {
708 case EFI_IFR_ORDERED_LIST_OP:
709 case EFI_IFR_ONE_OF_OP:
710 case EFI_IFR_NUMERIC_OP:
711 case EFI_IFR_TIME_OP:
712 case EFI_IFR_DATE_OP:
713 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
714
715 if (!Selected) {
716 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
717 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
718 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
719 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
720 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
721
722 }
723
724 if ((Selection->ThisTag->Operand == EFI_IFR_DATE_OP) || (Selection->ThisTag->Operand == EFI_IFR_TIME_OP)) {
725 PrintAt (
726 StartColumnOfHelp,
727 BottomRowOfHelp,
728 (CHAR16 *) L"%c%c%c%c%s",
729 ARROW_UP,
730 ARROW_DOWN,
731 ARROW_RIGHT,
732 ARROW_LEFT,
733 gMoveHighlight
734 );
735 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
736 } else {
737 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
738 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
739 }
740 } else {
741 PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
742
743 //
744 // If it is a selected numeric with manual input, display different message
745 //
746 if ((Selection->ThisTag->Operand == EFI_IFR_NUMERIC_OP) && (Selection->ThisTag->Step == 0)) {
747 PrintStringAt (SecCol, TopRowOfHelp, gNumericInput);
748 } else if (Selection->ThisTag->Operand != EFI_IFR_ORDERED_LIST_OP) {
749 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
750 }
751
752 if (Selection->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {
753 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
754 PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
755 }
756
757 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
758 }
759 break;
760
761 case EFI_IFR_CHECKBOX_OP:
762 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
763
764 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
765 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
766 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
767 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
768 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
769 }
770
771 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
772 PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
773 break;
774
775 case EFI_IFR_REF_OP:
776 case EFI_IFR_PASSWORD_OP:
777 case EFI_IFR_STRING_OP:
778 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
779
780 if (!Selected) {
781 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
782 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
783 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
784 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
785 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
786 }
787
788 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
789 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
790 } else {
791 if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
792 PrintStringAt (
793 (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
794 BottomRowOfHelp,
795 gEnterCommitString
796 );
797 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
798 }
799 }
800 break;
801 }
802
803 }
804
805 STATIC
806 VOID
807 ExtractFormHandle (
808 IN UI_MENU_OPTION *Selection,
809 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
810 IN UINTN IdValue,
811 OUT UINT16 *FormHandle,
812 OUT UINT16 *TitleToken,
813 OUT EFI_FORM_TAGS *FormTags
814 )
815 {
816 UINTN Index;
817 EFI_FILE_FORM_TAGS *FileFormTags;
818 EFI_FORM_TAGS LocalTags;
819
820 FileFormTags = FileFormTagsHead;
821
822 //
823 // Advance FileFormTags to the correct file's tag information.
824 // For instance, if Selection->IfrNumber is 3, that means the 4th
825 // file (0-based) in the FileFormTags linked-list contains the tag
826 // information.
827 //
828 for (Index = 0; Index < Selection->IfrNumber; Index++) {
829 FileFormTags = FileFormTags->NextFile;
830 }
831
832 LocalTags = FileFormTags->FormTags;
833
834 if (IdValue == 0) {
835 //
836 // Advance Index to the first FormOp tag information
837 //
838 for (Index = 0; FileFormTags->FormTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
839 ;
840 } else {
841 //
842 // Advance Index to the FormOp with the correct ID value
843 //
844 for (; LocalTags.Next != NULL; LocalTags = *LocalTags.Next) {
845 for (Index = 0; LocalTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
846 ;
847 if (LocalTags.Tags[Index].Id == IdValue) {
848 break;
849 }
850 }
851 }
852 //
853 // return the Form Id, Text, and the File's FormTags structure
854 //
855 *FormHandle = LocalTags.Tags[Index].Id;
856 *TitleToken = LocalTags.Tags[Index].Text;
857 *FormTags = LocalTags;
858 return ;
859 }
860
861 STATIC
862 EFI_STATUS
863 UpdateNewTagData (
864 IN UINT8 *FormData,
865 IN UINT16 ConsistencyId,
866 IN UINT16 CurrentVariable,
867 IN EFI_FORM_TAGS *FormTags,
868 OUT EFI_FILE_FORM_TAGS *FileFormTags
869 )
870 {
871 EFI_STATUS Status;
872 UINT16 Index;
873 UINT16 QuestionIndex;
874 UINT16 NumberOfTags;
875 INT16 CurrTag;
876 UINT8 TagLength;
877 UINTN Count;
878 BOOLEAN Finished;
879
880 //
881 // Initialize some Index variable and Status
882 //
883 Count = 0;
884 QuestionIndex = 0;
885 NumberOfTags = 1;
886 Index = 0;
887 Status = EFI_SUCCESS;
888 Finished = FALSE;
889
890 //
891 // Determine the number of tags for the first form
892 //
893 GetTagCount (&FormData[Index], &NumberOfTags);
894
895 //
896 // Allocate memory for our tags on the first form
897 //
898 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
899 ASSERT (FormTags->Tags != NULL);
900
901 for (CurrTag = 0; FormData[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
902 //
903 // Operand = IFR OpCode
904 //
905 FormTags->Tags[CurrTag].Operand = FormData[Index];
906
907 //
908 // Assume for now 0 lines occupied by this OpCode
909 //
910 FormTags->Tags[CurrTag].NumberOfLines = 0;
911
912 //
913 // Determine the length of the Tag so we can later skip to the next tag in the form
914 //
915 //
916 // get the length
917 //
918 TagLength = FormData[Index + 1];
919 //
920 // Operate on the Found OpCode
921 //
922 switch (FormData[Index]) {
923
924 case EFI_IFR_FORM_OP:
925 case EFI_IFR_SUBTITLE_OP:
926 case EFI_IFR_TEXT_OP:
927 case EFI_IFR_REF_OP:
928 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
929 break;
930
931 case EFI_IFR_VARSTORE_SELECT_OP:
932 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
933 CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &FormData[Index])->VarId, sizeof (UINT16));
934 break;
935
936 case EFI_IFR_END_FORM_OP:
937 FormTags->Tags[CurrTag].Operand = FormData[Index];
938 FormTags->Tags[CurrTag].NumberOfLines = 0;
939
940 Finished = TRUE;
941 break;
942
943 case EFI_IFR_ORDERED_LIST_OP:
944 case EFI_IFR_ONE_OF_OP:
945 GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
946
947 //
948 // Store away the CurrTag since what follows will be the answer that we
949 // need to place into the appropriate location in the tag array
950 //
951 //
952 // record for setting default later
953 //
954 QuestionIndex = (UINT16) CurrTag;
955 break;
956
957 case EFI_IFR_ONE_OF_OPTION_OP:
958 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
959 FormTags->Tags[QuestionIndex].Key = ((EFI_IFR_ONE_OF_OPTION *) &FormData[Index])->Key;
960 FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
961 break;
962
963 case EFI_IFR_CHECKBOX_OP:
964 GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
965 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
966 break;
967
968 case EFI_IFR_NUMERIC_OP:
969 GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
970 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
971 break;
972
973 case EFI_IFR_DATE_OP:
974 //
975 // Date elements come in as a Year, Month, Day. We need to process them as a country-based
976 // Order. It is much easier to do it here than anywhere else.
977 //
978 // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2
979 //
980 GetNumericHeader (
981 &FormTags->Tags[CurrTag],
982 FormData,
983 (UINT16) (Index + TagLength),
984 (UINT16) 0,
985 FileFormTags,
986 CurrentVariable
987 );
988
989 //
990 // The current language selected + the Date operand
991 //
992 FormTags->Tags[CurrTag + 1].Operand = FormData[Index];
993 GetNumericHeader (
994 &FormTags->Tags[CurrTag + 1],
995 FormData,
996 (UINT16) (Index + TagLength + FormData[Index + TagLength + 1]),
997 (UINT16) 0,
998 FileFormTags,
999 CurrentVariable
1000 );
1001
1002 //
1003 // The current language selected + the Date operand
1004 //
1005 FormTags->Tags[CurrTag + 2].Operand = FormData[Index];
1006 GetNumericHeader (&FormTags->Tags[CurrTag + 2], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1007
1008 CurrTag = (INT16) (CurrTag + 2);
1009
1010 Index = (UINT16) (Index + TagLength);
1011 //
1012 // get the length
1013 //
1014 TagLength = FormData[Index + 1];
1015 Index = (UINT16) (Index + TagLength);
1016 //
1017 // get the length
1018 //
1019 TagLength = FormData[Index + 1];
1020 break;
1021
1022 case EFI_IFR_TIME_OP:
1023 GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 0, FileFormTags, CurrentVariable);
1024
1025 if (Count == 2) {
1026 //
1027 // Override the GetQuestionHeader information - date/time are treated very differently
1028 //
1029 FormTags->Tags[CurrTag].NumberOfLines = 1;
1030 Count = 0;
1031 } else {
1032 //
1033 // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
1034 // associated with them, and the third has 1 line to allow to space beyond the choice.
1035 //
1036 Count++;
1037 }
1038 break;
1039
1040 case EFI_IFR_PASSWORD_OP:
1041 case EFI_IFR_STRING_OP:
1042 GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
1043 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1044 break;
1045
1046 case EFI_IFR_INCONSISTENT_IF_OP:
1047 case EFI_IFR_SUPPRESS_IF_OP:
1048 case EFI_IFR_GRAYOUT_IF_OP:
1049 ConsistencyId++;
1050 break;
1051
1052 case EFI_IFR_EQ_ID_VAL_OP:
1053 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1054 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1055 break;
1056
1057 case EFI_IFR_EQ_VAR_VAL_OP:
1058 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1059 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1060 break;
1061
1062 case EFI_IFR_EQ_ID_ID_OP:
1063 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1064 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1065 break;
1066
1067 case EFI_IFR_AND_OP:
1068 case EFI_IFR_OR_OP:
1069 case EFI_IFR_NOT_OP:
1070 case EFI_IFR_TRUE_OP:
1071 case EFI_IFR_FALSE_OP:
1072 case EFI_IFR_GT_OP:
1073 case EFI_IFR_GE_OP:
1074 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1075 break;
1076
1077 case EFI_IFR_EQ_ID_LIST_OP:
1078 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1079
1080 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1081 break;
1082
1083 default:
1084 break;
1085 }
1086 //
1087 // End of switch
1088 //
1089 if (Finished) {
1090 break;
1091 }
1092 //
1093 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1094 //
1095 Index = (UINT16) (Index + TagLength);
1096 }
1097 //
1098 // End of Index
1099 //
1100 return Status;
1101 }
1102
1103 STATIC
1104 VOID
1105 ExtractDynamicFormHandle (
1106 IN UI_MENU_OPTION *Selection,
1107 IN UINT8 *CallbackData,
1108 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1109 IN UINTN IdValue,
1110 OUT UINT16 *FormHandle,
1111 OUT UINT16 *TitleToken,
1112 OUT EFI_FORM_TAGS *FormTags
1113 )
1114 /*++
1115
1116 Routine Description:
1117
1118 The function does the most of the works when the EFI_TAG that
1119 user selects on is EFI_IFR_FLAG_INTERACTIVE or EFI_IFR_PASSWORD_OP:
1120 invoke CallBack, update the new form data.
1121
1122 Arguments:
1123
1124 Selection - The current selection of the form.
1125 CallbackData - The pointer to host the data passed back by the callback function.
1126 FileFormTagsHead - Prompt string token of the one-of box
1127 IdValue - The current page number.
1128 FormHandle - Output the the handle of the form.
1129 TitleToken - Output the TitleToken of the new page.
1130 FormTags - Output the FormFags of the new page.
1131
1132 Returns:
1133 VOID
1134
1135 --*/
1136 {
1137 UINTN Index;
1138 UINTN BackupIndex;
1139 EFI_FILE_FORM_TAGS *FileFormTags;
1140 EFI_FORM_TAGS *LocalTags;
1141 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
1142 EFI_STATUS Status;
1143 UINTN Length;
1144 UINT8 *Buffer;
1145 EFI_PHYSICAL_ADDRESS CallbackHandle;
1146 EFI_GUID TagGuid;
1147 UINT16 TargetPage;
1148 EFI_HII_CALLBACK_PACKET *Packet;
1149 UINTN ScreenSize;
1150 CHAR16 NullCharacter;
1151 EFI_INPUT_KEY Key;
1152 UINT16 ConsistencyId;
1153 UINT16 CurrentVariable;
1154 EFI_VARIABLE_DEFINITION *VariableDefinition;
1155 EFI_IFR_DATA_ENTRY *DataEntry;
1156
1157 VariableDefinition = NULL;
1158 NullCharacter = CHAR_NULL;
1159
1160 CurrentVariable = 0;
1161 FileFormTags = FileFormTagsHead;
1162 Length = 0;
1163 CallbackHandle = 0;
1164 TargetPage = (UINT16) IdValue;
1165 Packet = NULL;
1166 ConsistencyId = 0;
1167
1168 //
1169 // Advance FileFormTags to the correct file's tag information.
1170 // For instance, if Selection->IfrNumber is 3, that means the 4th
1171 // file (0-based) in the FileFormTags linked-list contains the tag
1172 // information.
1173 //
1174 for (Index = 0; Index < Selection->IfrNumber; Index++) {
1175 FileFormTags = FileFormTags->NextFile;
1176 }
1177
1178 LocalTags = &FileFormTags->FormTags;
1179
1180 //
1181 // Advance Index to the FormOp with the correct ID value
1182 //
1183 for (; LocalTags->Next != NULL; LocalTags = LocalTags->Next) {
1184 if ((LocalTags->Tags[0].CallbackHandle != 0) && (CallbackHandle == 0)) {
1185 CallbackHandle = LocalTags->Tags[0].CallbackHandle;
1186 CopyMem (&TagGuid, &LocalTags->Tags[0].GuidValue, sizeof (EFI_GUID));
1187 }
1188
1189 for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
1190 ;
1191 if (LocalTags->Tags[Index].Id == IdValue) {
1192 break;
1193 }
1194 }
1195 //
1196 // If we are going to callback on a non-goto opcode, make sure we don't change pages
1197 //
1198 if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
1199 TargetPage = Selection->FormId;
1200 }
1201 //
1202 // The first tag below should be the form op-code. We need to store away the
1203 // current variable setting to ensure if we have to reload the page, that we
1204 // can correctly restore the values for the active variable
1205 //
1206 CurrentVariable = Selection->Tags[0].VariableNumber;
1207
1208 //
1209 // Remember that dynamic pages in an environment where all pages are not
1210 // dynamic require us to call back to the user to give them an opportunity
1211 // to register fresh information in the HII database so that we can extract it.
1212 //
1213 Status = gBS->HandleProtocol (
1214 (VOID *) (UINTN) CallbackHandle,
1215 &gEfiFormCallbackProtocolGuid,
1216 (VOID **) &FormCallback
1217 );
1218
1219 if (EFI_ERROR (Status)) {
1220 FreePool (LocalTags->Tags);
1221 return ;
1222 }
1223
1224 ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition);
1225
1226 if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) {
1227 ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap;
1228 } else {
1229 ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL;
1230 }
1231
1232 if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
1233 Status = FormCallback->Callback (
1234 FormCallback,
1235 Selection->ThisTag->Key,
1236 (EFI_IFR_DATA_ARRAY *) CallbackData,
1237 &Packet
1238 );
1239 }
1240
1241 if (EFI_ERROR (Status)) {
1242 //
1243 // Restore Previous Value
1244 //
1245 CopyMem (
1246 &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
1247 gPreviousValue,
1248 Selection->ThisTag->StorageWidth
1249 );
1250
1251 if (Packet != NULL) {
1252 //
1253 // Upon error, we will likely receive a string to print out
1254 //
1255 ScreenSize = GetStringWidth (Packet->String) / 2;
1256
1257 //
1258 // Display error popup
1259 //
1260 CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter);
1261
1262 do {
1263 Status = WaitForKeyStroke (&Key);
1264 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1265 } else {
1266 UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE);
1267 }
1268
1269 } else {
1270 if (Packet != NULL) {
1271 //
1272 // We need to on a non-error, look in the outbound Packet for information and update the NVRAM
1273 // location associated with the op-code specified there. This is used on single op-code instances
1274 // and not for when a hyperlink sent us a whole page of data.
1275 //
1276 DataEntry = (EFI_IFR_DATA_ENTRY *) (&Packet->DataArray + 1);
1277 if (Packet->DataArray.EntryCount == 1) {
1278 switch (DataEntry->OpCode) {
1279 case EFI_IFR_STRING_OP:
1280 case EFI_IFR_NUMERIC_OP:
1281 case EFI_IFR_ORDERED_LIST_OP:
1282 case EFI_IFR_ONE_OF_OP:
1283 case EFI_IFR_CHECKBOX_OP:
1284 CopyMem (
1285 &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
1286 &DataEntry->Data,
1287 Selection->ThisTag->StorageWidth
1288 );
1289 break;
1290
1291 case EFI_IFR_NV_ACCESS_COMMAND:
1292 CopyMem (
1293 &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId],
1294 ((EFI_IFR_NV_DATA *) Packet) + 1,
1295 ((EFI_IFR_NV_DATA *) Packet)->StorageWidth
1296 );
1297 break;
1298
1299 }
1300
1301 if (DataEntry->Flags & RESET_REQUIRED) {
1302 gResetRequired = TRUE;
1303 }
1304
1305 if (DataEntry->Flags & EXIT_REQUIRED) {
1306 gExitRequired = TRUE;
1307 }
1308
1309 if (DataEntry->Flags & SAVE_REQUIRED) {
1310 gSaveRequired = TRUE;
1311 }
1312
1313 if (DataEntry->Flags & NV_CHANGED) {
1314 gNvUpdateRequired = TRUE;
1315 }
1316
1317 if (DataEntry->Flags & NV_NOT_CHANGED) {
1318 gNvUpdateRequired = FALSE;
1319 }
1320 }
1321 }
1322 }
1323
1324 if (Packet != NULL) {
1325 FreePool (Packet);
1326 }
1327
1328 for (BackupIndex = 0; LocalTags->Tags[BackupIndex].Operand != EFI_IFR_END_FORM_OP; BackupIndex++) {
1329 switch (LocalTags->Tags[BackupIndex].Operand) {
1330 case EFI_IFR_EQ_VAR_VAL_OP:
1331 case EFI_IFR_EQ_ID_VAL_OP:
1332 case EFI_IFR_EQ_ID_ID_OP:
1333 case EFI_IFR_AND_OP:
1334 case EFI_IFR_OR_OP:
1335 case EFI_IFR_NOT_OP:
1336 case EFI_IFR_TRUE_OP:
1337 case EFI_IFR_FALSE_OP:
1338 case EFI_IFR_GT_OP:
1339 case EFI_IFR_GE_OP:
1340 case EFI_IFR_EQ_ID_LIST_OP:
1341 //
1342 // If we encountered a ConsistencyId value, on this page they will be incremental
1343 // So register the first value we encounter. We will pass this in when we re-create this page
1344 //
1345 if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) {
1346 ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1);
1347 }
1348 break;
1349 }
1350 }
1351 //
1352 // Delete the buffer associated with previous dynamic page
1353 // We will re-allocate a buffer....
1354 //
1355 FreePool (LocalTags->Tags);
1356
1357 Length = 0xF000;
1358 Buffer = AllocateZeroPool (Length);
1359 ASSERT (Buffer != NULL);
1360
1361 //
1362 // Get the form that was updated by the callback
1363 //
1364 Hii->GetForms (
1365 Hii,
1366 Selection->Handle,
1367 TargetPage,
1368 &Length,
1369 Buffer
1370 );
1371
1372 //
1373 // Ok, we have the new page.....now we must purge the old page and re-allocate
1374 // the tag page with the new data
1375 //
1376 UpdateNewTagData (
1377 Buffer,
1378 ConsistencyId,
1379 CurrentVariable,
1380 LocalTags,
1381 FileFormTags
1382 );
1383
1384 //
1385 // return the Form Id, Text, and the File's FormTags structure
1386 //
1387 *FormHandle = LocalTags->Tags[0].Id;
1388 *TitleToken = LocalTags->Tags[0].Text;
1389 *FormTags = *LocalTags;
1390
1391 FormTags->Tags[0].CallbackHandle = CallbackHandle;
1392 CopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID));
1393
1394 return ;
1395 }
1396
1397 UI_MENU_OPTION *
1398 SetupBrowser (
1399 IN UI_MENU_OPTION *Selection,
1400 IN BOOLEAN Callback,
1401 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1402 IN UINT8 *CallbackData
1403 )
1404 {
1405 UINT16 FormHandle;
1406 UINT16 TitleToken;
1407 EFI_FORM_TAGS FormTags;
1408
1409 gEntryNumber = -1;
1410 gLastOpr = FALSE;
1411 //
1412 // Displays the Header and Footer borders
1413 //
1414 DisplayPageFrame ();
1415
1416 //
1417 // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR
1418 //
1419 ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags);
1420
1421 Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
1422
1423 //
1424 // If selection is null use the former selection
1425 //
1426 if (Selection == NULL) {
1427 return Selection;
1428 }
1429
1430 if (Callback) {
1431 return Selection;
1432 }
1433
1434 while (Selection->Tags != NULL) {
1435 if (Selection->Previous) {
1436 ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
1437 } else {
1438 //
1439 // True if a hyperlink/jump is selected
1440 //
1441 if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) {
1442 if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
1443 ExtractDynamicFormHandle (
1444 Selection,
1445 CallbackData,
1446 FileFormTagsHead,
1447 Selection->ThisTag->Id,
1448 &FormHandle,
1449 &TitleToken,
1450 &FormTags
1451 );
1452 goto DisplayPage;
1453 } else {
1454 ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags);
1455 goto DisplayPage;
1456 }
1457 }
1458
1459 if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) &&
1460 (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP)
1461 ) {
1462 ExtractDynamicFormHandle (
1463 Selection,
1464 CallbackData,
1465 FileFormTagsHead,
1466 Selection->FormId,
1467 &FormHandle,
1468 &TitleToken,
1469 &FormTags
1470 );
1471 } else {
1472 ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
1473 }
1474 }
1475
1476 DisplayPage:
1477 //
1478 // Displays the Header and Footer borders
1479 //
1480 DisplayPageFrame ();
1481
1482 Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
1483
1484 if (Selection == NULL) {
1485 break;
1486 }
1487 };
1488
1489 return Selection;
1490 }