6d5a3db2e585b76a8fdc58d979c998b8aa211c00
[efi/edk2/.git] / edk2 / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
1 /** @file\r
2 Utility functions for UI presentation.\r
3 \r
4 Copyright (c) 2004 - 2010, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "Setup.h"\r
16 \r
17 BOOLEAN            mHiiPackageListUpdated;\r
18 UI_MENU_SELECTION  *gCurrentSelection;\r
19 \r
20 \r
21 /**\r
22   Clear retangle with specified text attribute.\r
23 \r
24   @param  LeftColumn     Left column of retangle.\r
25   @param  RightColumn    Right column of retangle.\r
26   @param  TopRow         Start row of retangle.\r
27   @param  BottomRow      End row of retangle.\r
28   @param  TextAttribute  The character foreground and background.\r
29 \r
30 **/\r
31 VOID\r
32 ClearLines (\r
33   IN UINTN               LeftColumn,\r
34   IN UINTN               RightColumn,\r
35   IN UINTN               TopRow,\r
36   IN UINTN               BottomRow,\r
37   IN 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
72 /**\r
73   Concatenate a narrow string to another string.\r
74 \r
75   @param Destination The destination string.\r
76   @param Source      The source string. The string to be concatenated.\r
77                      to the end of Destination.\r
78 \r
79 **/\r
80 VOID\r
81 NewStrCat (\r
82   IN OUT CHAR16               *Destination,\r
83   IN     CHAR16               *Source\r
84   )\r
85 {\r
86   UINTN Length;\r
87 \r
88   for (Length = 0; Destination[Length] != 0; Length++)\r
89     ;\r
90 \r
91   //\r
92   // We now have the length of the original string\r
93   // We can safely assume for now that we are concatenating a narrow value to this string.\r
94   // For instance, the string is "XYZ" and cat'ing ">"\r
95   // If this assumption changes, we need to make this routine a bit more complex\r
96   //\r
97   Destination[Length] = NARROW_CHAR;\r
98   Length++;\r
99 \r
100   StrCpy (Destination + Length, Source);\r
101 }\r
102 \r
103 /**\r
104   Count the storage space of a Unicode string.\r
105 \r
106   This function handles the Unicode string with NARROW_CHAR\r
107   and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
108   does not count in the resultant output. If a WIDE_CHAR is\r
109   hit, then 2 Unicode character will consume an output storage\r
110   space with size of CHAR16 till a NARROW_CHAR is hit.\r
111 \r
112   @param String          The input string to be counted.\r
113 \r
114   @return Storage space for the input string.\r
115 \r
116 **/\r
117 UINTN\r
118 GetStringWidth (\r
119   IN CHAR16               *String\r
120   )\r
121 {\r
122   UINTN Index;\r
123   UINTN Count;\r
124   UINTN IncrementValue;\r
125 \r
126   Index           = 0;\r
127   Count           = 0;\r
128   IncrementValue  = 1;\r
129 \r
130   do {\r
131     //\r
132     // Advance to the null-terminator or to the first width directive\r
133     //\r
134     for (;\r
135          (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
136          Index++, Count = Count + IncrementValue\r
137         )\r
138       ;\r
139 \r
140     //\r
141     // We hit the null-terminator, we now have a count\r
142     //\r
143     if (String[Index] == 0) {\r
144       break;\r
145     }\r
146     //\r
147     // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
148     // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
149     //\r
150     if (String[Index] == NARROW_CHAR) {\r
151       //\r
152       // Skip to the next character\r
153       //\r
154       Index++;\r
155       IncrementValue = 1;\r
156     } else {\r
157       //\r
158       // Skip to the next character\r
159       //\r
160       Index++;\r
161       IncrementValue = 2;\r
162     }\r
163   } while (String[Index] != 0);\r
164 \r
165   //\r
166   // Increment by one to include the null-terminator in the size\r
167   //\r
168   Count++;\r
169 \r
170   return Count * sizeof (CHAR16);\r
171 }\r
172 \r
173 /**\r
174   This function displays the page frame.\r
175 \r
176 **/\r
177 VOID\r
178 DisplayPageFrame (\r
179   VOID\r
180   )\r
181 {\r
182   UINTN                  Index;\r
183   UINT8                  Line;\r
184   UINT8                  Alignment;\r
185   CHAR16                 Character;\r
186   CHAR16                 *Buffer;\r
187   CHAR16                 *StrFrontPageBanner;\r
188   UINTN                  Row;\r
189   EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
190   UINT8                  RowIdx;\r
191   UINT8                  ColumnIdx;\r
192 \r
193   ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
194   gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
195   ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
196 \r
197   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
198 \r
199   //\r
200   // For now, allocate an arbitrarily long buffer\r
201   //\r
202   Buffer = AllocateZeroPool (0x10000);\r
203   ASSERT (Buffer != NULL);\r
204 \r
205   Character = BOXDRAW_HORIZONTAL;\r
206 \r
207   for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
208     Buffer[Index] = Character;\r
209   }\r
210 \r
211   if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
212     //\r
213     //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
214     //\r
215     ClearLines (\r
216       LocalScreen.LeftColumn,\r
217       LocalScreen.RightColumn,\r
218       LocalScreen.TopRow,\r
219       FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
220       BANNER_TEXT | BANNER_BACKGROUND\r
221       );\r
222     //\r
223     //    for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
224     //\r
225     for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
226       //\r
227       //      for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
228       //\r
229       for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
230            Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
231            Alignment++\r
232           ) {\r
233         RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);\r
234         ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);\r
235 \r
236         ASSERT (RowIdx < BANNER_HEIGHT);\r
237         ASSERT (ColumnIdx < BANNER_COLUMNS);\r
238 \r
239         if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
240           StrFrontPageBanner = GetToken (\r
241                                 gBannerData->Banner[RowIdx][ColumnIdx],\r
242                                 gFrontPageHandle\r
243                                 );\r
244         } else {\r
245           continue;\r
246         }\r
247 \r
248         switch (Alignment - LocalScreen.LeftColumn) {\r
249         case 0:\r
250           //\r
251           // Handle left column\r
252           //\r
253           PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
254           break;\r
255 \r
256         case 1:\r
257           //\r
258           // Handle center column\r
259           //\r
260           PrintStringAt (\r
261             LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
262             Line,\r
263             StrFrontPageBanner\r
264             );\r
265           break;\r
266 \r
267         case 2:\r
268           //\r
269           // Handle right column\r
270           //\r
271           PrintStringAt (\r
272             LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
273             Line,\r
274             StrFrontPageBanner\r
275             );\r
276           break;\r
277         }\r
278 \r
279         FreePool (StrFrontPageBanner);\r
280       }\r
281     }\r
282   }\r
283 \r
284   ClearLines (\r
285     LocalScreen.LeftColumn,\r
286     LocalScreen.RightColumn,\r
287     LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
288     LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
289     KEYHELP_TEXT | KEYHELP_BACKGROUND\r
290     );\r
291 \r
292   if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
293     ClearLines (\r
294       LocalScreen.LeftColumn,\r
295       LocalScreen.RightColumn,\r
296       LocalScreen.TopRow,\r
297       LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
298       TITLE_TEXT | TITLE_BACKGROUND\r
299       );\r
300     //\r
301     // Print Top border line\r
302     // +------------------------------------------------------------------------------+\r
303     // ?                                                                             ?\r
304     // +------------------------------------------------------------------------------+\r
305     //\r
306     Character = BOXDRAW_DOWN_RIGHT;\r
307 \r
308     PrintChar (Character);\r
309     PrintString (Buffer);\r
310 \r
311     Character = BOXDRAW_DOWN_LEFT;\r
312     PrintChar (Character);\r
313 \r
314     Character = BOXDRAW_VERTICAL;\r
315     for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
316       PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
317       PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
318     }\r
319 \r
320     Character = BOXDRAW_UP_RIGHT;\r
321     PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
322     PrintString (Buffer);\r
323 \r
324     Character = BOXDRAW_UP_LEFT;\r
325     PrintChar (Character);\r
326 \r
327     if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
328       //\r
329       // Print Bottom border line\r
330       // +------------------------------------------------------------------------------+\r
331       // ?                                                                             ?\r
332       // +------------------------------------------------------------------------------+\r
333       //\r
334       Character = BOXDRAW_DOWN_RIGHT;\r
335       PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
336 \r
337       PrintString (Buffer);\r
338 \r
339       Character = BOXDRAW_DOWN_LEFT;\r
340       PrintChar (Character);\r
341       Character = BOXDRAW_VERTICAL;\r
342       for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
343            Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
344            Row++\r
345           ) {\r
346         PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
347         PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
348       }\r
349 \r
350       Character = BOXDRAW_UP_RIGHT;\r
351       PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
352 \r
353       PrintString (Buffer);\r
354 \r
355       Character = BOXDRAW_UP_LEFT;\r
356       PrintChar (Character);\r
357     }\r
358   }\r
359 \r
360   FreePool (Buffer);\r
361 \r
362 }\r
363 \r
364 \r
365 /**\r
366   Evaluate all expressions in a Form.\r
367 \r
368   @param  FormSet        FormSet this Form belongs to.\r
369   @param  Form           The Form.\r
370 \r
371   @retval EFI_SUCCESS    The expression evaluated successfuly\r
372 \r
373 **/\r
374 EFI_STATUS\r
375 EvaluateFormExpressions (\r
376   IN FORM_BROWSER_FORMSET  *FormSet,\r
377   IN FORM_BROWSER_FORM     *Form\r
378   )\r
379 {\r
380   EFI_STATUS       Status;\r
381   LIST_ENTRY       *Link;\r
382   FORM_EXPRESSION  *Expression;\r
383 \r
384   Link = GetFirstNode (&Form->ExpressionListHead);\r
385   while (!IsNull (&Form->ExpressionListHead, Link)) {\r
386     Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
387     Link = GetNextNode (&Form->ExpressionListHead, Link);\r
388 \r
389     if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
390         Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
391         Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
392         (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
393       //\r
394       // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
395       //\r
396       continue;\r
397     }\r
398 \r
399     Status = EvaluateExpression (FormSet, Form, Expression);\r
400     if (EFI_ERROR (Status)) {\r
401       return Status;\r
402     }\r
403   }\r
404 \r
405   return EFI_SUCCESS;\r
406 }\r
407 \r
408 /*\r
409 +------------------------------------------------------------------------------+\r
410 ?                                 Setup Page                                  ?\r
411 +------------------------------------------------------------------------------+\r
412 \r
413 \r
414 \r
415 \r
416 \r
417 \r
418 \r
419 \r
420 \r
421 \r
422 \r
423 \r
424 \r
425 \r
426 \r
427 \r
428 \r
429 +------------------------------------------------------------------------------+\r
430 ?F1=Scroll Help                 F9=Reset to Defaults        F10=Save and Exit ?\r
431 | ^"=Move Highlight          <Spacebar> Toggles Checkbox   Esc=Discard Changes |\r
432 +------------------------------------------------------------------------------+\r
433 */\r
434 \r
435 /**\r
436 \r
437 \r
438   Display form and wait for user to select one menu option, then return it.\r
439 \r
440   @param Selection       On input, Selection tell setup browser the information\r
441                          about the Selection, form and formset to be displayed.\r
442                          On output, Selection return the screen item that is selected\r
443                          by user.\r
444   @retval EFI_SUCESSS            This function always return successfully for now.\r
445 \r
446 **/\r
447 EFI_STATUS\r
448 DisplayForm (\r
449   IN OUT UI_MENU_SELECTION           *Selection\r
450   )\r
451 {\r
452   CHAR16                 *StringPtr;\r
453   UINT16                 MenuItemCount;\r
454   EFI_HII_HANDLE         Handle;\r
455   BOOLEAN                Suppress;\r
456   EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
457   UINT16                 Width;\r
458   UINTN                  ArrayEntry;\r
459   CHAR16                 *OutputString;\r
460   LIST_ENTRY             *Link;\r
461   FORM_BROWSER_STATEMENT *Statement;\r
462   UINT16                 NumberOfLines;\r
463   EFI_STATUS             Status;\r
464   UI_MENU_OPTION         *MenuOption;\r
465 \r
466   Handle        = Selection->Handle;\r
467   MenuItemCount = 0;\r
468   ArrayEntry    = 0;\r
469   OutputString  = NULL;\r
470 \r
471   UiInitMenu ();\r
472 \r
473   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
474 \r
475   StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
476 \r
477   if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
478     gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
479     PrintStringAt (\r
480       (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
481       LocalScreen.TopRow + 1,\r
482       StringPtr\r
483       );\r
484   }\r
485 \r
486   //\r
487   // Remove Buffer allocated for StringPtr after it has been used.\r
488   //\r
489   FreePool (StringPtr);\r
490 \r
491   //\r
492   // Evaluate all the Expressions in this Form\r
493   //\r
494   Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
495   if (EFI_ERROR (Status)) {\r
496     return Status;\r
497   }\r
498 \r
499   Selection->FormEditable = FALSE;\r
500   Link = GetFirstNode (&Selection->Form->StatementListHead);\r
501   while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
502     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
503 \r
504     if (Statement->SuppressExpression != NULL) {\r
505       Suppress = Statement->SuppressExpression->Result.Value.b;\r
506     } else {\r
507       Suppress = FALSE;\r
508     }\r
509 \r
510     if (Statement->DisableExpression != NULL) {\r
511       Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
512     }\r
513 \r
514     if (!Suppress) {\r
515       StringPtr = GetToken (Statement->Prompt, Handle);\r
516 \r
517       Width     = GetWidth (Statement, Handle);\r
518 \r
519       NumberOfLines = 1;\r
520       ArrayEntry = 0;\r
521       for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
522         //\r
523         // If there is more string to process print on the next row and increment the Skip value\r
524         //\r
525         if (StrLen (&StringPtr[ArrayEntry]) != 0) {\r
526           NumberOfLines++;\r
527         }\r
528 \r
529         FreePool (OutputString);\r
530       }\r
531 \r
532       //\r
533       // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
534       // it in UiFreeMenu.\r
535       //\r
536       MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
537       MenuItemCount++;\r
538 \r
539       if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
540         //\r
541         // At least one item is not readonly, this Form is considered as editable\r
542         //\r
543         Selection->FormEditable = TRUE;\r
544       }\r
545     }\r
546 \r
547     Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
548   }\r
549 \r
550   Status = UiDisplayMenu (Selection);\r
551 \r
552   UiFreeMenu ();\r
553 \r
554   return Status;\r
555 }\r
556 \r
557 /**\r
558   Initialize the HII String Token to the correct values.\r
559 \r
560 **/\r
561 VOID\r
562 InitializeBrowserStrings (\r
563   VOID\r
564   )\r
565 {\r
566   gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
567   gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
568   gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
569   gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
570   gEnterEscapeString    = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
571   gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
572   gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
573   gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
574   gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
575   gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
576   gHexNumericInput      = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
577   gToggleCheckBox       = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
578   gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
579   gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
580   gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
581   gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
582   gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
583   gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
584   gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
585   gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
586   gAreYouSure           = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
587   gYesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
588   gNoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
589   gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
590   gPlusString           = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
591   gMinusString          = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
592   gAdjustNumber         = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
593   gSaveChanges          = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
594   gOptionMismatch       = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
595   gFormSuppress         = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
596   return ;\r
597 }\r
598 \r
599 /**\r
600   Free up the resource allocated for all strings required\r
601   by Setup Browser.\r
602 \r
603 **/\r
604 VOID\r
605 FreeBrowserStrings (\r
606   VOID\r
607   )\r
608 {\r
609   FreePool (gFunctionNineString);\r
610   FreePool (gFunctionTenString);\r
611   FreePool (gEnterString);\r
612   FreePool (gEnterCommitString);\r
613   FreePool (gEnterEscapeString);\r
614   FreePool (gEscapeString);\r
615   FreePool (gMoveHighlight);\r
616   FreePool (gMakeSelection);\r
617   FreePool (gDecNumericInput);\r
618   FreePool (gHexNumericInput);\r
619   FreePool (gToggleCheckBox);\r
620   FreePool (gPromptForData);\r
621   FreePool (gPromptForPassword);\r
622   FreePool (gPromptForNewPassword);\r
623   FreePool (gConfirmPassword);\r
624   FreePool (gPassowordInvalid);\r
625   FreePool (gConfirmError);\r
626   FreePool (gPressEnter);\r
627   FreePool (gEmptyString);\r
628   FreePool (gAreYouSure);\r
629   FreePool (gYesResponse);\r
630   FreePool (gNoResponse);\r
631   FreePool (gMiniString);\r
632   FreePool (gPlusString);\r
633   FreePool (gMinusString);\r
634   FreePool (gAdjustNumber);\r
635   FreePool (gSaveChanges);\r
636   FreePool (gOptionMismatch);\r
637   FreePool (gFormSuppress);\r
638   return ;\r
639 }\r
640 \r
641 \r
642 /**\r
643   Update key's help imformation.\r
644 \r
645   @param Selection       Tell setup browser the information about the Selection\r
646   @param  MenuOption     The Menu option\r
647   @param  Selected       Whether or not a tag be selected\r
648 \r
649 **/\r
650 VOID\r
651 UpdateKeyHelp (\r
652   IN  UI_MENU_SELECTION           *Selection,\r
653   IN  UI_MENU_OPTION              *MenuOption,\r
654   IN  BOOLEAN                     Selected\r
655   )\r
656 {\r
657   UINTN                  SecCol;\r
658   UINTN                  ThdCol;\r
659   UINTN                  LeftColumnOfHelp;\r
660   UINTN                  RightColumnOfHelp;\r
661   UINTN                  TopRowOfHelp;\r
662   UINTN                  BottomRowOfHelp;\r
663   UINTN                  StartColumnOfHelp;\r
664   EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
665   FORM_BROWSER_STATEMENT *Statement;\r
666 \r
667   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
668 \r
669   SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
670   ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
671 \r
672   StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
673   LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;\r
674   RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
675   TopRowOfHelp      = LocalScreen.BottomRow - 4;\r
676   BottomRowOfHelp   = LocalScreen.BottomRow - 3;\r
677 \r
678   gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
679 \r
680   Statement = MenuOption->ThisTag;\r
681   switch (Statement->Operand) {\r
682   case EFI_IFR_ORDERED_LIST_OP:\r
683   case EFI_IFR_ONE_OF_OP:\r
684   case EFI_IFR_NUMERIC_OP:\r
685   case EFI_IFR_TIME_OP:\r
686   case EFI_IFR_DATE_OP:\r
687     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
688 \r
689     if (!Selected) {\r
690       if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
691         if (Selection->FormEditable) {\r
692           PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
693           PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
694         }\r
695         PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
696       }\r
697 \r
698       if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
699           (Statement->Operand == EFI_IFR_TIME_OP)) {\r
700         PrintAt (\r
701           StartColumnOfHelp,\r
702           BottomRowOfHelp,\r
703           L"%c%c%c%c%s",\r
704           ARROW_UP,\r
705           ARROW_DOWN,\r
706           ARROW_RIGHT,\r
707           ARROW_LEFT,\r
708           gMoveHighlight\r
709           );\r
710         PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
711       } else {\r
712         PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
713         if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
714           PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
715         } else {\r
716           PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
717         }\r
718       }\r
719     } else {\r
720       PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
721 \r
722       //\r
723       // If it is a selected numeric with manual input, display different message\r
724       //\r
725       if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
726         PrintStringAt (\r
727           SecCol,\r
728           TopRowOfHelp,\r
729           ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
730           );\r
731       } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
732         PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
733       }\r
734 \r
735       if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
736         PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
737         PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
738       }\r
739 \r
740       PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
741     }\r
742     break;\r
743 \r
744   case EFI_IFR_CHECKBOX_OP:\r
745     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
746 \r
747     if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
748       if (Selection->FormEditable) {\r
749         PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
750         PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
751       }\r
752       PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
753     }\r
754 \r
755     PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
756     PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
757     break;\r
758 \r
759   case EFI_IFR_REF_OP:\r
760   case EFI_IFR_PASSWORD_OP:\r
761   case EFI_IFR_STRING_OP:\r
762   case EFI_IFR_TEXT_OP:\r
763   case EFI_IFR_ACTION_OP:\r
764   case EFI_IFR_RESET_BUTTON_OP:\r
765     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
766 \r
767     if (!Selected) {\r
768       if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
769         if (Selection->FormEditable) {\r
770           PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
771           PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
772         }\r
773         PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
774       }\r
775 \r
776       PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
777       if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
778         PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
779       }\r
780     } else {\r
781       if (Statement->Operand != EFI_IFR_REF_OP) {\r
782         PrintStringAt (\r
783           (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
784           BottomRowOfHelp,\r
785           gEnterCommitString\r
786           );\r
787         PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
788       }\r
789     }\r
790     break;\r
791 \r
792   default:\r
793     break;\r
794   }\r
795 }\r
796 \r
797 /**\r
798   Functions which are registered to receive notification of\r
799   database events have this prototype. The actual event is encoded\r
800   in NotifyType. The following table describes how PackageType,\r
801   PackageGuid, Handle, and Package are used for each of the\r
802   notification types.\r
803 \r
804   @param PackageType  Package type of the notification.\r
805 \r
806   @param PackageGuid  If PackageType is\r
807                       EFI_HII_PACKAGE_TYPE_GUID, then this is\r
808                       the pointer to the GUID from the Guid\r
809                       field of EFI_HII_PACKAGE_GUID_HEADER.\r
810                       Otherwise, it must be NULL.\r
811 \r
812   @param Package  Points to the package referred to by the\r
813                   notification Handle The handle of the package\r
814                   list which contains the specified package.\r
815 \r
816   @param Handle       The HII handle.\r
817 \r
818   @param NotifyType   The type of change concerning the\r
819                       database. See\r
820                       EFI_HII_DATABASE_NOTIFY_TYPE.\r
821 \r
822 **/\r
823 EFI_STATUS\r
824 EFIAPI\r
825 FormUpdateNotify (\r
826   IN UINT8                              PackageType,\r
827   IN CONST EFI_GUID                     *PackageGuid,\r
828   IN CONST EFI_HII_PACKAGE_HEADER       *Package,\r
829   IN EFI_HII_HANDLE                     Handle,\r
830   IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType\r
831   )\r
832 {\r
833   mHiiPackageListUpdated = TRUE;\r
834 \r
835   return EFI_SUCCESS;\r
836 }\r
837 \r
838 /**\r
839   The worker function that send the displays to the screen. On output,\r
840   the selection made by user is returned.\r
841 \r
842   @param Selection       On input, Selection tell setup browser the information\r
843                          about the Selection, form and formset to be displayed.\r
844                          On output, Selection return the screen item that is selected\r
845                          by user.\r
846 \r
847   @retval EFI_SUCCESS    The page is displayed successfully.\r
848   @return Other value if the page failed to be diplayed.\r
849 \r
850 **/\r
851 EFI_STATUS\r
852 SetupBrowser (\r
853   IN OUT UI_MENU_SELECTION    *Selection\r
854   )\r
855 {\r
856   EFI_STATUS                      Status;\r
857   LIST_ENTRY                      *Link;\r
858   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
859   EFI_HANDLE                      NotifyHandle;\r
860   EFI_HII_VALUE                   *HiiValue;\r
861   EFI_IFR_TYPE_VALUE              *TypeValue;\r
862   FORM_BROWSER_STATEMENT          *Statement;\r
863   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
864   FORM_BROWSER_FORMSET            *FormSet;\r
865   EFI_INPUT_KEY                   Key;\r
866 \r
867   gMenuRefreshHead = NULL;\r
868   gResetRequired = FALSE;\r
869   FormSet = Selection->FormSet;\r
870 \r
871   //\r
872   // Register notify for Form package update\r
873   //\r
874   Status = mHiiDatabase->RegisterPackageNotify (\r
875                            mHiiDatabase,\r
876                            EFI_HII_PACKAGE_FORMS,\r
877                            NULL,\r
878                            FormUpdateNotify,\r
879                            EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
880                            &NotifyHandle\r
881                            );\r
882   if (EFI_ERROR (Status)) {\r
883     return Status;\r
884   }\r
885 \r
886   //\r
887   // Before display the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
888   //\r
889   ConfigAccess = Selection->FormSet->ConfigAccess;\r
890   if ((ConfigAccess != NULL) && (Selection->Action != UI_ACTION_REFRESH_FORMSET)) {\r
891     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
892     mHiiPackageListUpdated = FALSE;\r
893     Status = ConfigAccess->Callback (\r
894                              ConfigAccess,\r
895                              EFI_BROWSER_ACTION_FORM_OPEN,\r
896                              0,\r
897                              EFI_IFR_TYPE_UNDEFINED,\r
898                              NULL,\r
899                              &ActionRequest\r
900                              );\r
901 \r
902     if (!EFI_ERROR (Status)) {\r
903       switch (ActionRequest) {\r
904       case EFI_BROWSER_ACTION_REQUEST_RESET:\r
905         gResetRequired = TRUE;\r
906         break;\r
907 \r
908       case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
909         //\r
910         // Till now there is no uncommitted data, so ignore this request\r
911         //\r
912         break;\r
913 \r
914       case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
915         Selection->Action = UI_ACTION_EXIT;\r
916         break;\r
917 \r
918       default:\r
919         break;\r
920       }\r
921     }\r
922 \r
923     if (mHiiPackageListUpdated) {\r
924       //\r
925       // IFR is updated during callback, force to reparse the IFR binary\r
926       //\r
927       mHiiPackageListUpdated = FALSE;\r
928       Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
929       goto Done;\r
930     }\r
931   }\r
932 \r
933   //\r
934   // Initialize current settings of Questions in this FormSet\r
935   //\r
936   Status = InitializeCurrentSetting (Selection->FormSet);\r
937   if (EFI_ERROR (Status)) {\r
938     Selection->Action = UI_ACTION_EXIT;\r
939     goto Done;\r
940   }\r
941 \r
942   do {\r
943     //\r
944     // Initialize Selection->Form\r
945     //\r
946     if (Selection->FormId == 0) {\r
947       //\r
948       // Zero FormId indicates display the first Form in a FormSet\r
949       //\r
950       Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
951 \r
952       Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
953       Selection->FormId = Selection->Form->FormId;\r
954     } else {\r
955       Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
956     }\r
957 \r
958     if (Selection->Form == NULL) {\r
959       //\r
960       // No Form to display\r
961       //\r
962       return EFI_NOT_FOUND;\r
963     }\r
964 \r
965     //\r
966     // Check Form is suppressed.\r
967     //\r
968     if (Selection->Form->SuppressExpression != NULL) {\r
969       Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);\r
970       if (EFI_ERROR (Status)) {\r
971         return Status;\r
972       }\r
973 \r
974       if (Selection->Form->SuppressExpression->Result.Value.b) {\r
975         //\r
976         // Form is suppressed. \r
977         //\r
978         do {\r
979           CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
980         } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
981 \r
982         return EFI_NOT_FOUND;\r
983       }\r
984     }\r
985     \r
986     //\r
987     // Reset FormPackage update flag\r
988     //\r
989     mHiiPackageListUpdated = FALSE;\r
990 \r
991     //\r
992     // Load Questions' Value for display\r
993     //\r
994     Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
995     if (EFI_ERROR (Status)) {\r
996       return Status;\r
997     }\r
998 \r
999     //\r
1000     // IFR is updated during callback of read value, force to reparse the IFR binary\r
1001     //\r
1002     if (mHiiPackageListUpdated) {\r
1003       Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1004       mHiiPackageListUpdated = FALSE;\r
1005       goto Done;\r
1006     }\r
1007 \r
1008     //\r
1009     // Displays the Header and Footer borders\r
1010     //\r
1011     DisplayPageFrame ();\r
1012 \r
1013     //\r
1014     // Display form\r
1015     //\r
1016     Status = DisplayForm (Selection);\r
1017     if (EFI_ERROR (Status)) {\r
1018       return Status;\r
1019     }\r
1020 \r
1021     //\r
1022     // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
1023     //\r
1024     Statement = Selection->Statement;\r
1025     if (Statement != NULL) {\r
1026       if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
1027         gResetRequired = TRUE;\r
1028       }\r
1029 \r
1030       //\r
1031       // Reset FormPackage update flag\r
1032       //\r
1033       mHiiPackageListUpdated = FALSE;\r
1034 \r
1035       if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
1036         ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1037 \r
1038         if (ConfigAccess == NULL) {\r
1039           return EFI_UNSUPPORTED;\r
1040         }\r
1041 \r
1042         HiiValue = &Statement->HiiValue;\r
1043         TypeValue = &HiiValue->Value;\r
1044         if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1045           //\r
1046           // Create String in HII database for Configuration Driver to retrieve\r
1047           //\r
1048           HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
1049         } else if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
1050           //\r
1051           // For OrderedList, passing in the value buffer to Callback()\r
1052           //\r
1053           TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
1054         }\r
1055 \r
1056         Status = ConfigAccess->Callback (\r
1057                                  ConfigAccess,\r
1058                                  EFI_BROWSER_ACTION_CHANGING,\r
1059                                  Statement->QuestionId,\r
1060                                  HiiValue->Type,\r
1061                                  TypeValue,\r
1062                                  &ActionRequest\r
1063                                  );\r
1064 \r
1065         if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
1066           //\r
1067           // Clean the String in HII Database\r
1068           //\r
1069           DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
1070         }\r
1071 \r
1072         if (!EFI_ERROR (Status)) {\r
1073           switch (ActionRequest) {\r
1074           case EFI_BROWSER_ACTION_REQUEST_RESET:\r
1075             gResetRequired = TRUE;\r
1076             break;\r
1077 \r
1078           case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
1079             SubmitForm (Selection->FormSet, Selection->Form);\r
1080             break;\r
1081 \r
1082           case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
1083             Selection->Action = UI_ACTION_EXIT;\r
1084             gNvUpdateRequired = FALSE;\r
1085             break;\r
1086 \r
1087           default:\r
1088             break;\r
1089           }\r
1090         } else if (Status != EFI_UNSUPPORTED) {\r
1091           //\r
1092           // Callback return error status other than EFI_UNSUPPORTED\r
1093           //\r
1094           if (Statement->Operand == EFI_IFR_REF_OP) {\r
1095             //\r
1096             // Cross reference will not be taken\r
1097             //\r
1098             Selection->FormId = Selection->Form->FormId;\r
1099             Selection->QuestionId = 0;\r
1100           }\r
1101         }\r
1102       }\r
1103 \r
1104       //\r
1105       // Check whether Form Package has been updated during Callback\r
1106       //\r
1107       if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
1108         //\r
1109         // Force to reparse IFR binary of target Formset\r
1110         //\r
1111         mHiiPackageListUpdated = FALSE;\r
1112         Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1113       }\r
1114     }\r
1115   } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
1116 \r
1117   //\r
1118   // Before exit the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
1119   //\r
1120   if ((ConfigAccess != NULL) && (Selection->Action == UI_ACTION_EXIT)) {\r
1121     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1122     Status = ConfigAccess->Callback (\r
1123                              ConfigAccess,\r
1124                              EFI_BROWSER_ACTION_FORM_CLOSE,\r
1125                              0,\r
1126                              EFI_IFR_TYPE_UNDEFINED,\r
1127                              NULL,\r
1128                              &ActionRequest\r
1129                              );\r
1130 \r
1131     if (!EFI_ERROR (Status)) {\r
1132       switch (ActionRequest) {\r
1133       case EFI_BROWSER_ACTION_REQUEST_RESET:\r
1134         gResetRequired = TRUE;\r
1135         break;\r
1136 \r
1137       case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
1138         SubmitForm (Selection->FormSet, Selection->Form);\r
1139         break;\r
1140 \r
1141       case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
1142         gNvUpdateRequired = FALSE;\r
1143         break;\r
1144 \r
1145       default:\r
1146         break;\r
1147       }\r
1148     }\r
1149   }\r
1150 \r
1151   //\r
1152   // Record the old formset\r
1153   //\r
1154   if (gOldFormSet != NULL) {\r
1155     DestroyFormSet (gOldFormSet);\r
1156   }\r
1157   gOldFormSet = FormSet;\r
1158 \r
1159 Done:\r
1160   //\r
1161   // Unregister notify for Form package update\r
1162   //\r
1163   Status = mHiiDatabase->UnregisterPackageNotify (\r
1164                            mHiiDatabase,\r
1165                            NotifyHandle\r
1166                            );\r
1167   return Status;\r
1168 }\r