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