Home | History | Annotate | Download | only in GraphicsConsoleDxe
      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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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