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