]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Presentation.c
Modules cleanup.
[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 #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 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 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 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 STATIC
352 UI_MENU_OPTION *
353 DisplayForm (
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
360 )
361 {
362 CHAR16 *StringPtr;
363 UINTN Index;
364 UINTN Count;
365 UINT16 MenuItemCount;
366 EFI_HII_HANDLE Handle;
367 UINT16 FormId;
368 STRING_REF String;
369 EFI_FILE_FORM_TAGS *FileFormTags;
370 BOOLEAN SuppressIf;
371 BOOLEAN Suppress;
372 BOOLEAN GrayOut;
373 BOOLEAN Conditional;
374 EFI_SCREEN_DESCRIPTOR LocalScreen;
375 UINT16 Width;
376 UINTN ArrayEntry;
377 CHAR16 *OutputString;
378
379 Handle = Selection->Handle;
380 FormId = 0;
381 String = 0;
382 MenuItemCount = 0;
383 ArrayEntry = 0;
384 OutputString = NULL;
385
386 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
387
388 //
389 // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need
390 //
391 if (Selection->Previous) {
392 Selection->Previous = FALSE;
393 } else {
394 UiFreeMenu ();
395 UiInitMenu ();
396 }
397
398 StringPtr = GetToken (TitleToken, Handle);
399
400 if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
401 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
402 PrintStringAt (
403 (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
404 LocalScreen.TopRow + 1,
405 StringPtr
406 );
407 }
408
409 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
410 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
411
412 //
413 // Display the infrastructure strings
414 //
415 if (!IsListEmpty (&gMenuList)) {
416 PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
417 }
418
419 PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
420 PrintStringAt (
421 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
422 LocalScreen.BottomRow - 4,
423 gFunctionNineString
424 );
425 PrintStringAt (
426 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
427 LocalScreen.BottomRow - 4,
428 gFunctionTenString
429 );
430 PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
431 PrintStringAt (
432 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
433 LocalScreen.BottomRow - 3,
434 gEscapeString
435 );
436 }
437 //
438 // Remove Buffer allocated for StringPtr after it has been used.
439 //
440 FreePool (StringPtr);
441
442 for (Index = 0; FormTags.Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
443 GrayOut = FALSE;
444 Suppress = FALSE;
445 SuppressIf = FALSE;
446 Conditional = FALSE;
447 FileFormTags = FileFormTagsHead;
448
449 if (FormTags.Tags[Index].Operand == EFI_IFR_FORM_OP) {
450 FormId = FormTags.Tags[Index].Id;
451 }
452 //
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.
456 //
457 for (Count = 0; Count < gActiveIfr; Count++) {
458 FileFormTags = FileFormTags->NextFile;
459 }
460 //
461 // GrayoutIf [SuppressIf]
462 // <BOOLEANS>
463 // OpCode(s)
464 // EndIf
465 //
466 // SuppressIf [GrayoutIf]
467 // <BOOLEANS>
468 // OpCode(s)
469 // EndIf
470 //
471 Count = 0;
472
473 do {
474 switch (FormTags.Tags[Index].Operand) {
475 case EFI_IFR_SUPPRESS_IF_OP:
476 SuppressIf = TRUE;
477
478 case EFI_IFR_GRAYOUT_IF_OP:
479
480 Conditional = TRUE;
481
482 //
483 // Advance to the next op-code
484 //
485 Index++;
486
487 //
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.
490 //
491 for (;
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;
497 Index++
498 )
499 ;
500
501 //
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
505 //
506 if (SuppressIf) {
507 Suppress = ValueIsNotValid (
508 FALSE,
509 FormTags.Tags[Index].ConsistencyId,
510 &FormTags.Tags[Index],
511 FileFormTags,
512 &String
513 );
514 SuppressIf = FALSE;
515 } else {
516 GrayOut = ValueIsNotValid (
517 FALSE,
518 FormTags.Tags[Index].ConsistencyId,
519 &FormTags.Tags[Index],
520 FileFormTags,
521 &String
522 );
523 }
524 //
525 // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected)
526 //
527 for (;
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;
540 Index++
541 )
542 ;
543 break;
544
545 default:
546 goto GetOut;
547 }
548 //
549 // Do this two times (at most will see a suppress and grayout combination
550 //
551 Count++;
552 } while (Count < 2);
553
554 GetOut:
555 do {
556 if (GrayOut) {
557 FormTags.Tags[Index].GrayOut = TRUE;
558 } else {
559 FormTags.Tags[Index].GrayOut = FALSE;
560 }
561 if (Suppress && FormTags.Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
562 //
563 // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly.
564 //
565 FormTags.Tags[Index].Suppress = TRUE;
566 } else {
567 FormTags.Tags[Index].Suppress = FALSE;
568 }
569
570 if ((
571 FormTags.Tags[Index].NumberOfLines > 0 ||
572 FormTags.Tags[Index].Operand == EFI_IFR_DATE_OP ||
573 FormTags.Tags[Index].Operand == EFI_IFR_TIME_OP
574 ) &&
575 !Suppress
576 ) {
577
578 StringPtr = GetToken (FormTags.Tags[Index].Text, Handle);
579
580 Width = GetWidth (&FormTags.Tags[Index], Handle);
581
582 //
583 // This data can be retrieved over and over again. Therefore, reset to original values
584 // before processing otherwise things will start growing linearly
585 //
586 if (FormTags.Tags[Index].NumberOfLines > 1) {
587 FormTags.Tags[Index].NumberOfLines = 1;
588 }
589
590 for (Count = 0; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
591 //
592 // If there is more string to process print on the next row and increment the Skip value
593 //
594 if (StrLen (&StringPtr[ArrayEntry])) {
595 FormTags.Tags[Index].NumberOfLines++;
596 }
597
598 FreePool (OutputString);
599 }
600
601 ArrayEntry = 0;
602
603 //
604 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
605 // it in UiFreeMenu.
606 //
607 UiAddSubMenuOption (StringPtr, Handle, FormTags.Tags, Index, FormId, MenuItemCount);
608 MenuItemCount++;
609 }
610 //
611 // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if
612 //
613 Index++;
614 } while (FormTags.Tags[Index].Operand != EFI_IFR_END_IF_OP && Conditional);
615
616 //
617 // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic
618 //
619 Index--;
620 }
621
622 Selection = UiDisplayMenu (TRUE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
623
624 return Selection;
625 }
626
627 VOID
628 InitializeBrowserStrings (
629 VOID
630 )
631 {
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);
656 return ;
657 }
658
659 VOID
660 UpdateKeyHelp (
661 IN UI_MENU_OPTION *Selection,
662 IN BOOLEAN Selected
663 )
664 /*++
665 Routine Description:
666 Update key's help imformation
667
668 Arguments:
669 Selection C The form that current display
670 Selected C Whether or not a tag be selected
671
672 Returns:
673 None
674 --*/
675 {
676 UINTN SecCol;
677 UINTN ThdCol;
678 UINTN LeftColumnOfHelp;
679 UINTN RightColumnOfHelp;
680 UINTN TopRowOfHelp;
681 UINTN BottomRowOfHelp;
682 UINTN StartColumnOfHelp;
683 EFI_SCREEN_DESCRIPTOR LocalScreen;
684
685 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
686
687 SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
688 ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
689
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;
695
696 if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
697 return ;
698 }
699
700 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
701
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);
709
710 if (!Selected) {
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);
716
717 }
718
719 if ((Selection->ThisTag->Operand == EFI_IFR_DATE_OP) || (Selection->ThisTag->Operand == EFI_IFR_TIME_OP)) {
720 PrintAt (
721 StartColumnOfHelp,
722 BottomRowOfHelp,
723 (CHAR16 *) L"%c%c%c%c%s",
724 ARROW_UP,
725 ARROW_DOWN,
726 ARROW_RIGHT,
727 ARROW_LEFT,
728 gMoveHighlight
729 );
730 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
731 } else {
732 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
733 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
734 }
735 } else {
736 PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
737
738 //
739 // If it is a selected numeric with manual input, display different message
740 //
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);
745 }
746
747 if (Selection->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {
748 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
749 PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
750 }
751
752 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
753 }
754 break;
755
756 case EFI_IFR_CHECKBOX_OP:
757 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
758
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);
764 }
765
766 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
767 PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
768 break;
769
770 case EFI_IFR_REF_OP:
771 case EFI_IFR_PASSWORD_OP:
772 case EFI_IFR_STRING_OP:
773 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
774
775 if (!Selected) {
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);
781 }
782
783 PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
784 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
785 } else {
786 if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
787 PrintStringAt (
788 (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
789 BottomRowOfHelp,
790 gEnterCommitString
791 );
792 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
793 }
794 }
795 break;
796 }
797
798 }
799
800 STATIC
801 VOID
802 ExtractFormHandle (
803 IN UI_MENU_OPTION *Selection,
804 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
805 IN UINTN IdValue,
806 OUT UINT16 *FormHandle,
807 OUT UINT16 *TitleToken,
808 OUT EFI_FORM_TAGS *FormTags
809 )
810 {
811 UINTN Index;
812 EFI_FILE_FORM_TAGS *FileFormTags;
813 EFI_FORM_TAGS LocalTags;
814
815 FileFormTags = FileFormTagsHead;
816
817 //
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
821 // information.
822 //
823 for (Index = 0; Index < Selection->IfrNumber; Index++) {
824 FileFormTags = FileFormTags->NextFile;
825 }
826
827 LocalTags = FileFormTags->FormTags;
828
829 if (IdValue == 0) {
830 //
831 // Advance Index to the first FormOp tag information
832 //
833 for (Index = 0; FileFormTags->FormTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
834 ;
835 } else {
836 //
837 // Advance Index to the FormOp with the correct ID value
838 //
839 for (; LocalTags.Next != NULL; LocalTags = *LocalTags.Next) {
840 for (Index = 0; LocalTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
841 ;
842 if (LocalTags.Tags[Index].Id == IdValue) {
843 break;
844 }
845 }
846 }
847 //
848 // return the Form Id, Text, and the File's FormTags structure
849 //
850 *FormHandle = LocalTags.Tags[Index].Id;
851 *TitleToken = LocalTags.Tags[Index].Text;
852 *FormTags = LocalTags;
853 return ;
854 }
855
856 STATIC
857 EFI_STATUS
858 UpdateNewTagData (
859 IN UINT8 *FormData,
860 IN UINT16 ConsistencyId,
861 IN UINT16 CurrentVariable,
862 IN EFI_FORM_TAGS *FormTags,
863 OUT EFI_FILE_FORM_TAGS *FileFormTags
864 )
865 {
866 EFI_STATUS Status;
867 UINT16 Index;
868 UINT16 QuestionIndex;
869 UINT16 NumberOfTags;
870 INT16 CurrTag;
871 UINT8 TagLength;
872 UINTN Count;
873 BOOLEAN Finished;
874
875 //
876 // Initialize some Index variable and Status
877 //
878 Count = 0;
879 QuestionIndex = 0;
880 NumberOfTags = 1;
881 Index = 0;
882 Status = EFI_SUCCESS;
883 Finished = FALSE;
884
885 //
886 // Determine the number of tags for the first form
887 //
888 GetTagCount (&FormData[Index], &NumberOfTags);
889
890 //
891 // Allocate memory for our tags on the first form
892 //
893 FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
894 ASSERT (FormTags->Tags != NULL);
895
896 for (CurrTag = 0; FormData[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
897 //
898 // Operand = IFR OpCode
899 //
900 FormTags->Tags[CurrTag].Operand = FormData[Index];
901
902 //
903 // Assume for now 0 lines occupied by this OpCode
904 //
905 FormTags->Tags[CurrTag].NumberOfLines = 0;
906
907 //
908 // Determine the length of the Tag so we can later skip to the next tag in the form
909 //
910 //
911 // get the length
912 //
913 TagLength = FormData[Index + 1];
914 //
915 // Operate on the Found OpCode
916 //
917 switch (FormData[Index]) {
918
919 case EFI_IFR_FORM_OP:
920 case EFI_IFR_SUBTITLE_OP:
921 case EFI_IFR_TEXT_OP:
922 case EFI_IFR_REF_OP:
923 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
924 break;
925
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));
929 break;
930
931 case EFI_IFR_END_FORM_OP:
932 FormTags->Tags[CurrTag].Operand = FormData[Index];
933 FormTags->Tags[CurrTag].NumberOfLines = 0;
934
935 Finished = TRUE;
936 break;
937
938 case EFI_IFR_ORDERED_LIST_OP:
939 case EFI_IFR_ONE_OF_OP:
940 GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
941
942 //
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
945 //
946 //
947 // record for setting default later
948 //
949 QuestionIndex = (UINT16) CurrTag;
950 break;
951
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);
956 break;
957
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);
961 break;
962
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);
966 break;
967
968 case EFI_IFR_DATE_OP:
969 //
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.
972 //
973 // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2
974 //
975 GetNumericHeader (
976 &FormTags->Tags[CurrTag],
977 FormData,
978 (UINT16) (Index + TagLength),
979 (UINT16) 0,
980 FileFormTags,
981 CurrentVariable
982 );
983
984 //
985 // The current language selected + the Date operand
986 //
987 FormTags->Tags[CurrTag + 1].Operand = FormData[Index];
988 GetNumericHeader (
989 &FormTags->Tags[CurrTag + 1],
990 FormData,
991 (UINT16) (Index + TagLength + FormData[Index + TagLength + 1]),
992 (UINT16) 0,
993 FileFormTags,
994 CurrentVariable
995 );
996
997 //
998 // The current language selected + the Date operand
999 //
1000 FormTags->Tags[CurrTag + 2].Operand = FormData[Index];
1001 GetNumericHeader (&FormTags->Tags[CurrTag + 2], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
1002
1003 CurrTag = (INT16) (CurrTag + 2);
1004
1005 Index = (UINT16) (Index + TagLength);
1006 //
1007 // get the length
1008 //
1009 TagLength = FormData[Index + 1];
1010 Index = (UINT16) (Index + TagLength);
1011 //
1012 // get the length
1013 //
1014 TagLength = FormData[Index + 1];
1015 break;
1016
1017 case EFI_IFR_TIME_OP:
1018 GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 0, FileFormTags, CurrentVariable);
1019
1020 if (Count == 2) {
1021 //
1022 // Override the GetQuestionHeader information - date/time are treated very differently
1023 //
1024 FormTags->Tags[CurrTag].NumberOfLines = 1;
1025 Count = 0;
1026 } else {
1027 //
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.
1030 //
1031 Count++;
1032 }
1033 break;
1034
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);
1039 break;
1040
1041 case EFI_IFR_INCONSISTENT_IF_OP:
1042 case EFI_IFR_SUPPRESS_IF_OP:
1043 case EFI_IFR_GRAYOUT_IF_OP:
1044 ConsistencyId++;
1045 break;
1046
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;
1050 break;
1051
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;
1055 break;
1056
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;
1060 break;
1061
1062 case EFI_IFR_AND_OP:
1063 case EFI_IFR_OR_OP:
1064 case EFI_IFR_NOT_OP:
1065 case EFI_IFR_TRUE_OP:
1066 case EFI_IFR_FALSE_OP:
1067 case EFI_IFR_GT_OP:
1068 case EFI_IFR_GE_OP:
1069 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1070 break;
1071
1072 case EFI_IFR_EQ_ID_LIST_OP:
1073 IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
1074
1075 FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
1076 break;
1077
1078 default:
1079 break;
1080 }
1081 //
1082 // End of switch
1083 //
1084 if (Finished) {
1085 break;
1086 }
1087 //
1088 // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
1089 //
1090 Index = (UINT16) (Index + TagLength);
1091 }
1092 //
1093 // End of Index
1094 //
1095 return Status;
1096 }
1097
1098 STATIC
1099 VOID
1100 ExtractDynamicFormHandle (
1101 IN UI_MENU_OPTION *Selection,
1102 IN UINT8 *CallbackData,
1103 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1104 IN UINTN IdValue,
1105 OUT UINT16 *FormHandle,
1106 OUT UINT16 *TitleToken,
1107 OUT EFI_FORM_TAGS *FormTags
1108 )
1109 /*++
1110
1111 Routine Description:
1112
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.
1116
1117 Arguments:
1118
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.
1126
1127 Returns:
1128 VOID
1129
1130 --*/
1131 {
1132 UINTN Index;
1133 UINTN BackupIndex;
1134 EFI_FILE_FORM_TAGS *FileFormTags;
1135 EFI_FORM_TAGS *LocalTags;
1136 EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
1137 EFI_STATUS Status;
1138 UINTN Length;
1139 UINT8 *Buffer;
1140 EFI_PHYSICAL_ADDRESS CallbackHandle;
1141 EFI_GUID TagGuid;
1142 UINT16 TargetPage;
1143 EFI_HII_CALLBACK_PACKET *Packet;
1144 UINTN ScreenSize;
1145 CHAR16 NullCharacter;
1146 EFI_INPUT_KEY Key;
1147 UINT16 ConsistencyId;
1148 UINT16 CurrentVariable;
1149 EFI_VARIABLE_DEFINITION *VariableDefinition;
1150 EFI_IFR_DATA_ENTRY *DataEntry;
1151
1152 VariableDefinition = NULL;
1153 NullCharacter = CHAR_NULL;
1154
1155 CurrentVariable = 0;
1156 FileFormTags = FileFormTagsHead;
1157 Length = 0;
1158 CallbackHandle = 0;
1159 TargetPage = (UINT16) IdValue;
1160 Packet = NULL;
1161 ConsistencyId = 0;
1162
1163 //
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
1167 // information.
1168 //
1169 for (Index = 0; Index < Selection->IfrNumber; Index++) {
1170 FileFormTags = FileFormTags->NextFile;
1171 }
1172
1173 LocalTags = &FileFormTags->FormTags;
1174
1175 //
1176 // Advance Index to the FormOp with the correct ID value
1177 //
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));
1182 }
1183
1184 for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
1185 ;
1186 if (LocalTags->Tags[Index].Id == IdValue) {
1187 break;
1188 }
1189 }
1190 //
1191 // If we are going to callback on a non-goto opcode, make sure we don't change pages
1192 //
1193 if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
1194 TargetPage = Selection->FormId;
1195 }
1196 //
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
1200 //
1201 CurrentVariable = Selection->Tags[0].VariableNumber;
1202
1203 //
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.
1207 //
1208 Status = gBS->HandleProtocol (
1209 (VOID *) (UINTN) CallbackHandle,
1210 &gEfiFormCallbackProtocolGuid,
1211 (VOID **) &FormCallback
1212 );
1213
1214 if (EFI_ERROR (Status)) {
1215 FreePool (LocalTags->Tags);
1216 return ;
1217 }
1218
1219 ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition);
1220
1221 if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) {
1222 ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap;
1223 } else {
1224 ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL;
1225 }
1226
1227 if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
1228 Status = FormCallback->Callback (
1229 FormCallback,
1230 Selection->ThisTag->Key,
1231 (EFI_IFR_DATA_ARRAY *) CallbackData,
1232 &Packet
1233 );
1234 }
1235
1236 if (EFI_ERROR (Status)) {
1237 //
1238 // Restore Previous Value
1239 //
1240 CopyMem (
1241 &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
1242 gPreviousValue,
1243 Selection->ThisTag->StorageWidth
1244 );
1245
1246 if (Packet != NULL) {
1247 //
1248 // Upon error, we will likely receive a string to print out
1249 //
1250 ScreenSize = GetStringWidth (Packet->String) / 2;
1251
1252 //
1253 // Display error popup
1254 //
1255 CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter);
1256
1257 do {
1258 Status = WaitForKeyStroke (&Key);
1259 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1260 } else {
1261 UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE);
1262 }
1263
1264 } else {
1265 if (Packet != NULL) {
1266 //
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.
1270 //
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:
1279 CopyMem (
1280 &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
1281 &DataEntry->Data,
1282 Selection->ThisTag->StorageWidth
1283 );
1284 break;
1285
1286 case EFI_IFR_NV_ACCESS_COMMAND:
1287 CopyMem (
1288 &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId],
1289 ((EFI_IFR_NV_DATA *) Packet) + 1,
1290 ((EFI_IFR_NV_DATA *) Packet)->StorageWidth
1291 );
1292 break;
1293
1294 }
1295
1296 if (DataEntry->Flags & RESET_REQUIRED) {
1297 gResetRequired = TRUE;
1298 }
1299
1300 if (DataEntry->Flags & EXIT_REQUIRED) {
1301 gExitRequired = TRUE;
1302 }
1303
1304 if (DataEntry->Flags & SAVE_REQUIRED) {
1305 gSaveRequired = TRUE;
1306 }
1307
1308 if (DataEntry->Flags & NV_CHANGED) {
1309 gNvUpdateRequired = TRUE;
1310 }
1311
1312 if (DataEntry->Flags & NV_NOT_CHANGED) {
1313 gNvUpdateRequired = FALSE;
1314 }
1315 }
1316 }
1317 }
1318
1319 if (Packet != NULL) {
1320 FreePool (Packet);
1321 }
1322
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:
1329 case EFI_IFR_OR_OP:
1330 case EFI_IFR_NOT_OP:
1331 case EFI_IFR_TRUE_OP:
1332 case EFI_IFR_FALSE_OP:
1333 case EFI_IFR_GT_OP:
1334 case EFI_IFR_GE_OP:
1335 case EFI_IFR_EQ_ID_LIST_OP:
1336 //
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
1339 //
1340 if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) {
1341 ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1);
1342 }
1343 break;
1344 }
1345 }
1346 //
1347 // Delete the buffer associated with previous dynamic page
1348 // We will re-allocate a buffer....
1349 //
1350 FreePool (LocalTags->Tags);
1351
1352 Length = 0xF000;
1353 Buffer = AllocateZeroPool (Length);
1354 ASSERT (Buffer != NULL);
1355
1356 //
1357 // Get the form that was updated by the callback
1358 //
1359 Hii->GetForms (
1360 Hii,
1361 Selection->Handle,
1362 TargetPage,
1363 &Length,
1364 Buffer
1365 );
1366
1367 //
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
1370 //
1371 UpdateNewTagData (
1372 Buffer,
1373 ConsistencyId,
1374 CurrentVariable,
1375 LocalTags,
1376 FileFormTags
1377 );
1378
1379 //
1380 // return the Form Id, Text, and the File's FormTags structure
1381 //
1382 *FormHandle = LocalTags->Tags[0].Id;
1383 *TitleToken = LocalTags->Tags[0].Text;
1384 *FormTags = *LocalTags;
1385
1386 FormTags->Tags[0].CallbackHandle = CallbackHandle;
1387 CopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID));
1388
1389 return ;
1390 }
1391
1392 UI_MENU_OPTION *
1393 SetupBrowser (
1394 IN UI_MENU_OPTION *Selection,
1395 IN BOOLEAN Callback,
1396 IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
1397 IN UINT8 *CallbackData
1398 )
1399 {
1400 UINT16 FormHandle;
1401 UINT16 TitleToken;
1402 EFI_FORM_TAGS FormTags;
1403
1404 gEntryNumber = -1;
1405 gLastOpr = FALSE;
1406 //
1407 // Displays the Header and Footer borders
1408 //
1409 DisplayPageFrame ();
1410
1411 //
1412 // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR
1413 //
1414 ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags);
1415
1416 Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
1417
1418 //
1419 // If selection is null use the former selection
1420 //
1421 if (Selection == NULL) {
1422 return Selection;
1423 }
1424
1425 if (Callback) {
1426 return Selection;
1427 }
1428
1429 while (Selection->Tags != NULL) {
1430 if (Selection->Previous) {
1431 ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
1432 } else {
1433 //
1434 // True if a hyperlink/jump is selected
1435 //
1436 if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) {
1437 if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
1438 ExtractDynamicFormHandle (
1439 Selection,
1440 CallbackData,
1441 FileFormTagsHead,
1442 Selection->ThisTag->Id,
1443 &FormHandle,
1444 &TitleToken,
1445 &FormTags
1446 );
1447 goto DisplayPage;
1448 } else {
1449 ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags);
1450 goto DisplayPage;
1451 }
1452 }
1453
1454 if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) &&
1455 (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP)
1456 ) {
1457 ExtractDynamicFormHandle (
1458 Selection,
1459 CallbackData,
1460 FileFormTagsHead,
1461 Selection->FormId,
1462 &FormHandle,
1463 &TitleToken,
1464 &FormTags
1465 );
1466 } else {
1467 ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
1468 }
1469 }
1470
1471 DisplayPage:
1472 //
1473 // Displays the Header and Footer borders
1474 //
1475 DisplayPageFrame ();
1476
1477 Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
1478
1479 if (Selection == NULL) {
1480 break;
1481 }
1482 };
1483
1484 return Selection;
1485 }