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