1 /** @file
2   This is the main routine for initializing the Graphics Console support routines.
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "GraphicsConsole.h"
10 
11 //
12 // Graphics Console Device Private Data template
13 //
14 GRAPHICS_CONSOLE_DEV    mGraphicsConsoleDevTemplate = {
15   GRAPHICS_CONSOLE_DEV_SIGNATURE,
16   (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL,
17   (EFI_UGA_DRAW_PROTOCOL *) NULL,
18   {
19     GraphicsConsoleConOutReset,
20     GraphicsConsoleConOutOutputString,
21     GraphicsConsoleConOutTestString,
22     GraphicsConsoleConOutQueryMode,
23     GraphicsConsoleConOutSetMode,
24     GraphicsConsoleConOutSetAttribute,
25     GraphicsConsoleConOutClearScreen,
26     GraphicsConsoleConOutSetCursorPosition,
27     GraphicsConsoleConOutEnableCursor,
28     (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
29   },
30   {
31     0,
32     -1,
33     EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK),
34     0,
35     0,
36     TRUE
37   },
38   (GRAPHICS_CONSOLE_MODE_DATA *) NULL,
39   (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL
40 };
41 
42 GRAPHICS_CONSOLE_MODE_DATA mGraphicsConsoleModeData[] = {
43   {100, 31},
44   //
45   // New modes can be added here.
46   // The last entry is specific for full screen mode.
47   //
48   {0, 0}
49 };
50 
51 EFI_HII_DATABASE_PROTOCOL   *mHiiDatabase;
52 EFI_HII_FONT_PROTOCOL       *mHiiFont;
53 EFI_HII_HANDLE              mHiiHandle;
54 VOID                        *mHiiRegistration;
55 
56 EFI_GUID             mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, {0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad}};
57 
58 CHAR16               mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
59 
60 EFI_GRAPHICS_OUTPUT_BLT_PIXEL        mGraphicsEfiColors[16] = {
61   //
62   // B    G    R   reserved
63   //
64   {0x00, 0x00, 0x00, 0x00},  // BLACK
65   {0x98, 0x00, 0x00, 0x00},  // LIGHTBLUE
66   {0x00, 0x98, 0x00, 0x00},  // LIGHGREEN
67   {0x98, 0x98, 0x00, 0x00},  // LIGHCYAN
68   {0x00, 0x00, 0x98, 0x00},  // LIGHRED
69   {0x98, 0x00, 0x98, 0x00},  // MAGENTA
70   {0x00, 0x98, 0x98, 0x00},  // BROWN
71   {0x98, 0x98, 0x98, 0x00},  // LIGHTGRAY
72   {0x30, 0x30, 0x30, 0x00},  // DARKGRAY - BRIGHT BLACK
73   {0xff, 0x00, 0x00, 0x00},  // BLUE
74   {0x00, 0xff, 0x00, 0x00},  // LIME
75   {0xff, 0xff, 0x00, 0x00},  // CYAN
76   {0x00, 0x00, 0xff, 0x00},  // RED
77   {0xff, 0x00, 0xff, 0x00},  // FUCHSIA
78   {0x00, 0xff, 0xff, 0x00},  // YELLOW
79   {0xff, 0xff, 0xff, 0x00}   // WHITE
80 };
81 
82 EFI_NARROW_GLYPH     mCursorGlyph = {
83   0x0000,
84   0x00,
85   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
86 };
87 
88 CHAR16       SpaceStr[] = { NARROW_CHAR, ' ', 0 };
89 
90 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {
91   GraphicsConsoleControllerDriverSupported,
92   GraphicsConsoleControllerDriverStart,
93   GraphicsConsoleControllerDriverStop,
94   0xa,
95   NULL,
96   NULL
97 };
98 
99 /**
100   Test to see if Graphics Console could be supported on the Controller.
101 
102   Graphics Console could be supported if Graphics Output Protocol or UGA Draw
103   Protocol exists on the Controller. (UGA Draw Protocol could be skipped
104   if PcdUgaConsumeSupport is set to FALSE.)
105 
106   @param  This                Protocol instance pointer.
107   @param  Controller          Handle of device to test.
108   @param  RemainingDevicePath Optional parameter use to pick a specific child
109                               device to start.
110 
111   @retval EFI_SUCCESS         This driver supports this device.
112   @retval other               This driver does not support this device.
113 
114 **/
115 EFI_STATUS
116 EFIAPI
GraphicsConsoleControllerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)117 GraphicsConsoleControllerDriverSupported (
118   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
119   IN EFI_HANDLE                     Controller,
120   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
121   )
122 {
123   EFI_STATUS                   Status;
124   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
125   EFI_UGA_DRAW_PROTOCOL        *UgaDraw;
126   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
127 
128   GraphicsOutput = NULL;
129   UgaDraw        = NULL;
130   //
131   // Open the IO Abstraction(s) needed to perform the supported test
132   //
133   Status = gBS->OpenProtocol (
134                   Controller,
135                   &gEfiGraphicsOutputProtocolGuid,
136                   (VOID **) &GraphicsOutput,
137                   This->DriverBindingHandle,
138                   Controller,
139                   EFI_OPEN_PROTOCOL_BY_DRIVER
140                   );
141 
142   if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
143     //
144     // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
145     //
146     Status = gBS->OpenProtocol (
147                     Controller,
148                     &gEfiUgaDrawProtocolGuid,
149                     (VOID **) &UgaDraw,
150                     This->DriverBindingHandle,
151                     Controller,
152                     EFI_OPEN_PROTOCOL_BY_DRIVER
153                     );
154   }
155   if (EFI_ERROR (Status)) {
156     return Status;
157   }
158 
159   //
160   // We need to ensure that we do not layer on top of a virtual handle.
161   // We need to ensure that the handles produced by the conspliter do not
162   // get used.
163   //
164   Status = gBS->OpenProtocol (
165                   Controller,
166                   &gEfiDevicePathProtocolGuid,
167                   (VOID **) &DevicePath,
168                   This->DriverBindingHandle,
169                   Controller,
170                   EFI_OPEN_PROTOCOL_BY_DRIVER
171                   );
172   if (!EFI_ERROR (Status)) {
173     gBS->CloseProtocol (
174           Controller,
175           &gEfiDevicePathProtocolGuid,
176           This->DriverBindingHandle,
177           Controller
178           );
179   } else {
180     goto Error;
181   }
182 
183   //
184   // Does Hii Exist?  If not, we aren't ready to run
185   //
186   Status = EfiLocateHiiProtocol ();
187 
188   //
189   // Close the I/O Abstraction(s) used to perform the supported test
190   //
191 Error:
192   if (GraphicsOutput != NULL) {
193     gBS->CloseProtocol (
194           Controller,
195           &gEfiGraphicsOutputProtocolGuid,
196           This->DriverBindingHandle,
197           Controller
198           );
199   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
200     gBS->CloseProtocol (
201           Controller,
202           &gEfiUgaDrawProtocolGuid,
203           This->DriverBindingHandle,
204           Controller
205           );
206   }
207   return Status;
208 }
209 
210 /**
211   Initialize all the text modes which the graphics console supports.
212 
213   It returns information for available text modes that the graphics can support.
214 
215   @param[in]  HorizontalResolution     The size of video screen in pixels in the X dimension.
216   @param[in]  VerticalResolution       The size of video screen in pixels in the Y dimension.
217   @param[in]  GopModeNumber            The graphics mode number which graphis console is based on.
218   @param[out] TextModeCount            The total number of text modes that graphics console supports.
219   @param[out] TextModeData             The buffer to the text modes column and row information.
220                                        Caller is responsible to free it when it's non-NULL.
221 
222   @retval EFI_SUCCESS                  The supporting mode information is returned.
223   @retval EFI_INVALID_PARAMETER        The parameters are invalid.
224 
225 **/
226 EFI_STATUS
InitializeGraphicsConsoleTextMode(IN UINT32 HorizontalResolution,IN UINT32 VerticalResolution,IN UINT32 GopModeNumber,OUT UINTN * TextModeCount,OUT GRAPHICS_CONSOLE_MODE_DATA ** TextModeData)227 InitializeGraphicsConsoleTextMode (
228   IN UINT32                        HorizontalResolution,
229   IN UINT32                        VerticalResolution,
230   IN UINT32                        GopModeNumber,
231   OUT UINTN                        *TextModeCount,
232   OUT GRAPHICS_CONSOLE_MODE_DATA   **TextModeData
233   )
234 {
235   UINTN                       Index;
236   UINTN                       Count;
237   GRAPHICS_CONSOLE_MODE_DATA  *ModeBuffer;
238   GRAPHICS_CONSOLE_MODE_DATA  *NewModeBuffer;
239   UINTN                       ValidCount;
240   UINTN                       ValidIndex;
241   UINTN                       MaxColumns;
242   UINTN                       MaxRows;
243 
244   if ((TextModeCount == NULL) || (TextModeData == NULL)) {
245     return EFI_INVALID_PARAMETER;
246   }
247 
248   Count = sizeof (mGraphicsConsoleModeData) / sizeof (GRAPHICS_CONSOLE_MODE_DATA);
249 
250   //
251   // Compute the maximum number of text Rows and Columns that this current graphics mode can support.
252   // To make graphics console work well, MaxColumns and MaxRows should not be zero.
253   //
254   MaxColumns = HorizontalResolution / EFI_GLYPH_WIDTH;
255   MaxRows    = VerticalResolution / EFI_GLYPH_HEIGHT;
256 
257   //
258   // According to UEFI spec, all output devices support at least 80x25 text mode.
259   //
260   ASSERT ((MaxColumns >= 80) && (MaxRows >= 25));
261 
262   //
263   // Add full screen mode to the last entry.
264   //
265   mGraphicsConsoleModeData[Count - 1].Columns = MaxColumns;
266   mGraphicsConsoleModeData[Count - 1].Rows    = MaxRows;
267 
268   //
269   // Get defined mode buffer pointer.
270   //
271   ModeBuffer = mGraphicsConsoleModeData;
272 
273   //
274   // Here we make sure that the final mode exposed does not include the duplicated modes,
275   // and does not include the invalid modes which exceed the max column and row.
276   // Reserve 2 modes for 80x25, 80x50 of graphics console.
277   //
278   NewModeBuffer = AllocateZeroPool (sizeof (GRAPHICS_CONSOLE_MODE_DATA) * (Count + 2));
279   ASSERT (NewModeBuffer != NULL);
280 
281   //
282   // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.
283   //
284   ValidCount = 0;
285 
286   NewModeBuffer[ValidCount].Columns       = 80;
287   NewModeBuffer[ValidCount].Rows          = 25;
288   NewModeBuffer[ValidCount].GopWidth      = HorizontalResolution;
289   NewModeBuffer[ValidCount].GopHeight     = VerticalResolution;
290   NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
291   NewModeBuffer[ValidCount].DeltaX        = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1;
292   NewModeBuffer[ValidCount].DeltaY        = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1;
293   ValidCount++;
294 
295   if ((MaxColumns >= 80) && (MaxRows >= 50)) {
296     NewModeBuffer[ValidCount].Columns = 80;
297     NewModeBuffer[ValidCount].Rows    = 50;
298     NewModeBuffer[ValidCount].DeltaX  = (HorizontalResolution - (80 * EFI_GLYPH_WIDTH)) >> 1;
299     NewModeBuffer[ValidCount].DeltaY  = (VerticalResolution - (50 * EFI_GLYPH_HEIGHT)) >> 1;
300   }
301   NewModeBuffer[ValidCount].GopWidth      = HorizontalResolution;
302   NewModeBuffer[ValidCount].GopHeight     = VerticalResolution;
303   NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
304   ValidCount++;
305 
306   //
307   // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.
308   //
309   for (Index = 0; Index < Count; Index++) {
310     if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0) ||
311         (ModeBuffer[Index].Columns > MaxColumns) || (ModeBuffer[Index].Rows > MaxRows)) {
312       //
313       // Skip the pre-defined mode which is invalid or exceeds the max column and row.
314       //
315       continue;
316     }
317     for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {
318       if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&
319           (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {
320         //
321         // Skip the duplicated mode.
322         //
323         break;
324       }
325     }
326     if (ValidIndex == ValidCount) {
327       NewModeBuffer[ValidCount].Columns       = ModeBuffer[Index].Columns;
328       NewModeBuffer[ValidCount].Rows          = ModeBuffer[Index].Rows;
329       NewModeBuffer[ValidCount].GopWidth      = HorizontalResolution;
330       NewModeBuffer[ValidCount].GopHeight     = VerticalResolution;
331       NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber;
332       NewModeBuffer[ValidCount].DeltaX        = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1;
333       NewModeBuffer[ValidCount].DeltaY        = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1;
334       ValidCount++;
335     }
336   }
337 
338   DEBUG_CODE (
339     for (Index = 0; Index < ValidCount; Index++) {
340       DEBUG ((EFI_D_INFO, "Graphics - Mode %d, Column = %d, Row = %d\n",
341                            Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows));
342     }
343   );
344 
345   //
346   // Return valid mode count and mode information buffer.
347   //
348   *TextModeCount = ValidCount;
349   *TextModeData  = NewModeBuffer;
350   return EFI_SUCCESS;
351 }
352 
353 /**
354   Start this driver on Controller by opening Graphics Output protocol or
355   UGA Draw protocol, and installing Simple Text Out protocol on Controller.
356   (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
357 
358   @param  This                 Protocol instance pointer.
359   @param  Controller           Handle of device to bind driver to
360   @param  RemainingDevicePath  Optional parameter use to pick a specific child
361                                device to start.
362 
363   @retval EFI_SUCCESS          This driver is added to Controller.
364   @retval other                This driver does not support this device.
365 
366 **/
367 EFI_STATUS
368 EFIAPI
GraphicsConsoleControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)369 GraphicsConsoleControllerDriverStart (
370   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
371   IN EFI_HANDLE                     Controller,
372   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
373   )
374 {
375   EFI_STATUS                           Status;
376   GRAPHICS_CONSOLE_DEV                 *Private;
377   UINT32                               HorizontalResolution;
378   UINT32                               VerticalResolution;
379   UINT32                               ColorDepth;
380   UINT32                               RefreshRate;
381   UINT32                               ModeIndex;
382   UINTN                                MaxMode;
383   UINT32                               ModeNumber;
384   EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE    *Mode;
385   UINTN                                SizeOfInfo;
386   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
387 
388   ModeNumber = 0;
389 
390   //
391   // Initialize the Graphics Console device instance
392   //
393   Private = AllocateCopyPool (
394               sizeof (GRAPHICS_CONSOLE_DEV),
395               &mGraphicsConsoleDevTemplate
396               );
397   if (Private == NULL) {
398     return EFI_OUT_OF_RESOURCES;
399   }
400 
401   Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode);
402 
403   Status = gBS->OpenProtocol (
404                   Controller,
405                   &gEfiGraphicsOutputProtocolGuid,
406                   (VOID **) &Private->GraphicsOutput,
407                   This->DriverBindingHandle,
408                   Controller,
409                   EFI_OPEN_PROTOCOL_BY_DRIVER
410                   );
411 
412   if (EFI_ERROR(Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
413     Status = gBS->OpenProtocol (
414                     Controller,
415                     &gEfiUgaDrawProtocolGuid,
416                     (VOID **) &Private->UgaDraw,
417                     This->DriverBindingHandle,
418                     Controller,
419                     EFI_OPEN_PROTOCOL_BY_DRIVER
420                     );
421   }
422 
423   if (EFI_ERROR (Status)) {
424     goto Error;
425   }
426 
427   HorizontalResolution  = PcdGet32 (PcdVideoHorizontalResolution);
428   VerticalResolution    = PcdGet32 (PcdVideoVerticalResolution);
429 
430   if (Private->GraphicsOutput != NULL) {
431     //
432     // The console is build on top of Graphics Output Protocol, find the mode number
433     // for the user-defined mode; if there are multiple video devices,
434     // graphic console driver will set all the video devices to the same mode.
435     //
436     if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) {
437       //
438       // Find the highest resolution which GOP supports.
439       //
440       MaxMode = Private->GraphicsOutput->Mode->MaxMode;
441 
442       for (ModeIndex = 0; ModeIndex < MaxMode; ModeIndex++) {
443         Status = Private->GraphicsOutput->QueryMode (
444                            Private->GraphicsOutput,
445                            ModeIndex,
446                            &SizeOfInfo,
447                            &Info
448                            );
449         if (!EFI_ERROR (Status)) {
450           if ((Info->HorizontalResolution > HorizontalResolution) ||
451               ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution > VerticalResolution))) {
452             HorizontalResolution = Info->HorizontalResolution;
453             VerticalResolution   = Info->VerticalResolution;
454             ModeNumber           = ModeIndex;
455           }
456           FreePool (Info);
457         }
458       }
459       if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) {
460         Status = EFI_UNSUPPORTED;
461         goto Error;
462       }
463     } else {
464       //
465       // Use user-defined resolution
466       //
467       Status = CheckModeSupported (
468                    Private->GraphicsOutput,
469                    HorizontalResolution,
470                    VerticalResolution,
471                    &ModeNumber
472                    );
473       if (EFI_ERROR (Status)) {
474         //
475         // if not supporting current mode, try 800x600 which is required by UEFI/EFI spec
476         //
477         HorizontalResolution = 800;
478         VerticalResolution   = 600;
479         Status = CheckModeSupported (
480                      Private->GraphicsOutput,
481                      HorizontalResolution,
482                      VerticalResolution,
483                      &ModeNumber
484                      );
485         Mode = Private->GraphicsOutput->Mode;
486         if (EFI_ERROR (Status) && Mode->MaxMode != 0) {
487           //
488           // Set default mode failed or device don't support default mode, then get the current mode information
489           //
490           HorizontalResolution = Mode->Info->HorizontalResolution;
491           VerticalResolution = Mode->Info->VerticalResolution;
492           ModeNumber = Mode->Mode;
493         }
494       }
495     }
496     if (ModeNumber != Private->GraphicsOutput->Mode->Mode) {
497       //
498       // Current graphics mode is not set or is not set to the mode which we has found,
499       // set the new graphic mode.
500       //
501       Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber);
502       if (EFI_ERROR (Status)) {
503         //
504         // The mode set operation failed
505         //
506         goto Error;
507       }
508     }
509   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
510     //
511     // At first try to set user-defined resolution
512     //
513     ColorDepth            = 32;
514     RefreshRate           = 60;
515     Status = Private->UgaDraw->SetMode (
516                                 Private->UgaDraw,
517                                 HorizontalResolution,
518                                 VerticalResolution,
519                                 ColorDepth,
520                                 RefreshRate
521                                 );
522     if (EFI_ERROR (Status)) {
523       //
524       // Try to set 800*600 which is required by UEFI/EFI spec
525       //
526       Status = Private->UgaDraw->SetMode (
527                                   Private->UgaDraw,
528                                   800,
529                                   600,
530                                   ColorDepth,
531                                   RefreshRate
532                                   );
533       if (EFI_ERROR (Status)) {
534         Status = Private->UgaDraw->GetMode (
535                                     Private->UgaDraw,
536                                     &HorizontalResolution,
537                                     &VerticalResolution,
538                                     &ColorDepth,
539                                     &RefreshRate
540                                     );
541         if (EFI_ERROR (Status)) {
542           goto Error;
543         }
544       }
545     }
546   }
547 
548   DEBUG ((EFI_D_INFO, "GraphicsConsole video resolution %d x %d\n", HorizontalResolution, VerticalResolution));
549 
550   //
551   // Initialize the mode which GraphicsConsole supports.
552   //
553   Status = InitializeGraphicsConsoleTextMode (
554              HorizontalResolution,
555              VerticalResolution,
556              ModeNumber,
557              &MaxMode,
558              &Private->ModeData
559              );
560 
561   if (EFI_ERROR (Status)) {
562     goto Error;
563   }
564 
565   //
566   // Update the maximum number of modes
567   //
568   Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode;
569 
570   DEBUG_CODE_BEGIN ();
571     Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0);
572     if (EFI_ERROR (Status)) {
573       goto Error;
574     }
575     Status = GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r");
576     if (EFI_ERROR (Status)) {
577       goto Error;
578     }
579   DEBUG_CODE_END ();
580 
581   //
582   // Install protocol interfaces for the Graphics Console device.
583   //
584   Status = gBS->InstallMultipleProtocolInterfaces (
585                   &Controller,
586                   &gEfiSimpleTextOutProtocolGuid,
587                   &Private->SimpleTextOutput,
588                   NULL
589                   );
590 
591 Error:
592   if (EFI_ERROR (Status)) {
593     //
594     // Close the GOP and UGA Draw Protocol
595     //
596     if (Private->GraphicsOutput != NULL) {
597       gBS->CloseProtocol (
598              Controller,
599              &gEfiGraphicsOutputProtocolGuid,
600              This->DriverBindingHandle,
601              Controller
602              );
603     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
604       gBS->CloseProtocol (
605              Controller,
606              &gEfiUgaDrawProtocolGuid,
607              This->DriverBindingHandle,
608              Controller
609              );
610     }
611 
612     if (Private->LineBuffer != NULL) {
613       FreePool (Private->LineBuffer);
614     }
615 
616     if (Private->ModeData != NULL) {
617       FreePool (Private->ModeData);
618     }
619 
620     //
621     // Free private data
622     //
623     FreePool (Private);
624   }
625 
626   return Status;
627 }
628 
629 /**
630   Stop this driver on Controller by removing Simple Text Out protocol
631   and closing the Graphics Output Protocol or UGA Draw protocol on Controller.
632   (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
633 
634 
635   @param  This              Protocol instance pointer.
636   @param  Controller        Handle of device to stop driver on
637   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
638                             children is zero stop the entire bus driver.
639   @param  ChildHandleBuffer List of Child Handles to Stop.
640 
641   @retval EFI_SUCCESS       This driver is removed Controller.
642   @retval EFI_NOT_STARTED   Simple Text Out protocol could not be found the
643                             Controller.
644   @retval other             This driver was not removed from this device.
645 
646 **/
647 EFI_STATUS
648 EFIAPI
GraphicsConsoleControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)649 GraphicsConsoleControllerDriverStop (
650   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
651   IN  EFI_HANDLE                    Controller,
652   IN  UINTN                         NumberOfChildren,
653   IN  EFI_HANDLE                    *ChildHandleBuffer
654   )
655 {
656   EFI_STATUS                       Status;
657   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *SimpleTextOutput;
658   GRAPHICS_CONSOLE_DEV             *Private;
659 
660   Status = gBS->OpenProtocol (
661                   Controller,
662                   &gEfiSimpleTextOutProtocolGuid,
663                   (VOID **) &SimpleTextOutput,
664                   This->DriverBindingHandle,
665                   Controller,
666                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
667                   );
668   if (EFI_ERROR (Status)) {
669     return EFI_NOT_STARTED;
670   }
671 
672   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);
673 
674   Status = gBS->UninstallProtocolInterface (
675                   Controller,
676                   &gEfiSimpleTextOutProtocolGuid,
677                   &Private->SimpleTextOutput
678                   );
679 
680   if (!EFI_ERROR (Status)) {
681     //
682     // Close the GOP or UGA IO Protocol
683     //
684     if (Private->GraphicsOutput != NULL) {
685       gBS->CloseProtocol (
686             Controller,
687             &gEfiGraphicsOutputProtocolGuid,
688             This->DriverBindingHandle,
689             Controller
690             );
691     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
692       gBS->CloseProtocol (
693             Controller,
694             &gEfiUgaDrawProtocolGuid,
695             This->DriverBindingHandle,
696             Controller
697             );
698     }
699 
700     if (Private->LineBuffer != NULL) {
701       FreePool (Private->LineBuffer);
702     }
703 
704     if (Private->ModeData != NULL) {
705       FreePool (Private->ModeData);
706     }
707 
708     //
709     // Free our instance data
710     //
711     FreePool (Private);
712   }
713 
714   return Status;
715 }
716 
717 /**
718   Check if the current specific mode supported the user defined resolution
719   for the Graphics Console device based on Graphics Output Protocol.
720 
721   If yes, set the graphic devcice's current mode to this specific mode.
722 
723   @param  GraphicsOutput        Graphics Output Protocol instance pointer.
724   @param  HorizontalResolution  User defined horizontal resolution
725   @param  VerticalResolution    User defined vertical resolution.
726   @param  CurrentModeNumber     Current specific mode to be check.
727 
728   @retval EFI_SUCCESS       The mode is supported.
729   @retval EFI_UNSUPPORTED   The specific mode is out of range of graphics
730                             device supported.
731   @retval other             The specific mode does not support user defined
732                             resolution or failed to set the current mode to the
733                             specific mode on graphics device.
734 
735 **/
736 EFI_STATUS
CheckModeSupported(EFI_GRAPHICS_OUTPUT_PROTOCOL * GraphicsOutput,IN UINT32 HorizontalResolution,IN UINT32 VerticalResolution,OUT UINT32 * CurrentModeNumber)737 CheckModeSupported (
738   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput,
739   IN  UINT32                    HorizontalResolution,
740   IN  UINT32                    VerticalResolution,
741   OUT UINT32                    *CurrentModeNumber
742   )
743 {
744   UINT32     ModeNumber;
745   EFI_STATUS Status;
746   UINTN      SizeOfInfo;
747   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
748   UINT32     MaxMode;
749 
750   Status  = EFI_SUCCESS;
751   MaxMode = GraphicsOutput->Mode->MaxMode;
752 
753   for (ModeNumber = 0; ModeNumber < MaxMode; ModeNumber++) {
754     Status = GraphicsOutput->QueryMode (
755                        GraphicsOutput,
756                        ModeNumber,
757                        &SizeOfInfo,
758                        &Info
759                        );
760     if (!EFI_ERROR (Status)) {
761       if ((Info->HorizontalResolution == HorizontalResolution) &&
762           (Info->VerticalResolution == VerticalResolution)) {
763         if ((GraphicsOutput->Mode->Info->HorizontalResolution == HorizontalResolution) &&
764             (GraphicsOutput->Mode->Info->VerticalResolution == VerticalResolution)) {
765           //
766           // If video device has been set to this mode, we do not need to SetMode again
767           //
768           FreePool (Info);
769           break;
770         } else {
771           Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
772           if (!EFI_ERROR (Status)) {
773             FreePool (Info);
774             break;
775           }
776         }
777       }
778       FreePool (Info);
779     }
780   }
781 
782   if (ModeNumber == GraphicsOutput->Mode->MaxMode) {
783     Status = EFI_UNSUPPORTED;
784   }
785 
786   *CurrentModeNumber = ModeNumber;
787   return Status;
788 }
789 
790 
791 /**
792   Locate HII Database protocol and HII Font protocol.
793 
794   @retval  EFI_SUCCESS     HII Database protocol and HII Font protocol
795                            are located successfully.
796   @return  other           Failed to locate HII Database protocol or
797                            HII Font protocol.
798 
799 **/
800 EFI_STATUS
EfiLocateHiiProtocol(VOID)801 EfiLocateHiiProtocol (
802   VOID
803   )
804 {
805   EFI_STATUS  Status;
806 
807   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabase);
808   if (EFI_ERROR (Status)) {
809     return Status;
810   }
811 
812   Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &mHiiFont);
813   return Status;
814 }
815 
816 //
817 // Body of the STO functions
818 //
819 
820 /**
821   Reset the text output device hardware and optionally run diagnostics.
822 
823   Implements SIMPLE_TEXT_OUTPUT.Reset().
824   If ExtendeVerification is TRUE, then perform dependent Graphics Console
825   device reset, and set display mode to mode 0.
826   If ExtendedVerification is FALSE, only set display mode to mode 0.
827 
828   @param  This                  Protocol instance pointer.
829   @param  ExtendedVerification  Indicates that the driver may perform a more
830                                 exhaustive verification operation of the device
831                                 during reset.
832 
833   @retval EFI_SUCCESS          The text output device was reset.
834   @retval EFI_DEVICE_ERROR     The text output device is not functioning correctly and
835                                could not be reset.
836 
837 **/
838 EFI_STATUS
839 EFIAPI
GraphicsConsoleConOutReset(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)840 GraphicsConsoleConOutReset (
841   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
842   IN  BOOLEAN                          ExtendedVerification
843   )
844 {
845   EFI_STATUS    Status;
846   Status = This->SetMode (This, 0);
847   if (EFI_ERROR (Status)) {
848     return Status;
849   }
850   Status = This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
851   return Status;
852 }
853 
854 
855 /**
856   Write a Unicode string to the output device.
857 
858   Implements SIMPLE_TEXT_OUTPUT.OutputString().
859   The Unicode string will be converted to Glyphs and will be
860   sent to the Graphics Console.
861 
862   @param  This                    Protocol instance pointer.
863   @param  WString                 The NULL-terminated Unicode string to be displayed
864                                   on the output device(s). All output devices must
865                                   also support the Unicode drawing defined in this file.
866 
867   @retval EFI_SUCCESS             The string was output to the device.
868   @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
869                                   the text.
870   @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
871                                   defined text mode.
872   @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
873                                   characters in the Unicode string could not be
874                                   rendered and were skipped.
875 
876 **/
877 EFI_STATUS
878 EFIAPI
GraphicsConsoleConOutOutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * WString)879 GraphicsConsoleConOutOutputString (
880   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
881   IN  CHAR16                           *WString
882   )
883 {
884   GRAPHICS_CONSOLE_DEV  *Private;
885   EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;
886   EFI_UGA_DRAW_PROTOCOL *UgaDraw;
887   INTN                  Mode;
888   UINTN                 MaxColumn;
889   UINTN                 MaxRow;
890   UINTN                 Width;
891   UINTN                 Height;
892   UINTN                 Delta;
893   EFI_STATUS            Status;
894   BOOLEAN               Warning;
895   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Foreground;
896   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Background;
897   UINTN                 DeltaX;
898   UINTN                 DeltaY;
899   UINTN                 Count;
900   UINTN                 Index;
901   INT32                 OriginAttribute;
902   EFI_TPL               OldTpl;
903 
904   if (This->Mode->Mode == -1) {
905     //
906     // If current mode is not valid, return error.
907     //
908     return EFI_UNSUPPORTED;
909   }
910 
911   Status = EFI_SUCCESS;
912 
913   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
914   //
915   // Current mode
916   //
917   Mode      = This->Mode->Mode;
918   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
919   GraphicsOutput = Private->GraphicsOutput;
920   UgaDraw   = Private->UgaDraw;
921 
922   MaxColumn = Private->ModeData[Mode].Columns;
923   MaxRow    = Private->ModeData[Mode].Rows;
924   DeltaX    = (UINTN) Private->ModeData[Mode].DeltaX;
925   DeltaY    = (UINTN) Private->ModeData[Mode].DeltaY;
926   Width     = MaxColumn * EFI_GLYPH_WIDTH;
927   Height    = (MaxRow - 1) * EFI_GLYPH_HEIGHT;
928   Delta     = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
929 
930   //
931   // The Attributes won't change when during the time OutputString is called
932   //
933   GetTextColors (This, &Foreground, &Background);
934 
935   FlushCursor (This);
936 
937   Warning = FALSE;
938 
939   //
940   // Backup attribute
941   //
942   OriginAttribute = This->Mode->Attribute;
943 
944   while (*WString != L'\0') {
945 
946     if (*WString == CHAR_BACKSPACE) {
947       //
948       // If the cursor is at the left edge of the display, then move the cursor
949       // one row up.
950       //
951       if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) {
952         This->Mode->CursorRow--;
953         This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
954         This->OutputString (This, SpaceStr);
955         FlushCursor (This);
956         This->Mode->CursorRow--;
957         This->Mode->CursorColumn = (INT32) (MaxColumn - 1);
958       } else if (This->Mode->CursorColumn > 0) {
959         //
960         // If the cursor is not at the left edge of the display, then move the cursor
961         // left one column.
962         //
963         This->Mode->CursorColumn--;
964         This->OutputString (This, SpaceStr);
965         FlushCursor (This);
966         This->Mode->CursorColumn--;
967       }
968 
969       WString++;
970 
971     } else if (*WString == CHAR_LINEFEED) {
972       //
973       // If the cursor is at the bottom of the display, then scroll the display one
974       // row, and do not update the cursor position. Otherwise, move the cursor
975       // down one row.
976       //
977       if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) {
978         if (GraphicsOutput != NULL) {
979           //
980           // Scroll Screen Up One Row
981           //
982           GraphicsOutput->Blt (
983                     GraphicsOutput,
984                     NULL,
985                     EfiBltVideoToVideo,
986                     DeltaX,
987                     DeltaY + EFI_GLYPH_HEIGHT,
988                     DeltaX,
989                     DeltaY,
990                     Width,
991                     Height,
992                     Delta
993                     );
994 
995           //
996           // Print Blank Line at last line
997           //
998           GraphicsOutput->Blt (
999                     GraphicsOutput,
1000                     &Background,
1001                     EfiBltVideoFill,
1002                     0,
1003                     0,
1004                     DeltaX,
1005                     DeltaY + Height,
1006                     Width,
1007                     EFI_GLYPH_HEIGHT,
1008                     Delta
1009                     );
1010         } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1011           //
1012           // Scroll Screen Up One Row
1013           //
1014           UgaDraw->Blt (
1015                     UgaDraw,
1016                     NULL,
1017                     EfiUgaVideoToVideo,
1018                     DeltaX,
1019                     DeltaY + EFI_GLYPH_HEIGHT,
1020                     DeltaX,
1021                     DeltaY,
1022                     Width,
1023                     Height,
1024                     Delta
1025                     );
1026 
1027           //
1028           // Print Blank Line at last line
1029           //
1030           UgaDraw->Blt (
1031                     UgaDraw,
1032                     (EFI_UGA_PIXEL *) (UINTN) &Background,
1033                     EfiUgaVideoFill,
1034                     0,
1035                     0,
1036                     DeltaX,
1037                     DeltaY + Height,
1038                     Width,
1039                     EFI_GLYPH_HEIGHT,
1040                     Delta
1041                     );
1042         }
1043       } else {
1044         This->Mode->CursorRow++;
1045       }
1046 
1047       WString++;
1048 
1049     } else if (*WString == CHAR_CARRIAGE_RETURN) {
1050       //
1051       // Move the cursor to the beginning of the current row.
1052       //
1053       This->Mode->CursorColumn = 0;
1054       WString++;
1055 
1056     } else if (*WString == WIDE_CHAR) {
1057 
1058       This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE;
1059       WString++;
1060 
1061     } else if (*WString == NARROW_CHAR) {
1062 
1063       This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1064       WString++;
1065 
1066     } else {
1067       //
1068       // Print the character at the current cursor position and move the cursor
1069       // right one column. If this moves the cursor past the right edge of the
1070       // display, then the line should wrap to the beginning of the next line. This
1071       // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
1072       // bottom of the display, and the line wraps, then the display will be scrolled
1073       // one line.
1074       // If wide char is going to be displayed, need to display one character at a time
1075       // Or, need to know the display length of a certain string.
1076       //
1077       // Index is used to determine how many character width units (wide = 2, narrow = 1)
1078       // Count is used to determine how many characters are used regardless of their attributes
1079       //
1080       for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) {
1081         if (WString[Count] == CHAR_NULL ||
1082             WString[Count] == CHAR_BACKSPACE ||
1083             WString[Count] == CHAR_LINEFEED ||
1084             WString[Count] == CHAR_CARRIAGE_RETURN ||
1085             WString[Count] == WIDE_CHAR ||
1086             WString[Count] == NARROW_CHAR) {
1087           break;
1088         }
1089         //
1090         // Is the wide attribute on?
1091         //
1092         if ((This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) != 0) {
1093           //
1094           // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
1095           //
1096           Index++;
1097           //
1098           // This is the end-case where if we are at column 79 and about to print a wide character
1099           // We should prevent this from happening because we will wrap inappropriately.  We should
1100           // not print this character until the next line.
1101           //
1102           if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) {
1103             Index++;
1104             break;
1105           }
1106         }
1107       }
1108 
1109       Status = DrawUnicodeWeightAtCursorN (This, WString, Count);
1110       if (EFI_ERROR (Status)) {
1111         Warning = TRUE;
1112       }
1113       //
1114       // At the end of line, output carriage return and line feed
1115       //
1116       WString += Count;
1117       This->Mode->CursorColumn += (INT32) Index;
1118       if (This->Mode->CursorColumn > (INT32) MaxColumn) {
1119         This->Mode->CursorColumn -= 2;
1120         This->OutputString (This, SpaceStr);
1121       }
1122 
1123       if (This->Mode->CursorColumn >= (INT32) MaxColumn) {
1124         FlushCursor (This);
1125         This->OutputString (This, mCrLfString);
1126         FlushCursor (This);
1127       }
1128     }
1129   }
1130 
1131   This->Mode->Attribute = OriginAttribute;
1132 
1133   FlushCursor (This);
1134 
1135   if (Warning) {
1136     Status = EFI_WARN_UNKNOWN_GLYPH;
1137   }
1138 
1139   gBS->RestoreTPL (OldTpl);
1140   return Status;
1141 
1142 }
1143 
1144 /**
1145   Verifies that all characters in a Unicode string can be output to the
1146   target device.
1147 
1148   Implements SIMPLE_TEXT_OUTPUT.TestString().
1149   If one of the characters in the *Wstring is neither valid valid Unicode
1150   drawing characters, not ASCII code, then this function will return
1151   EFI_UNSUPPORTED
1152 
1153   @param  This    Protocol instance pointer.
1154   @param  WString The NULL-terminated Unicode string to be examined for the output
1155                   device(s).
1156 
1157   @retval EFI_SUCCESS      The device(s) are capable of rendering the output string.
1158   @retval EFI_UNSUPPORTED  Some of the characters in the Unicode string cannot be
1159                            rendered by one or more of the output devices mapped
1160                            by the EFI handle.
1161 
1162 **/
1163 EFI_STATUS
1164 EFIAPI
GraphicsConsoleConOutTestString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * WString)1165 GraphicsConsoleConOutTestString (
1166   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1167   IN  CHAR16                           *WString
1168   )
1169 {
1170   EFI_STATUS            Status;
1171   UINT16                Count;
1172 
1173   EFI_IMAGE_OUTPUT      *Blt;
1174 
1175   Blt   = NULL;
1176   Count = 0;
1177 
1178   while (WString[Count] != 0) {
1179     Status = mHiiFont->GetGlyph (
1180                          mHiiFont,
1181                          WString[Count],
1182                          NULL,
1183                          &Blt,
1184                          NULL
1185                          );
1186     if (Blt != NULL) {
1187       FreePool (Blt);
1188       Blt = NULL;
1189     }
1190     Count++;
1191 
1192     if (EFI_ERROR (Status)) {
1193       return EFI_UNSUPPORTED;
1194     }
1195   }
1196 
1197   return EFI_SUCCESS;
1198 }
1199 
1200 
1201 /**
1202   Returns information for an available text mode that the output device(s)
1203   supports
1204 
1205   Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1206   It returnes information for an available text mode that the Graphics Console supports.
1207   In this driver,we only support text mode 80x25, which is defined as mode 0.
1208 
1209   @param  This                  Protocol instance pointer.
1210   @param  ModeNumber            The mode number to return information on.
1211   @param  Columns               The returned columns of the requested mode.
1212   @param  Rows                  The returned rows of the requested mode.
1213 
1214   @retval EFI_SUCCESS           The requested mode information is returned.
1215   @retval EFI_UNSUPPORTED       The mode number is not valid.
1216 
1217 **/
1218 EFI_STATUS
1219 EFIAPI
GraphicsConsoleConOutQueryMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber,OUT UINTN * Columns,OUT UINTN * Rows)1220 GraphicsConsoleConOutQueryMode (
1221   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1222   IN  UINTN                            ModeNumber,
1223   OUT UINTN                            *Columns,
1224   OUT UINTN                            *Rows
1225   )
1226 {
1227   GRAPHICS_CONSOLE_DEV  *Private;
1228   EFI_STATUS            Status;
1229   EFI_TPL               OldTpl;
1230 
1231   if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1232     return EFI_UNSUPPORTED;
1233   }
1234 
1235   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1236   Status = EFI_SUCCESS;
1237 
1238   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1239 
1240   *Columns  = Private->ModeData[ModeNumber].Columns;
1241   *Rows     = Private->ModeData[ModeNumber].Rows;
1242 
1243   if (*Columns <= 0 || *Rows <= 0) {
1244     Status = EFI_UNSUPPORTED;
1245     goto Done;
1246 
1247   }
1248 
1249 Done:
1250   gBS->RestoreTPL (OldTpl);
1251   return Status;
1252 }
1253 
1254 
1255 /**
1256   Sets the output device(s) to a specified mode.
1257 
1258   Implements SIMPLE_TEXT_OUTPUT.SetMode().
1259   Set the Graphics Console to a specified mode. In this driver, we only support mode 0.
1260 
1261   @param  This                  Protocol instance pointer.
1262   @param  ModeNumber            The text mode to set.
1263 
1264   @retval EFI_SUCCESS           The requested text mode is set.
1265   @retval EFI_DEVICE_ERROR      The requested text mode cannot be set because of
1266                                 Graphics Console device error.
1267   @retval EFI_UNSUPPORTED       The text mode number is not valid.
1268 
1269 **/
1270 EFI_STATUS
1271 EFIAPI
GraphicsConsoleConOutSetMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber)1272 GraphicsConsoleConOutSetMode (
1273   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1274   IN  UINTN                            ModeNumber
1275   )
1276 {
1277   EFI_STATUS                      Status;
1278   GRAPHICS_CONSOLE_DEV            *Private;
1279   GRAPHICS_CONSOLE_MODE_DATA      *ModeData;
1280   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *NewLineBuffer;
1281   UINT32                          HorizontalResolution;
1282   UINT32                          VerticalResolution;
1283   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
1284   EFI_UGA_DRAW_PROTOCOL           *UgaDraw;
1285   UINT32                          ColorDepth;
1286   UINT32                          RefreshRate;
1287   EFI_TPL                         OldTpl;
1288 
1289   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1290 
1291   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1292   GraphicsOutput = Private->GraphicsOutput;
1293   UgaDraw   = Private->UgaDraw;
1294 
1295   //
1296   // Make sure the requested mode number is supported
1297   //
1298   if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
1299     Status = EFI_UNSUPPORTED;
1300     goto Done;
1301   }
1302 
1303   ModeData  = &(Private->ModeData[ModeNumber]);
1304 
1305   if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
1306     Status = EFI_UNSUPPORTED;
1307     goto Done;
1308   }
1309 
1310   //
1311   // If the mode has been set at least one other time, then LineBuffer will not be NULL
1312   //
1313   if (Private->LineBuffer != NULL) {
1314     //
1315     // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1316     //
1317     if ((INT32) ModeNumber == This->Mode->Mode) {
1318       //
1319       // Clear the current text window on the current graphics console
1320       //
1321       This->ClearScreen (This);
1322       Status = EFI_SUCCESS;
1323       goto Done;
1324     }
1325     //
1326     // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,
1327     // so erase the cursor, and free the LineBuffer for the current mode
1328     //
1329     FlushCursor (This);
1330 
1331     FreePool (Private->LineBuffer);
1332   }
1333 
1334   //
1335   // Attempt to allocate a line buffer for the requested mode number
1336   //
1337   NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT);
1338 
1339   if (NewLineBuffer == NULL) {
1340     //
1341     // The new line buffer could not be allocated, so return an error.
1342     // No changes to the state of the current console have been made, so the current console is still valid
1343     //
1344     Status = EFI_OUT_OF_RESOURCES;
1345     goto Done;
1346   }
1347 
1348   //
1349   // Assign the current line buffer to the newly allocated line buffer
1350   //
1351   Private->LineBuffer = NewLineBuffer;
1352 
1353   if (GraphicsOutput != NULL) {
1354     if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) {
1355       //
1356       // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1357       //
1358       Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber);
1359       if (EFI_ERROR (Status)) {
1360         //
1361         // The mode set operation failed
1362         //
1363         goto Done;
1364       }
1365     } else {
1366       //
1367       // The current graphics mode is correct, so simply clear the entire display
1368       //
1369       Status = GraphicsOutput->Blt (
1370                           GraphicsOutput,
1371                           &mGraphicsEfiColors[0],
1372                           EfiBltVideoFill,
1373                           0,
1374                           0,
1375                           0,
1376                           0,
1377                           ModeData->GopWidth,
1378                           ModeData->GopHeight,
1379                           0
1380                           );
1381     }
1382   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1383     //
1384     // Get the current UGA Draw mode information
1385     //
1386     Status = UgaDraw->GetMode (
1387                         UgaDraw,
1388                         &HorizontalResolution,
1389                         &VerticalResolution,
1390                         &ColorDepth,
1391                         &RefreshRate
1392                         );
1393     if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) {
1394       //
1395       // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
1396       //
1397       Status = UgaDraw->SetMode (
1398                           UgaDraw,
1399                           ModeData->GopWidth,
1400                           ModeData->GopHeight,
1401                           32,
1402                           60
1403                           );
1404       if (EFI_ERROR (Status)) {
1405         //
1406         // The mode set operation failed
1407         //
1408         goto Done;
1409       }
1410     } else {
1411       //
1412       // The current graphics mode is correct, so simply clear the entire display
1413       //
1414       Status = UgaDraw->Blt (
1415                           UgaDraw,
1416                           (EFI_UGA_PIXEL *) (UINTN) &mGraphicsEfiColors[0],
1417                           EfiUgaVideoFill,
1418                           0,
1419                           0,
1420                           0,
1421                           0,
1422                           ModeData->GopWidth,
1423                           ModeData->GopHeight,
1424                           0
1425                           );
1426     }
1427   }
1428 
1429   //
1430   // The new mode is valid, so commit the mode change
1431   //
1432   This->Mode->Mode = (INT32) ModeNumber;
1433 
1434   //
1435   // Move the text cursor to the upper left hand corner of the display and flush it
1436   //
1437   This->Mode->CursorColumn  = 0;
1438   This->Mode->CursorRow     = 0;
1439 
1440   FlushCursor (This);
1441 
1442   Status = EFI_SUCCESS;
1443 
1444 Done:
1445   gBS->RestoreTPL (OldTpl);
1446   return Status;
1447 }
1448 
1449 
1450 /**
1451   Sets the background and foreground colors for the OutputString () and
1452   ClearScreen () functions.
1453 
1454   Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1455 
1456   @param  This                  Protocol instance pointer.
1457   @param  Attribute             The attribute to set. Bits 0..3 are the foreground
1458                                 color, and bits 4..6 are the background color.
1459                                 All other bits are undefined and must be zero.
1460 
1461   @retval EFI_SUCCESS           The requested attribute is set.
1462   @retval EFI_DEVICE_ERROR      The requested attribute cannot be set due to Graphics Console port error.
1463   @retval EFI_UNSUPPORTED       The attribute requested is not defined.
1464 
1465 **/
1466 EFI_STATUS
1467 EFIAPI
GraphicsConsoleConOutSetAttribute(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Attribute)1468 GraphicsConsoleConOutSetAttribute (
1469   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1470   IN  UINTN                            Attribute
1471   )
1472 {
1473   EFI_TPL               OldTpl;
1474 
1475   if ((Attribute | 0x7F) != 0x7F) {
1476     return EFI_UNSUPPORTED;
1477   }
1478 
1479   if ((INT32) Attribute == This->Mode->Attribute) {
1480     return EFI_SUCCESS;
1481   }
1482 
1483   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1484 
1485   FlushCursor (This);
1486 
1487   This->Mode->Attribute = (INT32) Attribute;
1488 
1489   FlushCursor (This);
1490 
1491   gBS->RestoreTPL (OldTpl);
1492 
1493   return EFI_SUCCESS;
1494 }
1495 
1496 
1497 /**
1498   Clears the output device(s) display to the currently selected background
1499   color.
1500 
1501   Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1502 
1503   @param  This                  Protocol instance pointer.
1504 
1505   @retval  EFI_SUCCESS      The operation completed successfully.
1506   @retval  EFI_DEVICE_ERROR The device had an error and could not complete the request.
1507   @retval  EFI_UNSUPPORTED  The output device is not in a valid text mode.
1508 
1509 **/
1510 EFI_STATUS
1511 EFIAPI
GraphicsConsoleConOutClearScreen(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This)1512 GraphicsConsoleConOutClearScreen (
1513   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
1514   )
1515 {
1516   EFI_STATUS                    Status;
1517   GRAPHICS_CONSOLE_DEV          *Private;
1518   GRAPHICS_CONSOLE_MODE_DATA    *ModeData;
1519   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
1520   EFI_UGA_DRAW_PROTOCOL         *UgaDraw;
1521   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
1522   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
1523   EFI_TPL                       OldTpl;
1524 
1525   if (This->Mode->Mode == -1) {
1526     //
1527     // If current mode is not valid, return error.
1528     //
1529     return EFI_UNSUPPORTED;
1530   }
1531 
1532   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1533 
1534   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1535   GraphicsOutput = Private->GraphicsOutput;
1536   UgaDraw   = Private->UgaDraw;
1537   ModeData  = &(Private->ModeData[This->Mode->Mode]);
1538 
1539   GetTextColors (This, &Foreground, &Background);
1540   if (GraphicsOutput != NULL) {
1541     Status = GraphicsOutput->Blt (
1542                         GraphicsOutput,
1543                         &Background,
1544                         EfiBltVideoFill,
1545                         0,
1546                         0,
1547                         0,
1548                         0,
1549                         ModeData->GopWidth,
1550                         ModeData->GopHeight,
1551                         0
1552                         );
1553   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1554     Status = UgaDraw->Blt (
1555                         UgaDraw,
1556                         (EFI_UGA_PIXEL *) (UINTN) &Background,
1557                         EfiUgaVideoFill,
1558                         0,
1559                         0,
1560                         0,
1561                         0,
1562                         ModeData->GopWidth,
1563                         ModeData->GopHeight,
1564                         0
1565                         );
1566   } else {
1567     Status = EFI_UNSUPPORTED;
1568   }
1569 
1570   This->Mode->CursorColumn  = 0;
1571   This->Mode->CursorRow     = 0;
1572 
1573   FlushCursor (This);
1574 
1575   gBS->RestoreTPL (OldTpl);
1576 
1577   return Status;
1578 }
1579 
1580 
1581 /**
1582   Sets the current coordinates of the cursor position.
1583 
1584   Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1585 
1586   @param  This        Protocol instance pointer.
1587   @param  Column      The position to set the cursor to. Must be greater than or
1588                       equal to zero and less than the number of columns and rows
1589                       by QueryMode ().
1590   @param  Row         The position to set the cursor to. Must be greater than or
1591                       equal to zero and less than the number of columns and rows
1592                       by QueryMode ().
1593 
1594   @retval EFI_SUCCESS      The operation completed successfully.
1595   @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
1596   @retval EFI_UNSUPPORTED  The output device is not in a valid text mode, or the
1597                            cursor position is invalid for the current mode.
1598 
1599 **/
1600 EFI_STATUS
1601 EFIAPI
GraphicsConsoleConOutSetCursorPosition(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Column,IN UINTN Row)1602 GraphicsConsoleConOutSetCursorPosition (
1603   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1604   IN  UINTN                            Column,
1605   IN  UINTN                            Row
1606   )
1607 {
1608   GRAPHICS_CONSOLE_DEV        *Private;
1609   GRAPHICS_CONSOLE_MODE_DATA  *ModeData;
1610   EFI_STATUS                  Status;
1611   EFI_TPL                     OldTpl;
1612 
1613   if (This->Mode->Mode == -1) {
1614     //
1615     // If current mode is not valid, return error.
1616     //
1617     return EFI_UNSUPPORTED;
1618   }
1619 
1620   Status = EFI_SUCCESS;
1621 
1622   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1623 
1624   Private   = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1625   ModeData  = &(Private->ModeData[This->Mode->Mode]);
1626 
1627   if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
1628     Status = EFI_UNSUPPORTED;
1629     goto Done;
1630   }
1631 
1632   if ((This->Mode->CursorColumn == (INT32) Column) && (This->Mode->CursorRow == (INT32) Row)) {
1633     Status = EFI_SUCCESS;
1634     goto Done;
1635   }
1636 
1637   FlushCursor (This);
1638 
1639   This->Mode->CursorColumn  = (INT32) Column;
1640   This->Mode->CursorRow     = (INT32) Row;
1641 
1642   FlushCursor (This);
1643 
1644 Done:
1645   gBS->RestoreTPL (OldTpl);
1646 
1647   return Status;
1648 }
1649 
1650 
1651 /**
1652   Makes the cursor visible or invisible.
1653 
1654   Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1655 
1656   @param  This                  Protocol instance pointer.
1657   @param  Visible               If TRUE, the cursor is set to be visible, If FALSE,
1658                                 the cursor is set to be invisible.
1659 
1660   @retval EFI_SUCCESS           The operation completed successfully.
1661   @retval EFI_UNSUPPORTED       The output device's mode is not currently in a
1662                                 defined text mode.
1663 
1664 **/
1665 EFI_STATUS
1666 EFIAPI
GraphicsConsoleConOutEnableCursor(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN Visible)1667 GraphicsConsoleConOutEnableCursor (
1668   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1669   IN  BOOLEAN                          Visible
1670   )
1671 {
1672   EFI_TPL               OldTpl;
1673 
1674   if (This->Mode->Mode == -1) {
1675     //
1676     // If current mode is not valid, return error.
1677     //
1678     return EFI_UNSUPPORTED;
1679   }
1680 
1681   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1682 
1683   FlushCursor (This);
1684 
1685   This->Mode->CursorVisible = Visible;
1686 
1687   FlushCursor (This);
1688 
1689   gBS->RestoreTPL (OldTpl);
1690   return EFI_SUCCESS;
1691 }
1692 
1693 /**
1694   Gets Graphics Console devcie's foreground color and background color.
1695 
1696   @param  This                  Protocol instance pointer.
1697   @param  Foreground            Returned text foreground color.
1698   @param  Background            Returned text background color.
1699 
1700   @retval EFI_SUCCESS           It returned always.
1701 
1702 **/
1703 EFI_STATUS
GetTextColors(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * Foreground,OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * Background)1704 GetTextColors (
1705   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1706   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Foreground,
1707   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL    *Background
1708   )
1709 {
1710   INTN  Attribute;
1711 
1712   Attribute   = This->Mode->Attribute & 0x7F;
1713 
1714   *Foreground = mGraphicsEfiColors[Attribute & 0x0f];
1715   *Background = mGraphicsEfiColors[Attribute >> 4];
1716 
1717   return EFI_SUCCESS;
1718 }
1719 
1720 /**
1721   Draw Unicode string on the Graphics Console device's screen.
1722 
1723   @param  This                  Protocol instance pointer.
1724   @param  UnicodeWeight         One Unicode string to be displayed.
1725   @param  Count                 The count of Unicode string.
1726 
1727   @retval EFI_OUT_OF_RESOURCES  If no memory resource to use.
1728   @retval EFI_UNSUPPORTED       If no Graphics Output protocol and UGA Draw
1729                                 protocol exist.
1730   @retval EFI_SUCCESS           Drawing Unicode string implemented successfully.
1731 
1732 **/
1733 EFI_STATUS
DrawUnicodeWeightAtCursorN(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * UnicodeWeight,IN UINTN Count)1734 DrawUnicodeWeightAtCursorN (
1735   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
1736   IN  CHAR16                           *UnicodeWeight,
1737   IN  UINTN                            Count
1738   )
1739 {
1740   EFI_STATUS                        Status;
1741   GRAPHICS_CONSOLE_DEV              *Private;
1742   EFI_IMAGE_OUTPUT                  *Blt;
1743   EFI_STRING                        String;
1744   EFI_FONT_DISPLAY_INFO             *FontInfo;
1745   EFI_UGA_DRAW_PROTOCOL             *UgaDraw;
1746   EFI_HII_ROW_INFO                  *RowInfoArray;
1747   UINTN                             RowInfoArraySize;
1748 
1749   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1750   Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1751   if (Blt == NULL) {
1752     return EFI_OUT_OF_RESOURCES;
1753   }
1754 
1755   Blt->Width        = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);
1756   Blt->Height       = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);
1757 
1758   String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
1759   if (String == NULL) {
1760     FreePool (Blt);
1761     return EFI_OUT_OF_RESOURCES;
1762   }
1763   //
1764   // Set the end character
1765   //
1766   *(String + Count) = L'\0';
1767 
1768   FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
1769   if (FontInfo == NULL) {
1770     FreePool (Blt);
1771     FreePool (String);
1772     return EFI_OUT_OF_RESOURCES;
1773   }
1774   //
1775   // Get current foreground and background colors.
1776   //
1777   GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
1778 
1779   if (Private->GraphicsOutput != NULL) {
1780     //
1781     // If Graphics Output protocol exists, using HII Font protocol to draw.
1782     //
1783     Blt->Image.Screen = Private->GraphicsOutput;
1784 
1785     Status = mHiiFont->StringToImage (
1786                          mHiiFont,
1787                          EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN | EFI_HII_IGNORE_LINE_BREAK,
1788                          String,
1789                          FontInfo,
1790                          &Blt,
1791                          This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1792                          This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1793                          NULL,
1794                          NULL,
1795                          NULL
1796                          );
1797 
1798   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1799     //
1800     // If Graphics Output protocol cannot be found and PcdUgaConsumeSupport enabled,
1801     // using UGA Draw protocol to draw.
1802     //
1803     ASSERT (Private->UgaDraw!= NULL);
1804 
1805     UgaDraw = Private->UgaDraw;
1806 
1807     Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
1808     if (Blt->Image.Bitmap == NULL) {
1809       FreePool (Blt);
1810       FreePool (String);
1811       return EFI_OUT_OF_RESOURCES;
1812     }
1813 
1814     RowInfoArray = NULL;
1815     //
1816     //  StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
1817     //  we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
1818     //
1819     Status = mHiiFont->StringToImage (
1820                           mHiiFont,
1821                           EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK,
1822                           String,
1823                           FontInfo,
1824                           &Blt,
1825                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
1826                           This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1827                           &RowInfoArray,
1828                           &RowInfoArraySize,
1829                           NULL
1830                           );
1831 
1832     if (!EFI_ERROR (Status)) {
1833       //
1834       // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
1835       // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
1836       //
1837       ASSERT (RowInfoArraySize <= 1);
1838 
1839       Status = UgaDraw->Blt (
1840                           UgaDraw,
1841                           (EFI_UGA_PIXEL *) Blt->Image.Bitmap,
1842                           EfiUgaBltBufferToVideo,
1843                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH  + Private->ModeData[This->Mode->Mode].DeltaX,
1844                           (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1845                           This->Mode->CursorColumn * EFI_GLYPH_WIDTH  + Private->ModeData[This->Mode->Mode].DeltaX,
1846                           (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
1847                           RowInfoArray[0].LineWidth,
1848                           RowInfoArray[0].LineHeight,
1849                           Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1850                           );
1851     }
1852 
1853     FreePool (RowInfoArray);
1854     FreePool (Blt->Image.Bitmap);
1855   } else {
1856     Status = EFI_UNSUPPORTED;
1857   }
1858 
1859   if (Blt != NULL) {
1860     FreePool (Blt);
1861   }
1862   if (String != NULL) {
1863     FreePool (String);
1864   }
1865   if (FontInfo != NULL) {
1866     FreePool (FontInfo);
1867   }
1868   return Status;
1869 }
1870 
1871 /**
1872   Flush the cursor on the screen.
1873 
1874   If CursorVisible is FALSE, nothing to do and return directly.
1875   If CursorVisible is TRUE,
1876      i) If the cursor shows on screen, it will be erased.
1877     ii) If the cursor does not show on screen, it will be shown.
1878 
1879   @param  This                  Protocol instance pointer.
1880 
1881   @retval EFI_SUCCESS           The cursor is erased successfully.
1882 
1883 **/
1884 EFI_STATUS
FlushCursor(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This)1885 FlushCursor (
1886   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
1887   )
1888 {
1889   GRAPHICS_CONSOLE_DEV                *Private;
1890   EFI_SIMPLE_TEXT_OUTPUT_MODE         *CurrentMode;
1891   INTN                                GlyphX;
1892   INTN                                GlyphY;
1893   EFI_GRAPHICS_OUTPUT_PROTOCOL        *GraphicsOutput;
1894   EFI_UGA_DRAW_PROTOCOL               *UgaDraw;
1895   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
1896   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
1897   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH];
1898   UINTN                               PosX;
1899   UINTN                               PosY;
1900 
1901   CurrentMode = This->Mode;
1902 
1903   if (!CurrentMode->CursorVisible) {
1904     return EFI_SUCCESS;
1905   }
1906 
1907   Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
1908   GraphicsOutput = Private->GraphicsOutput;
1909   UgaDraw = Private->UgaDraw;
1910 
1911   //
1912   // In this driver, only narrow character was supported.
1913   //
1914   //
1915   // Blt a character to the screen
1916   //
1917   GlyphX  = (CurrentMode->CursorColumn * EFI_GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX;
1918   GlyphY  = (CurrentMode->CursorRow * EFI_GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY;
1919   if (GraphicsOutput != NULL) {
1920     GraphicsOutput->Blt (
1921               GraphicsOutput,
1922               (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1923               EfiBltVideoToBltBuffer,
1924               GlyphX,
1925               GlyphY,
1926               0,
1927               0,
1928               EFI_GLYPH_WIDTH,
1929               EFI_GLYPH_HEIGHT,
1930               EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1931               );
1932   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1933     UgaDraw->Blt (
1934               UgaDraw,
1935               (EFI_UGA_PIXEL *) (UINTN) BltChar,
1936               EfiUgaVideoToBltBuffer,
1937               GlyphX,
1938               GlyphY,
1939               0,
1940               0,
1941               EFI_GLYPH_WIDTH,
1942               EFI_GLYPH_HEIGHT,
1943               EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1944               );
1945   }
1946 
1947   GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
1948 
1949   //
1950   // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1951   //
1952   for (PosY = 0; PosY < EFI_GLYPH_HEIGHT; PosY++) {
1953     for (PosX = 0; PosX < EFI_GLYPH_WIDTH; PosX++) {
1954       if ((mCursorGlyph.GlyphCol1[PosY] & (BIT0 << PosX)) != 0) {
1955         BltChar[PosY][EFI_GLYPH_WIDTH - PosX - 1].Raw ^= Foreground.Raw;
1956       }
1957     }
1958   }
1959 
1960   if (GraphicsOutput != NULL) {
1961     GraphicsOutput->Blt (
1962               GraphicsOutput,
1963               (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar,
1964               EfiBltBufferToVideo,
1965               0,
1966               0,
1967               GlyphX,
1968               GlyphY,
1969               EFI_GLYPH_WIDTH,
1970               EFI_GLYPH_HEIGHT,
1971               EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
1972               );
1973   } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
1974     UgaDraw->Blt (
1975               UgaDraw,
1976               (EFI_UGA_PIXEL *) (UINTN) BltChar,
1977               EfiUgaBltBufferToVideo,
1978               0,
1979               0,
1980               GlyphX,
1981               GlyphY,
1982               EFI_GLYPH_WIDTH,
1983               EFI_GLYPH_HEIGHT,
1984               EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
1985               );
1986   }
1987 
1988   return EFI_SUCCESS;
1989 }
1990 
1991 /**
1992   HII Database Protocol notification event handler.
1993 
1994   Register font package when HII Database Protocol has been installed.
1995 
1996   @param[in] Event    Event whose notification function is being invoked.
1997   @param[in] Context  Pointer to the notification function's context.
1998 **/
1999 VOID
2000 EFIAPI
RegisterFontPackage(IN EFI_EVENT Event,IN VOID * Context)2001 RegisterFontPackage (
2002   IN  EFI_EVENT       Event,
2003   IN  VOID            *Context
2004   )
2005 {
2006   EFI_STATUS                           Status;
2007   EFI_HII_SIMPLE_FONT_PACKAGE_HDR      *SimplifiedFont;
2008   UINT32                               PackageLength;
2009   UINT8                                *Package;
2010   UINT8                                *Location;
2011   EFI_HII_DATABASE_PROTOCOL            *HiiDatabase;
2012 
2013   //
2014   // Locate HII Database Protocol
2015   //
2016   Status = gBS->LocateProtocol (
2017                   &gEfiHiiDatabaseProtocolGuid,
2018                   NULL,
2019                   (VOID **) &HiiDatabase
2020                   );
2021   if (EFI_ERROR (Status)) {
2022     return;
2023   }
2024 
2025   //
2026   // Add 4 bytes to the header for entire length for HiiAddPackages use only.
2027   //
2028   //    +--------------------------------+ <-- Package
2029   //    |                                |
2030   //    |    PackageLength(4 bytes)      |
2031   //    |                                |
2032   //    |--------------------------------| <-- SimplifiedFont
2033   //    |                                |
2034   //    |EFI_HII_SIMPLE_FONT_PACKAGE_HDR |
2035   //    |                                |
2036   //    |--------------------------------| <-- Location
2037   //    |                                |
2038   //    |     gUsStdNarrowGlyphData      |
2039   //    |                                |
2040   //    +--------------------------------+
2041 
2042   PackageLength   = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mNarrowFontSize + 4;
2043   Package = AllocateZeroPool (PackageLength);
2044   ASSERT (Package != NULL);
2045 
2046   WriteUnaligned32((UINT32 *) Package,PackageLength);
2047   SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4);
2048   SimplifiedFont->Header.Length        = (UINT32) (PackageLength - 4);
2049   SimplifiedFont->Header.Type          = EFI_HII_PACKAGE_SIMPLE_FONTS;
2050   SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (mNarrowFontSize / sizeof (EFI_NARROW_GLYPH));
2051 
2052   Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1);
2053   CopyMem (Location, gUsStdNarrowGlyphData, mNarrowFontSize);
2054 
2055   //
2056   // Add this simplified font package to a package list then install it.
2057   //
2058   mHiiHandle = HiiAddPackages (
2059                  &mFontPackageListGuid,
2060                  NULL,
2061                  Package,
2062                  NULL
2063                  );
2064   ASSERT (mHiiHandle != NULL);
2065   FreePool (Package);
2066 }
2067 
2068 /**
2069   The user Entry Point for module GraphicsConsole. The user code starts with this function.
2070 
2071   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
2072   @param[in] SystemTable    A pointer to the EFI System Table.
2073 
2074   @retval  EFI_SUCCESS       The entry point is executed successfully.
2075   @return  other             Some error occurs when executing this entry point.
2076 
2077 **/
2078 EFI_STATUS
2079 EFIAPI
InitializeGraphicsConsole(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)2080 InitializeGraphicsConsole (
2081   IN EFI_HANDLE           ImageHandle,
2082   IN EFI_SYSTEM_TABLE     *SystemTable
2083   )
2084 {
2085   EFI_STATUS              Status;
2086 
2087   //
2088   // Register notify function on HII Database Protocol to add font package.
2089   //
2090   EfiCreateProtocolNotifyEvent (
2091     &gEfiHiiDatabaseProtocolGuid,
2092     TPL_CALLBACK,
2093     RegisterFontPackage,
2094     NULL,
2095     &mHiiRegistration
2096     );
2097 
2098   //
2099   // Install driver model protocol(s).
2100   //
2101   Status = EfiLibInstallDriverBindingComponentName2 (
2102              ImageHandle,
2103              SystemTable,
2104              &gGraphicsConsoleDriverBinding,
2105              ImageHandle,
2106              &gGraphicsConsoleComponentName,
2107              &gGraphicsConsoleComponentName2
2108              );
2109   ASSERT_EFI_ERROR (Status);
2110 
2111   return Status;
2112 }
2113 
2114 
2115