1/** @file
2
3  This library class defines a set of interfaces to customize Display module
4
5Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
6This program and the accompanying materials are licensed and made available under
7the terms and conditions of the BSD License that accompanies this distribution.
8The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php.
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15#include "CustomizedDisplayLibInternal.h"
16
17EFI_GUID          gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } };
18
19EFI_HII_HANDLE    mCDLStringPackHandle;
20UINT16            gClassOfVfr;                 // Formset class information
21BOOLEAN           gLibIsFirstForm = TRUE;
22BANNER_DATA       *gBannerData;
23
24UINTN             gFooterHeight;
25
26/**
27+------------------------------------------------------------------------------+
28|                                 Setup Page                                   |
29+------------------------------------------------------------------------------+
30
31Statement
32Statement
33Statement
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**/
57EFI_STATUS
58EFIAPI
59DisplayPageFrame (
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**/
128VOID
129EFIAPI
130RefreshKeyHelp (
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**/
344VOID
345EFIAPI
346UpdateStatusBar (
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**/
410VOID
411EFIAPI
412CreateDialog (
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**/
558UINTN
559EFIAPI
560ConfirmDataChange (
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**/
603BOOLEAN
604EFIAPI
605FormExitPolicy (
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**/
623UINT64
624EFIAPI
625FormExitTimeout (
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**/
645UINTN
646EFIAPI
647PrintStringAt (
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**/
668UINTN
669EFIAPI
670PrintStringAtWithWidth (
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**/
691UINTN
692EFIAPI
693PrintCharAt (
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**/
712VOID
713EFIAPI
714ClearLines (
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**/
762UINT8
763EFIAPI
764GetPopupColor (
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**/
776UINT8
777EFIAPI
778GetPopupInverseColor (
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**/
790UINT8
791EFIAPI
792GetPickListColor (
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**/
804UINT8
805EFIAPI
806GetArrowColor (
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**/
818UINT8
819EFIAPI
820GetInfoTextColor (
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**/
832UINT8
833EFIAPI
834GetHelpTextColor (
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**/
846UINT8
847EFIAPI
848GetGrayedTextColor (
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**/
860UINT8
861EFIAPI
862GetHighlightTextColor (
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**/
874UINT8
875EFIAPI
876GetFieldTextColor (
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**/
888UINT8
889EFIAPI
890GetSubTitleTextColor (
891  VOID
892  )
893{
894  return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND;
895}
896
897/**
898  Clear Screen to the initial state.
899**/
900VOID
901EFIAPI
902ClearDisplayPage (
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**/
920EFI_STATUS
921EFIAPI
922CustomizedDisplayLibConstructor (
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**/
945EFI_STATUS
946EFIAPI
947CustomizedDisplayLibDestructor (
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