Home | History | Annotate | Download | only in GraphicsLite
      1 /*++
      2 
      3 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   Graphics.c
     15 
     16 Abstract:
     17 
     18   Support for Basic Graphics operations.
     19 
     20   BugBug: Currently *.BMP files are supported. This will be replaced
     21           when Tiano graphics format is supported.
     22 
     23 --*/
     24 
     25 #include "Tiano.h"
     26 #include "EfiDriverLib.h"
     27 #include "GraphicsLib.h"
     28 
     29 
     30 EFI_STATUS
     31 GetGraphicsBitMapFromFV (
     32   IN  EFI_GUID      *FileNameGuid,
     33   OUT VOID          **Image,
     34   OUT UINTN         *ImageSize
     35   )
     36 /*++
     37 
     38 Routine Description:
     39 
     40   Return the graphics image file named FileNameGuid into Image and return it's
     41   size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
     42   file name.
     43 
     44 Arguments:
     45 
     46   FileNameGuid  - File Name of graphics file in the FV(s).
     47 
     48   Image         - Pointer to pointer to return graphics image.  If NULL, a
     49                   buffer will be allocated.
     50 
     51   ImageSize     - Size of the graphics Image in bytes. Zero if no image found.
     52 
     53 
     54 Returns:
     55 
     56   EFI_SUCCESS          - Image and ImageSize are valid.
     57   EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
     58   EFI_NOT_FOUND        - FileNameGuid not found
     59 
     60 --*/
     61 {
     62   return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);
     63 }
     64 
     65 EFI_STATUS
     66 GetGraphicsBitMapFromFVEx (
     67   IN  EFI_HANDLE    ImageHandle,
     68   IN  EFI_GUID      *FileNameGuid,
     69   OUT VOID          **Image,
     70   OUT UINTN         *ImageSize
     71   )
     72 /*++
     73 
     74 Routine Description:
     75 
     76   Return the graphics image file named FileNameGuid into Image and return it's
     77   size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
     78   file name.
     79 
     80 Arguments:
     81 
     82   ImageHandle   - The driver image handle of the caller. The parameter is used to
     83                   optimize the loading of the image file so that the FV from which
     84                   the driver image is loaded will be tried first.
     85 
     86   FileNameGuid  - File Name of graphics file in the FV(s).
     87 
     88   Image         - Pointer to pointer to return graphics image.  If NULL, a
     89                   buffer will be allocated.
     90 
     91   ImageSize     - Size of the graphics Image in bytes. Zero if no image found.
     92 
     93 
     94 Returns:
     95 
     96   EFI_SUCCESS          - Image and ImageSize are valid.
     97   EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
     98   EFI_NOT_FOUND        - FileNameGuid not found
     99 
    100 --*/
    101 {
    102   return GetImageEx (
    103            ImageHandle,
    104            FileNameGuid,
    105            EFI_SECTION_RAW,
    106            Image,
    107            ImageSize,
    108            FALSE
    109            );
    110 }
    111 
    112 
    113 EFI_STATUS
    114 ConvertBmpToGopBlt (
    115   IN  VOID      *BmpImage,
    116   IN  UINTN     BmpImageSize,
    117   IN OUT VOID   **GopBlt,
    118   IN OUT UINTN  *GopBltSize,
    119   OUT UINTN     *PixelHeight,
    120   OUT UINTN     *PixelWidth
    121   )
    122 /*++
    123 
    124 Routine Description:
    125 
    126   Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
    127   is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
    128   buffer is passed in it will be used if it is big enough.
    129 
    130 Arguments:
    131 
    132   BmpImage      - Pointer to BMP file
    133 
    134   BmpImageSize  - Number of bytes in BmpImage
    135 
    136   GopBlt        - Buffer containing GOP version of BmpImage.
    137 
    138   GopBltSize    - Size of GopBlt in bytes.
    139 
    140   PixelHeight   - Height of GopBlt/BmpImage in pixels
    141 
    142   PixelWidth    - Width of GopBlt/BmpImage in pixels
    143 
    144 
    145 Returns:
    146 
    147   EFI_SUCCESS           - GopBlt and GopBltSize are returned.
    148   EFI_UNSUPPORTED       - BmpImage is not a valid *.BMP image
    149   EFI_BUFFER_TOO_SMALL  - The passed in GopBlt buffer is not big enough.
    150                           GopBltSize will contain the required size.
    151   EFI_OUT_OF_RESOURCES  - No enough buffer to allocate
    152 
    153 --*/
    154 {
    155   UINT8                         *Image;
    156   UINT8                         *ImageHeader;
    157   BMP_IMAGE_HEADER              *BmpHeader;
    158   BMP_COLOR_MAP                 *BmpColorMap;
    159   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
    160   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
    161   UINT64                        BltBufferSize;
    162   UINTN                         Index;
    163   UINTN                         Height;
    164   UINTN                         Width;
    165   UINTN                         ImageIndex;
    166   UINTN                         DataSizePerLine;
    167   BOOLEAN                       IsAllocated;
    168   UINT32                        ColorMapNum;
    169 
    170   if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
    171     return EFI_INVALID_PARAMETER;
    172   }
    173 
    174   BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
    175 
    176   if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
    177     return EFI_UNSUPPORTED;
    178   }
    179 
    180   //
    181   // Doesn't support compress.
    182   //
    183   if (BmpHeader->CompressionType != 0) {
    184     return EFI_UNSUPPORTED;
    185   }
    186 
    187   //
    188   // Only support BITMAPINFOHEADER format.
    189   // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
    190   //
    191   if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - ((UINTN) &(((BMP_IMAGE_HEADER *)0)->HeaderSize))) {
    192     return EFI_UNSUPPORTED;
    193   }
    194 
    195   //
    196   // The data size in each line must be 4 byte alignment.
    197   //
    198   DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
    199   BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
    200   if (BltBufferSize > (UINT32) ~0) {
    201     return EFI_INVALID_PARAMETER;
    202   }
    203 
    204   if ((BmpHeader->Size != BmpImageSize) ||
    205       (BmpHeader->Size < BmpHeader->ImageOffset) ||
    206       (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
    207     return EFI_INVALID_PARAMETER;
    208   }
    209 
    210   //
    211   // Calculate Color Map offset in the image.
    212   //
    213   Image       = BmpImage;
    214   BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
    215   if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
    216     return EFI_INVALID_PARAMETER;
    217   }
    218 
    219   if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
    220     switch (BmpHeader->BitPerPixel) {
    221       case 1:
    222         ColorMapNum = 2;
    223         break;
    224       case 4:
    225         ColorMapNum = 16;
    226         break;
    227       case 8:
    228         ColorMapNum = 256;
    229         break;
    230       default:
    231         ColorMapNum = 0;
    232         break;
    233       }
    234     if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) != sizeof (BMP_COLOR_MAP) * ColorMapNum) {
    235       return EFI_INVALID_PARAMETER;
    236     }
    237   }
    238 
    239   //
    240   // Calculate graphics image data address in the image
    241   //
    242   Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
    243   ImageHeader   = Image;
    244 
    245   BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
    246   //
    247   // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
    248   //
    249   if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), NULL)) {
    250      return EFI_UNSUPPORTED;
    251   }
    252   BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    253 
    254   IsAllocated   = FALSE;
    255   if (*GopBlt == NULL) {
    256     *GopBltSize = (UINTN) BltBufferSize;
    257     *GopBlt     = EfiLibAllocatePool (*GopBltSize);
    258     IsAllocated = TRUE;
    259     if (*GopBlt == NULL) {
    260       return EFI_OUT_OF_RESOURCES;
    261     }
    262   } else {
    263     if (*GopBltSize < (UINTN) BltBufferSize) {
    264       *GopBltSize = (UINTN) BltBufferSize;
    265       return EFI_BUFFER_TOO_SMALL;
    266     }
    267   }
    268 
    269   *PixelWidth   = BmpHeader->PixelWidth;
    270   *PixelHeight  = BmpHeader->PixelHeight;
    271 
    272   //
    273   // Convert image from BMP to Blt buffer format
    274   //
    275   BltBuffer = *GopBlt;
    276   for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
    277     Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
    278     for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
    279       switch (BmpHeader->BitPerPixel) {
    280       case 1:
    281         //
    282         // Convert 1bit BMP to 24-bit color
    283         //
    284         for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
    285           Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
    286           Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
    287           Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
    288           Blt++;
    289           Width++;
    290         }
    291 
    292         Blt --;
    293         Width --;
    294         break;
    295 
    296       case 4:
    297         //
    298         // Convert BMP Palette to 24-bit color
    299         //
    300         Index       = (*Image) >> 4;
    301         Blt->Red    = BmpColorMap[Index].Red;
    302         Blt->Green  = BmpColorMap[Index].Green;
    303         Blt->Blue   = BmpColorMap[Index].Blue;
    304         if (Width < (BmpHeader->PixelWidth - 1)) {
    305           Blt++;
    306           Width++;
    307           Index       = (*Image) & 0x0f;
    308           Blt->Red    = BmpColorMap[Index].Red;
    309           Blt->Green  = BmpColorMap[Index].Green;
    310           Blt->Blue   = BmpColorMap[Index].Blue;
    311         }
    312         break;
    313 
    314       case 8:
    315         //
    316         // Convert BMP Palette to 24-bit color
    317         //
    318         Blt->Red    = BmpColorMap[*Image].Red;
    319         Blt->Green  = BmpColorMap[*Image].Green;
    320         Blt->Blue   = BmpColorMap[*Image].Blue;
    321         break;
    322 
    323       case 24:
    324         Blt->Blue   = *Image++;
    325         Blt->Green  = *Image++;
    326         Blt->Red    = *Image;
    327         break;
    328 
    329       default:
    330         if (IsAllocated) {
    331           gBS->FreePool (*GopBlt);
    332           *GopBlt = NULL;
    333         }
    334         return EFI_UNSUPPORTED;
    335         break;
    336       };
    337 
    338     }
    339 
    340     ImageIndex = (UINTN) (Image - ImageHeader);
    341     if ((ImageIndex % 4) != 0) {
    342       //
    343       // Bmp Image starts each row on a 32-bit boundary!
    344       //
    345       Image = Image + (4 - (ImageIndex % 4));
    346     }
    347   }
    348 
    349   return EFI_SUCCESS;
    350 }
    351 
    352 
    353 EFI_STATUS
    354 LockKeyboards (
    355   IN  CHAR16    *Password
    356   )
    357 /*++
    358 
    359 Routine Description:
    360   Use Console Control Protocol to lock the Console In Spliter virtual handle.
    361   This is the ConInHandle and ConIn handle in the EFI system table. All key
    362   presses will be ignored until the Password is typed in. The only way to
    363   disable the password is to type it in to a ConIn device.
    364 
    365 Arguments:
    366   Password - Password used to lock ConIn device
    367 
    368 
    369 Returns:
    370 
    371   EFI_SUCCESS     - ConsoleControl has been flipped to graphics and logo
    372                           displayed.
    373   EFI_UNSUPPORTED - Logo not found
    374 
    375 --*/
    376 {
    377   EFI_STATUS                    Status;
    378   EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;
    379 
    380   Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
    381   if (EFI_ERROR (Status)) {
    382     return EFI_UNSUPPORTED;
    383   }
    384 
    385   Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
    386   return Status;
    387 }
    388 
    389 EFI_STATUS
    390 EnableQuietBoot (
    391   IN  EFI_GUID  *LogoFile
    392   )
    393 /*++
    394 
    395 Routine Description:
    396 
    397   Use Console Control to turn off UGA based Simple Text Out consoles from going
    398   to the UGA device. Put up LogoFile on every UGA device that is a console
    399 
    400 Arguments:
    401 
    402   LogoFile - File name of logo to display on the center of the screen.
    403 
    404 
    405 Returns:
    406 
    407   EFI_SUCCESS           - ConsoleControl has been flipped to graphics and logo
    408                           displayed.
    409   EFI_UNSUPPORTED       - Logo not found
    410 
    411 --*/
    412 {
    413   return EnableQuietBootEx (LogoFile, NULL);
    414 }
    415 
    416 
    417 EFI_STATUS
    418 EnableQuietBootEx (
    419   IN  EFI_GUID    *LogoFile,
    420   IN  EFI_HANDLE  ImageHandle
    421   )
    422 /*++
    423 
    424 Routine Description:
    425 
    426   Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going
    427   to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console
    428 
    429 Arguments:
    430 
    431   LogoFile - File name of logo to display on the center of the screen.
    432 
    433 
    434 Returns:
    435 
    436   EFI_SUCCESS           - ConsoleControl has been flipped to graphics and logo
    437                           displayed.
    438   EFI_UNSUPPORTED       - Logo not found
    439 
    440 --*/
    441 {
    442   EFI_STATUS                    Status;
    443   EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;
    444   EFI_OEM_BADGING_PROTOCOL      *Badging;
    445   UINT32                        SizeOfX;
    446   UINT32                        SizeOfY;
    447   INTN                          DestX;
    448   INTN                          DestY;
    449   UINT8                         *ImageData;
    450   UINTN                         ImageSize;
    451   UINTN                         BltSize;
    452   UINT32                        Instance;
    453   EFI_BADGING_FORMAT            Format;
    454   EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
    455   UINTN                         CoordinateX;
    456   UINTN                         CoordinateY;
    457   UINTN                         Height;
    458   UINTN                         Width;
    459   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
    460   EFI_UGA_DRAW_PROTOCOL         *UgaDraw;
    461   UINT32                        ColorDepth;
    462   UINT32                        RefreshRate;
    463   EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
    464 
    465   Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
    466   if (EFI_ERROR (Status)) {
    467     return EFI_UNSUPPORTED;
    468   }
    469 
    470   UgaDraw = NULL;
    471   //
    472   // Try to open GOP first
    473   //
    474   Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
    475   if (EFI_ERROR (Status)) {
    476     GraphicsOutput = NULL;
    477     //
    478     // Open GOP failed, try to open UGA
    479     //
    480     Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
    481     if (EFI_ERROR (Status)) {
    482       return EFI_UNSUPPORTED;
    483     }
    484   }
    485 
    486   Badging = NULL;
    487   Status  = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
    488 
    489   ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
    490 
    491   if (GraphicsOutput != NULL) {
    492     SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
    493     SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
    494   } else if (UgaDraw != NULL) {
    495     Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
    496     if (EFI_ERROR (Status)) {
    497       return EFI_UNSUPPORTED;
    498     }
    499   } else {
    500     return EFI_UNSUPPORTED;
    501   }
    502 
    503   Instance = 0;
    504   while (1) {
    505     ImageData = NULL;
    506     ImageSize = 0;
    507 
    508     if (Badging != NULL) {
    509       Status = Badging->GetImage (
    510                           Badging,
    511                           &Instance,
    512                           &Format,
    513                           &ImageData,
    514                           &ImageSize,
    515                           &Attribute,
    516                           &CoordinateX,
    517                           &CoordinateY
    518                           );
    519       if (EFI_ERROR (Status)) {
    520         return Status;
    521       }
    522 
    523       //
    524       // Currently only support BMP format
    525       //
    526       if (Format != EfiBadgingFormatBMP) {
    527         gBS->FreePool (ImageData);
    528         continue;
    529       }
    530     } else {
    531       Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
    532       if (EFI_ERROR (Status)) {
    533         return EFI_UNSUPPORTED;
    534       }
    535 
    536       CoordinateX = 0;
    537       CoordinateY = 0;
    538       Attribute   = EfiBadgingDisplayAttributeCenter;
    539     }
    540 
    541     Blt = NULL;
    542     Status = ConvertBmpToGopBlt (
    543               ImageData,
    544               ImageSize,
    545               (VOID **) &Blt,
    546               &BltSize,
    547               &Height,
    548               &Width
    549               );
    550     if (EFI_ERROR (Status)) {
    551       gBS->FreePool (ImageData);
    552       if (Badging == NULL) {
    553         return Status;
    554       } else {
    555         continue;
    556       }
    557     }
    558 
    559     switch (Attribute) {
    560     case EfiBadgingDisplayAttributeLeftTop:
    561       DestX = CoordinateX;
    562       DestY = CoordinateY;
    563       break;
    564 
    565     case EfiBadgingDisplayAttributeCenterTop:
    566       DestX = (SizeOfX - Width) / 2;
    567       DestY = CoordinateY;
    568       break;
    569 
    570     case EfiBadgingDisplayAttributeRightTop:
    571       DestX = (SizeOfX - Width - CoordinateX);
    572       DestY = CoordinateY;;
    573       break;
    574 
    575     case EfiBadgingDisplayAttributeCenterRight:
    576       DestX = (SizeOfX - Width - CoordinateX);
    577       DestY = (SizeOfY - Height) / 2;
    578       break;
    579 
    580     case EfiBadgingDisplayAttributeRightBottom:
    581       DestX = (SizeOfX - Width - CoordinateX);
    582       DestY = (SizeOfY - Height - CoordinateY);
    583       break;
    584 
    585     case EfiBadgingDisplayAttributeCenterBottom:
    586       DestX = (SizeOfX - Width) / 2;
    587       DestY = (SizeOfY - Height - CoordinateY);
    588       break;
    589 
    590     case EfiBadgingDisplayAttributeLeftBottom:
    591       DestX = CoordinateX;
    592       DestY = (SizeOfY - Height - CoordinateY);
    593       break;
    594 
    595     case EfiBadgingDisplayAttributeCenterLeft:
    596       DestX = CoordinateX;
    597       DestY = (SizeOfY - Height) / 2;
    598       break;
    599 
    600     case EfiBadgingDisplayAttributeCenter:
    601       DestX = (SizeOfX - Width) / 2;
    602       DestY = (SizeOfY - Height) / 2;
    603       break;
    604 
    605     default:
    606       DestX = CoordinateX;
    607       DestY = CoordinateY;
    608       break;
    609     }
    610 
    611     if ((DestX >= 0) && (DestY >= 0)) {
    612       if (GraphicsOutput != NULL) {
    613         Status = GraphicsOutput->Blt (
    614                             GraphicsOutput,
    615                             Blt,
    616                             EfiBltBufferToVideo,
    617                             0,
    618                             0,
    619                             (UINTN) DestX,
    620                             (UINTN) DestY,
    621                             Width,
    622                             Height,
    623                             Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
    624                             );
    625       } else {
    626         Status = UgaDraw->Blt (
    627                             UgaDraw,
    628                             (EFI_UGA_PIXEL *) Blt,
    629                             EfiUgaBltBufferToVideo,
    630                             0,
    631                             0,
    632                             (UINTN) DestX,
    633                             (UINTN) DestY,
    634                             Width,
    635                             Height,
    636                             Width * sizeof (EFI_UGA_PIXEL)
    637                             );
    638       }
    639     }
    640 
    641     gBS->FreePool (ImageData);
    642     gBS->FreePool (Blt);
    643 
    644     if (Badging == NULL) {
    645       break;
    646     }
    647   }
    648 
    649   return Status;
    650 }
    651 
    652 
    653 EFI_STATUS
    654 DisableQuietBoot (
    655   VOID
    656   )
    657 /*++
    658 
    659 Routine Description:
    660 
    661   Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
    662   Simple Text Out screens will now be synced up with all non GOP/UGA output devices
    663 
    664 Arguments:
    665 
    666   NONE
    667 
    668 Returns:
    669 
    670   EFI_SUCCESS           - GOP/UGA devices are back in text mode and synced up.
    671   EFI_UNSUPPORTED       - Logo not found
    672 
    673 --*/
    674 {
    675   EFI_STATUS                    Status;
    676   EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;
    677 
    678   Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
    679   if (EFI_ERROR (Status)) {
    680     return EFI_UNSUPPORTED;
    681   }
    682 
    683   return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
    684 }
    685