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