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