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