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