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