1 /** @file
2 
3   This library class defines a set of interfaces to customize Display module
4 
5 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 #include "CustomizedDisplayLibInternal.h"
16 
17 EFI_GUID          gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } };
18 
19 EFI_HII_HANDLE    mCDLStringPackHandle;
20 UINT16            gClassOfVfr;                 // Formset class information
21 BOOLEAN           gLibIsFirstForm = TRUE;
22 BANNER_DATA       *gBannerData;
23 
24 UINTN             gFooterHeight;
25 
26 /**
27 +------------------------------------------------------------------------------+
28 |                                 Setup Page                                   |
29 +------------------------------------------------------------------------------+
30 
31 Statement
32 Statement
33 Statement
34 
35 
36 
37 
38 
39 +------------------------------------------------------------------------------+
40 |                                F9=Reset to Defaults        F10=Save          |
41 | ^"=Move Highlight          <Spacebar> Toggles Checkbox     Esc=Exit          |
42 +------------------------------------------------------------------------------+
43   StatusBar
44 **/
45 
46 /**
47   This funtion defines Page Frame and Backgroud.
48 
49   Based on the above layout, it will be responsible for HeaderHeight, FooterHeight,
50   StatusBarHeight and Backgroud. And, it will reserve Screen for Statement.
51 
52   @param[in]  FormData             Form Data to be shown in Page.
53   @param[out] ScreenForStatement   Screen to be used for Statement. (Prompt, Value and Help)
54 
55   @return Status
56 **/
57 EFI_STATUS
58 EFIAPI
DisplayPageFrame(IN FORM_DISPLAY_ENGINE_FORM * FormData,OUT EFI_SCREEN_DESCRIPTOR * ScreenForStatement)59 DisplayPageFrame (
60   IN FORM_DISPLAY_ENGINE_FORM       *FormData,
61   OUT EFI_SCREEN_DESCRIPTOR         *ScreenForStatement
62   )
63 {
64   EFI_STATUS             Status;
65 
66   ASSERT (FormData != NULL && ScreenForStatement != NULL);
67   if (FormData == NULL || ScreenForStatement == NULL) {
68     return EFI_INVALID_PARAMETER;
69   }
70 
71   Status = ScreenDiemensionInfoValidate (FormData);
72   if (EFI_ERROR (Status)) {
73     return Status;
74   }
75 
76   gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;
77 
78   ProcessExternedOpcode(FormData);
79 
80   //
81   // Calculate the ScreenForStatement.
82   //
83   ScreenForStatement->BottomRow   = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight;
84   if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
85     ScreenForStatement->TopRow    = gScreenDimensions.TopRow + FRONT_PAGE_HEADER_HEIGHT;
86   } else {
87     ScreenForStatement->TopRow    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
88   }
89   ScreenForStatement->LeftColumn  = gScreenDimensions.LeftColumn;
90   ScreenForStatement->RightColumn = gScreenDimensions.RightColumn;
91 
92   if ((gLibIsFirstForm) || ((FormData->Attribute & HII_DISPLAY_MODAL) != 0)) {
93     //
94     // Ensure we are in Text mode
95     //
96     gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
97     ClearLines (0, gScreenDimensions.RightColumn, 0, gScreenDimensions.BottomRow, KEYHELP_BACKGROUND);
98     gLibIsFirstForm = FALSE;
99   }
100 
101   //
102   // Don't print frame for modal form.
103   //
104   if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
105     return EFI_SUCCESS;
106   }
107 
108   if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
109     PrintBannerInfo (FormData);
110   }
111 
112   PrintFramework (FormData);
113 
114   UpdateStatusBar(NV_UPDATE_REQUIRED, FormData->SettingChangedFlag);
115 
116   return EFI_SUCCESS;
117 }
118 
119 /**
120   This function updates customized key panel's help information.
121   The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.
122   and arrange them in Footer panel.
123 
124   @param[in]  FormData       Form Data to be shown in Page. FormData has the highlighted statement.
125   @param[in]  Statement      The statement current selected.
126   @param[in]  Selected       Whether or not a tag be selected. TRUE means Enter has hit this question.
127 **/
128 VOID
129 EFIAPI
RefreshKeyHelp(IN FORM_DISPLAY_ENGINE_FORM * FormData,IN FORM_DISPLAY_ENGINE_STATEMENT * Statement,IN BOOLEAN Selected)130 RefreshKeyHelp (
131   IN FORM_DISPLAY_ENGINE_FORM      *FormData,
132   IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
133   IN  BOOLEAN                      Selected
134   )
135 {
136   UINTN                  SecCol;
137   UINTN                  ThdCol;
138   UINTN                  RightColumnOfHelp;
139   UINTN                  TopRowOfHelp;
140   UINTN                  BottomRowOfHelp;
141   UINTN                  StartColumnOfHelp;
142   EFI_IFR_NUMERIC        *NumericOp;
143   EFI_IFR_DATE           *DateOp;
144   EFI_IFR_TIME           *TimeOp;
145   BOOLEAN                HexDisplay;
146   UINTN                  ColumnWidth1;
147   UINTN                  ColumnWidth2;
148   UINTN                  ColumnWidth3;
149   CHAR16                 *ColumnStr1;
150   CHAR16                 *ColumnStr2;
151   CHAR16                 *ColumnStr3;
152 
153   ASSERT (FormData != NULL);
154   if (FormData == NULL) {
155     return;
156   }
157 
158   gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
159 
160   if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
161     return;
162   }
163 
164   SecCol            = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3;
165   ThdCol            = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3 * 2;
166 
167   //
168   // + 2 means leave 1 space before the first hotkey info.
169   //
170   StartColumnOfHelp = gScreenDimensions.LeftColumn + 2;
171   RightColumnOfHelp = gScreenDimensions.RightColumn - 1;
172   TopRowOfHelp      = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
173   BottomRowOfHelp   = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;
174 
175   ColumnWidth1      = SecCol - StartColumnOfHelp;
176   ColumnWidth2      = ThdCol - SecCol;
177   ColumnWidth3      = RightColumnOfHelp - ThdCol;
178   ColumnStr1        = gLibEmptyString;
179   ColumnStr2        = gLibEmptyString;
180   ColumnStr3        = gLibEmptyString;
181 
182   //
183   // Clean the space at gScreenDimensions.LeftColumn + 1.
184   //
185   PrintStringAtWithWidth (StartColumnOfHelp - 1, BottomRowOfHelp, gLibEmptyString, 1);
186   PrintStringAtWithWidth (StartColumnOfHelp - 1, TopRowOfHelp, gLibEmptyString, 1);
187 
188   if (Statement == NULL) {
189     //
190     // Print Key for Form without showable statement.
191     //
192     PrintHotKeyHelpString (FormData, TRUE);
193     PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1);
194     PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gLibEmptyString, ColumnWidth2);
195     PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1);
196     if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
197       ColumnStr3 = gEscapeString;
198     }
199     PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
200 
201     return;
202   }
203 
204   HexDisplay = FALSE;
205   NumericOp = NULL;
206   DateOp    = NULL;
207   TimeOp    = NULL;
208   if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
209     NumericOp = (EFI_IFR_NUMERIC *) Statement->OpCode;
210     HexDisplay = (NumericOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
211   } else if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
212     DateOp   = (EFI_IFR_DATE *) Statement->OpCode;
213     HexDisplay = (DateOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
214   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
215     TimeOp  = (EFI_IFR_TIME *) Statement->OpCode;
216     HexDisplay = (TimeOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
217   }
218   switch (Statement->OpCode->OpCode) {
219   case EFI_IFR_ORDERED_LIST_OP:
220   case EFI_IFR_ONE_OF_OP:
221   case EFI_IFR_NUMERIC_OP:
222   case EFI_IFR_TIME_OP:
223   case EFI_IFR_DATE_OP:
224     if (!Selected) {
225       PrintHotKeyHelpString (FormData, TRUE);
226 
227       if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
228         ColumnStr3 = gEscapeString;
229       }
230       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
231 
232       if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
233           (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
234         PrintAt (
235           ColumnWidth1,
236           StartColumnOfHelp,
237           BottomRowOfHelp,
238           L"%c%c%c%c%s",
239           ARROW_UP,
240           ARROW_DOWN,
241           ARROW_RIGHT,
242           ARROW_LEFT,
243           gMoveHighlight
244           );
245         PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2);
246         PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber, ColumnWidth1);
247       } else {
248         PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
249         if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP && NumericOp != NULL && LibGetFieldFromNum(Statement->OpCode) != 0) {
250           ColumnStr1 = gAdjustNumber;
251         }
252         PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
253         PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2);
254       }
255     } else {
256       PrintHotKeyHelpString (FormData, FALSE);
257       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterCommitString, ColumnWidth2);
258 
259       //
260       // If it is a selected numeric with manual input, display different message
261       //
262       if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) ||
263           (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
264           (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
265         ColumnStr2 = HexDisplay ? gHexNumericInput : gDecNumericInput;
266         PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1);
267       } else {
268         PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
269       }
270 
271       if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
272         ColumnStr1 = gPlusString;
273         ColumnStr3 = gMinusString;
274       }
275       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
276       PrintStringAtWithWidth (ThdCol, TopRowOfHelp, ColumnStr3, ColumnWidth3);
277       PrintStringAtWithWidth (SecCol, TopRowOfHelp, ColumnStr2, ColumnWidth2);
278 
279       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, gEnterEscapeString, ColumnWidth3);
280     }
281     break;
282 
283   case EFI_IFR_CHECKBOX_OP:
284     PrintHotKeyHelpString (FormData, TRUE);
285 
286     if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
287       ColumnStr3 = gEscapeString;
288     }
289     PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
290 
291     PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
292     PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gToggleCheckBox, ColumnWidth2);
293     PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1);
294     break;
295 
296   case EFI_IFR_REF_OP:
297   case EFI_IFR_PASSWORD_OP:
298   case EFI_IFR_STRING_OP:
299   case EFI_IFR_TEXT_OP:
300   case EFI_IFR_ACTION_OP:
301   case EFI_IFR_RESET_BUTTON_OP:
302   case EFI_IFR_SUBTITLE_OP:
303      if (!Selected) {
304       PrintHotKeyHelpString (FormData, TRUE);
305 
306       if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
307         ColumnStr3 = gEscapeString;
308       }
309       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
310 
311       PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
312       if (Statement->OpCode->OpCode != EFI_IFR_TEXT_OP && Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP) {
313         ColumnStr2 = gEnterString;
314       }
315       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2);
316       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
317     } else {
318       PrintHotKeyHelpString (FormData, FALSE);
319       if (Statement->OpCode->OpCode != EFI_IFR_REF_OP) {
320         ColumnStr2 = gEnterCommitString;
321         ColumnStr3 = gEnterEscapeString;
322       }
323       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
324       PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, ColumnStr1, ColumnWidth1);
325       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2);
326       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
327     }
328     break;
329 
330   default:
331     break;
332   }
333 }
334 
335 /**
336   Update status bar.
337 
338   This function updates the status bar on the bottom of menu screen. It just shows StatusBar.
339   Original logic in this function should be splitted out.
340 
341   @param[in]  MessageType            The type of message to be shown. InputError or Configuration Changed.
342   @param[in]  State                  Show or Clear Message.
343 **/
344 VOID
345 EFIAPI
UpdateStatusBar(IN UINTN MessageType,IN BOOLEAN State)346 UpdateStatusBar (
347   IN  UINTN                  MessageType,
348   IN  BOOLEAN                State
349   )
350 {
351   UINTN           Index;
352   CHAR16          OptionWidth;
353 
354   OptionWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
355 
356   switch (MessageType) {
357   case INPUT_ERROR:
358     if (State) {
359       gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
360       PrintStringAt (
361         gScreenDimensions.LeftColumn + OptionWidth,
362         gScreenDimensions.BottomRow - 1,
363         gInputErrorMessage
364         );
365     } else {
366       gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
367       for (Index = 0; Index < (LibGetStringWidth (gInputErrorMessage) - 2) / 2; Index++) {
368         PrintStringAt (gScreenDimensions.LeftColumn + OptionWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");
369       }
370     }
371     break;
372 
373   case NV_UPDATE_REQUIRED:
374     //
375     // Global setting support. Show configuration change on every form.
376     //
377     if (State) {
378       gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
379       PrintStringAt (
380         gScreenDimensions.LeftColumn + OptionWidth * 2,
381         gScreenDimensions.BottomRow - 1,
382         gNvUpdateMessage
383         );
384     } else {
385       gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
386       for (Index = 0; Index < (LibGetStringWidth (gNvUpdateMessage) - 2) / 2; Index++) {
387         PrintStringAt (
388           (gScreenDimensions.LeftColumn + OptionWidth * 2 + Index),
389           gScreenDimensions.BottomRow - 1,
390           L"  "
391           );
392       }
393     }
394     break;
395 
396   default:
397     break;
398   }
399 }
400 
401 /**
402   Create popup window. It will replace CreateDialog().
403 
404   This function draws OEM/Vendor specific pop up windows.
405 
406   @param[out]  Key    User Input Key
407   @param       ...    String to be shown in Popup. The variable argument list is terminated by a NULL.
408 
409 **/
410 VOID
411 EFIAPI
CreateDialog(OUT EFI_INPUT_KEY * Key,OPTIONAL...)412 CreateDialog (
413   OUT EFI_INPUT_KEY  *Key,        OPTIONAL
414   ...
415   )
416 {
417   VA_LIST       Marker;
418   EFI_INPUT_KEY KeyValue;
419   EFI_STATUS    Status;
420   UINTN         LargestString;
421   UINTN         LineNum;
422   UINTN   Index;
423   UINTN   Count;
424   CHAR16  Character;
425   UINTN   Start;
426   UINTN   End;
427   UINTN   Top;
428   UINTN   Bottom;
429   CHAR16  *String;
430   UINTN   DimensionsWidth;
431   UINTN   DimensionsHeight;
432   UINTN   CurrentAttribute;
433   BOOLEAN CursorVisible;
434 
435   //
436   // If screen dimension info is not ready, get it from console.
437   //
438   if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) {
439     ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
440     gST->ConOut->QueryMode (
441                    gST->ConOut,
442                    gST->ConOut->Mode->Mode,
443                    &gScreenDimensions.RightColumn,
444                    &gScreenDimensions.BottomRow
445                    );
446   }
447 
448   DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
449   DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
450 
451   LargestString = 0;
452   LineNum       = 0;
453   VA_START (Marker, Key);
454   while  ((String = VA_ARG (Marker, CHAR16 *)) != NULL) {
455     LineNum ++;
456 
457     if ((LibGetStringWidth (String) / 2) > LargestString) {
458       LargestString = (LibGetStringWidth (String) / 2);
459     }
460   }
461   VA_END (Marker);
462 
463   if ((LargestString + 2) > DimensionsWidth) {
464     LargestString = DimensionsWidth - 2;
465   }
466 
467   CurrentAttribute  = gST->ConOut->Mode->Attribute;
468   CursorVisible     = gST->ConOut->Mode->CursorVisible;
469   gST->ConOut->EnableCursor (gST->ConOut, FALSE);
470   gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
471 
472   //
473   // Subtract the PopUp width from total Columns, allow for one space extra on
474   // each end plus a border.
475   //
476   Start     = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
477   End       = Start + LargestString + 1;
478 
479   Top       = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1;
480   Bottom    = Top + LineNum + 2;
481 
482   Character = BOXDRAW_DOWN_RIGHT;
483   PrintCharAt (Start, Top, Character);
484   Character = BOXDRAW_HORIZONTAL;
485   for (Index = Start; Index + 2 < End; Index++) {
486     PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
487   }
488 
489   Character = BOXDRAW_DOWN_LEFT;
490   PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
491   Character = BOXDRAW_VERTICAL;
492 
493   Count = 0;
494   VA_START (Marker, Key);
495   for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
496     String = VA_ARG (Marker, CHAR16*);
497 
498     if (String[0] == CHAR_NULL) {
499       //
500       // Passing in a NULL results in a blank space
501       //
502       ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
503     } else if (String[0] == L' ') {
504       //
505       // Passing in a space results in the assumption that this is where typing will occur
506       //
507       ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
508       PrintStringAt (
509         ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
510         Index + 1,
511         String + 1
512         );
513     } else {
514       //
515       // This will clear the background of the line - we never know who might have been
516       // here before us.  This differs from the next clear in that it used the non-reverse
517       // video for normal printing.
518       //
519       ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
520       PrintStringAt (
521         ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
522         Index + 1,
523         String
524         );
525     }
526 
527     gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
528     PrintCharAt (Start, Index + 1, Character);
529     PrintCharAt (End - 1, Index + 1, Character);
530   }
531   VA_END (Marker);
532 
533   Character = BOXDRAW_UP_RIGHT;
534   PrintCharAt (Start, Bottom - 1, Character);
535   Character = BOXDRAW_HORIZONTAL;
536   for (Index = Start; Index + 2 < End; Index++) {
537     PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
538   }
539 
540   Character = BOXDRAW_UP_LEFT;
541   PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
542 
543   if (Key != NULL) {
544     Status = WaitForKeyStroke (&KeyValue);
545     ASSERT_EFI_ERROR (Status);
546     CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY));
547   }
548 
549   gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
550   gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
551 }
552 
553 /**
554   Confirm how to handle the changed data.
555 
556   @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.
557 **/
558 UINTN
559 EFIAPI
ConfirmDataChange(VOID)560 ConfirmDataChange (
561   VOID
562   )
563 {
564   CHAR16                  YesResponse;
565   CHAR16                  NoResponse;
566   EFI_INPUT_KEY           Key;
567 
568   gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
569 
570   YesResponse = gYesResponse[0];
571   NoResponse  = gNoResponse[0];
572 
573   //
574   // If NV flag is up, prompt user
575   //
576   do {
577     CreateDialog (&Key, gLibEmptyString, gSaveChanges, gAreYouSure, gLibEmptyString, NULL);
578   } while
579   (
580     (Key.ScanCode != SCAN_ESC) &&
581     ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
582     ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
583   );
584 
585   if (Key.ScanCode == SCAN_ESC) {
586     return BROWSER_ACTION_NONE;
587   } else if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
588     return BROWSER_ACTION_SUBMIT;
589   } else {
590     return BROWSER_ACTION_DISCARD;
591   }
592 }
593 
594 /**
595   OEM specifies whether Setup exits Page by ESC key.
596 
597   This function customized the behavior that whether Setup exits Page so that
598   system able to boot when configuration is not changed.
599 
600   @retval  TRUE     Exits FrontPage
601   @retval  FALSE    Don't exit FrontPage.
602 **/
603 BOOLEAN
604 EFIAPI
FormExitPolicy(VOID)605 FormExitPolicy (
606   VOID
607   )
608 {
609   return gClassOfVfr == FORMSET_CLASS_FRONT_PAGE ? FALSE : TRUE;
610 }
611 
612 /**
613   Set Timeout value for a ceratain Form to get user response.
614 
615   This function allows to set timeout value on a ceratain form if necessary.
616   If timeout is not zero, the form will exit if user has no response in timeout.
617 
618   @param[in]  FormData   Form Data to be shown in Page
619 
620   @return 0     No timeout for this form.
621   @return > 0   Timeout value in 100 ns units.
622 **/
623 UINT64
624 EFIAPI
FormExitTimeout(IN FORM_DISPLAY_ENGINE_FORM * FormData)625 FormExitTimeout (
626   IN FORM_DISPLAY_ENGINE_FORM      *FormData
627   )
628 {
629   return 0;
630 }
631 //
632 // Print Functions
633 //
634 /**
635   Prints a unicode string to the default console, at
636   the supplied cursor position, using L"%s" format.
637 
638   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
639   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
640   @param  String     String pointer.
641 
642   @return Length of string printed to the console
643 
644 **/
645 UINTN
646 EFIAPI
PrintStringAt(IN UINTN Column,IN UINTN Row,IN CHAR16 * String)647 PrintStringAt (
648   IN UINTN     Column,
649   IN UINTN     Row,
650   IN CHAR16    *String
651   )
652 {
653   return PrintAt (0, Column, Row, L"%s", String);
654 }
655 
656 /**
657   Prints a unicode string to the default console, at
658   the supplied cursor position, using L"%s" format.
659 
660   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
661   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
662   @param  String     String pointer.
663   @param  Width      Width for String.
664 
665   @return Length of string printed to the console
666 
667 **/
668 UINTN
669 EFIAPI
PrintStringAtWithWidth(IN UINTN Column,IN UINTN Row,IN CHAR16 * String,IN UINTN Width)670 PrintStringAtWithWidth (
671   IN UINTN     Column,
672   IN UINTN     Row,
673   IN CHAR16    *String,
674   IN UINTN     Width
675   )
676 {
677   return PrintAt (Width, Column, Row, L"%s", String);
678 }
679 
680 /**
681   Prints a character to the default console, at
682   the supplied cursor position, using L"%c" format.
683 
684   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
685   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
686   @param  Character  Character to print.
687 
688   @return Length of string printed to the console.
689 
690 **/
691 UINTN
692 EFIAPI
PrintCharAt(IN UINTN Column,IN UINTN Row,CHAR16 Character)693 PrintCharAt (
694   IN UINTN     Column,
695   IN UINTN     Row,
696   CHAR16       Character
697   )
698 {
699   return PrintAt (0, Column, Row, L"%c", Character);
700 }
701 
702 /**
703   Clear retangle with specified text attribute.
704 
705   @param  LeftColumn     Left column of retangle.
706   @param  RightColumn    Right column of retangle.
707   @param  TopRow         Start row of retangle.
708   @param  BottomRow      End row of retangle.
709   @param  TextAttribute  The character foreground and background.
710 
711 **/
712 VOID
713 EFIAPI
ClearLines(IN UINTN LeftColumn,IN UINTN RightColumn,IN UINTN TopRow,IN UINTN BottomRow,IN UINTN TextAttribute)714 ClearLines (
715   IN UINTN               LeftColumn,
716   IN UINTN               RightColumn,
717   IN UINTN               TopRow,
718   IN UINTN               BottomRow,
719   IN UINTN               TextAttribute
720   )
721 {
722   CHAR16  *Buffer;
723   UINTN   Row;
724 
725   //
726   // For now, allocate an arbitrarily long buffer
727   //
728   Buffer = AllocateZeroPool (0x10000);
729   ASSERT (Buffer != NULL);
730 
731   //
732   // Set foreground and background as defined
733   //
734   gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
735 
736   //
737   // Much faster to buffer the long string instead of print it a character at a time
738   //
739   LibSetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
740 
741   //
742   // Clear the desired area with the appropriate foreground/background
743   //
744   for (Row = TopRow; Row <= BottomRow; Row++) {
745     PrintStringAt (LeftColumn, Row, Buffer);
746   }
747 
748   gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
749 
750   FreePool (Buffer);
751 }
752 
753 //
754 // Color Setting Functions
755 //
756 
757 /**
758   Get OEM/Vendor specific popup attribute colors.
759 
760   @retval  Byte code color setting for popup color.
761 **/
762 UINT8
763 EFIAPI
GetPopupColor(VOID)764 GetPopupColor (
765   VOID
766   )
767 {
768   return POPUP_TEXT | POPUP_BACKGROUND;
769 }
770 
771 /**
772   Get OEM/Vendor specific popup attribute colors.
773 
774   @retval  Byte code color setting for popup inverse color.
775 **/
776 UINT8
777 EFIAPI
GetPopupInverseColor(VOID)778 GetPopupInverseColor (
779   VOID
780   )
781 {
782   return POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND;
783 }
784 
785 /**
786   Get OEM/Vendor specific PickList color attribute.
787 
788   @retval  Byte code color setting for pick list color.
789 **/
790 UINT8
791 EFIAPI
GetPickListColor(VOID)792 GetPickListColor (
793   VOID
794   )
795 {
796   return PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND;
797 }
798 
799 /**
800   Get OEM/Vendor specific arrow color attribute.
801 
802   @retval  Byte code color setting for arrow color.
803 **/
804 UINT8
805 EFIAPI
GetArrowColor(VOID)806 GetArrowColor (
807   VOID
808   )
809 {
810   return ARROW_TEXT | ARROW_BACKGROUND;
811 }
812 
813 /**
814   Get OEM/Vendor specific info text color attribute.
815 
816   @retval  Byte code color setting for info text color.
817 **/
818 UINT8
819 EFIAPI
GetInfoTextColor(VOID)820 GetInfoTextColor (
821   VOID
822   )
823 {
824   return INFO_TEXT | FIELD_BACKGROUND;
825 }
826 
827 /**
828   Get OEM/Vendor specific help text color attribute.
829 
830   @retval  Byte code color setting for help text color.
831 **/
832 UINT8
833 EFIAPI
GetHelpTextColor(VOID)834 GetHelpTextColor (
835   VOID
836   )
837 {
838   return HELP_TEXT | FIELD_BACKGROUND;
839 }
840 
841 /**
842   Get OEM/Vendor specific grayed out text color attribute.
843 
844   @retval  Byte code color setting for grayed out text color.
845 **/
846 UINT8
847 EFIAPI
GetGrayedTextColor(VOID)848 GetGrayedTextColor (
849   VOID
850   )
851 {
852   return FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
853 }
854 
855 /**
856   Get OEM/Vendor specific highlighted text color attribute.
857 
858   @retval  Byte code color setting for highlight text color.
859 **/
860 UINT8
861 EFIAPI
GetHighlightTextColor(VOID)862 GetHighlightTextColor (
863   VOID
864   )
865 {
866   return PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);
867 }
868 
869 /**
870   Get OEM/Vendor specific field text color attribute.
871 
872   @retval  Byte code color setting for field text color.
873 **/
874 UINT8
875 EFIAPI
GetFieldTextColor(VOID)876 GetFieldTextColor (
877   VOID
878   )
879 {
880   return PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
881 }
882 
883 /**
884   Get OEM/Vendor specific subtitle text color attribute.
885 
886   @retval  Byte code color setting for subtitle text color.
887 **/
888 UINT8
889 EFIAPI
GetSubTitleTextColor(VOID)890 GetSubTitleTextColor (
891   VOID
892   )
893 {
894   return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND;
895 }
896 
897 /**
898   Clear Screen to the initial state.
899 **/
900 VOID
901 EFIAPI
ClearDisplayPage(VOID)902 ClearDisplayPage (
903   VOID
904   )
905 {
906   gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
907   gST->ConOut->ClearScreen (gST->ConOut);
908   gLibIsFirstForm = TRUE;
909 }
910 
911 /**
912   Constructor of Customized Display Library Instance.
913 
914   @param  ImageHandle   The firmware allocated handle for the EFI image.
915   @param  SystemTable   A pointer to the EFI System Table.
916 
917   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
918 
919 **/
920 EFI_STATUS
921 EFIAPI
CustomizedDisplayLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)922 CustomizedDisplayLibConstructor (
923   IN      EFI_HANDLE                ImageHandle,
924   IN      EFI_SYSTEM_TABLE          *SystemTable
925   )
926 {
927   mCDLStringPackHandle = HiiAddPackages (&gCustomizedDisplayLibGuid, ImageHandle, CustomizedDisplayLibStrings, NULL);
928   ASSERT (mCDLStringPackHandle != NULL);
929 
930   InitializeLibStrings();
931 
932   return EFI_SUCCESS;
933 }
934 
935 /**
936   Destructor of Customized Display Library Instance.
937 
938   @param  ImageHandle   The firmware allocated handle for the EFI image.
939   @param  SystemTable   A pointer to the EFI System Table.
940 
941   @retval EFI_SUCCESS   The destructor completed successfully.
942   @retval Other value   The destructor did not complete successfully.
943 
944 **/
945 EFI_STATUS
946 EFIAPI
CustomizedDisplayLibDestructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)947 CustomizedDisplayLibDestructor (
948   IN EFI_HANDLE        ImageHandle,
949   IN EFI_SYSTEM_TABLE  *SystemTable
950   )
951 {
952   HiiRemovePackages(mCDLStringPackHandle);
953 
954   FreeLibStrings ();
955 
956   return EFI_SUCCESS;
957 }
958 
959