graphicsconsole.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,847 行 · 第 1/4 页

C
1,847
字号
/*++

Copyright (c) 2004 - 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

  GraphicsConsole.c
  
Abstract:

  This is the main routine for initializing the Graphics Console support routines.

Revision History

Remaining Tasks
  Add all standard Glyphs from EFI 1.02 Specification
  Implement optimal automatic Mode creation algorithm
  Solve palette issues for mixed graphics and text
  When does this protocol reset the palette?

--*/

#include "GraphicsConsole.h"
#include "IfrLibrary.h"

//
// Function Prototypes
//
EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN  EFI_HANDLE                     Controller,
  IN  UINTN                          NumberOfChildren,
  IN  EFI_HANDLE                     *ChildHandleBuffer
  );

EFI_STATUS
GetTextColors (
  IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *This,
  OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
  OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
  );

EFI_STATUS
DrawUnicodeWeightAtCursor (
  IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *This,
  IN  CHAR16                        UnicodeWeight
  );

EFI_STATUS
DrawUnicodeWeightAtCursorN (
  IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *This,
  IN  CHAR16                        *UnicodeWeight,
  IN  UINTN                         Count
  );

EFI_STATUS
EraseCursor (
  IN  EFI_SIMPLE_TEXT_OUT_PROTOCOL  *This
  );

//
// Globals
//
GRAPHICS_CONSOLE_DEV        mGraphicsConsoleDevTemplate = {
  GRAPHICS_CONSOLE_DEV_SIGNATURE,
  (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL,
  (EFI_UGA_DRAW_PROTOCOL *) NULL,
  {
    GraphicsConsoleConOutReset,
    GraphicsConsoleConOutOutputString,
    GraphicsConsoleConOutTestString,
    GraphicsConsoleConOutQueryMode,
    GraphicsConsoleConOutSetMode,
    GraphicsConsoleConOutSetAttribute,
    GraphicsConsoleConOutClearScreen,
    GraphicsConsoleConOutSetCursorPosition,
    GraphicsConsoleConOutEnableCursor,
    (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
  },
  {
    0,
    0,
    EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK),
    0,
    0,
    TRUE
  },
  {
    { 80, 25, 0, 0, 0, 0 },  // Mode 0
    { 80, 50, 0, 0, 0, 0 },  // Mode 1
    {  0,  0, 0, 0, 0, 0 }   // Mode 2
  },
  (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
  (EFI_HII_HANDLE) 0
};

EFI_HII_PROTOCOL            *mHii;

static CHAR16               mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };

static EFI_GRAPHICS_OUTPUT_BLT_PIXEL        mEfiColors[16] = {
  //
  // B     G     R
  //
  0x00, 0x00, 0x00, 0x00,  // BLACK
  0x98, 0x00, 0x00, 0x00,  // BLUE
  0x00, 0x98, 0x00, 0x00,  // GREEN
  0x98, 0x98, 0x00, 0x00,  // CYAN
  0x00, 0x00, 0x98, 0x00,  // RED
  0x98, 0x00, 0x98, 0x00,  // MAGENTA
  0x00, 0x98, 0x98, 0x00,  // BROWN
  0x98, 0x98, 0x98, 0x00,  // LIGHTGRAY
  0x30, 0x30, 0x30, 0x00,  // DARKGRAY - BRIGHT BLACK
  0xff, 0x00, 0x00, 0x00,  // LIGHTBLUE - ?
  0x00, 0xff, 0x00, 0x00,  // LIGHTGREEN - ?
  0xff, 0xff, 0x00, 0x00,  // LIGHTCYAN
  0x00, 0x00, 0xff, 0x00,  // LIGHTRED
  0xff, 0x00, 0xff, 0x00,  // LIGHTMAGENTA
  0x00, 0xff, 0xff, 0x00,  // LIGHTBROWN
  0xff, 0xff, 0xff, 0x00,  // WHITE
};

static EFI_NARROW_GLYPH     mCursorGlyph = {
  0x0000,
  0x00,
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
};

EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {
  GraphicsConsoleControllerDriverSupported,
  GraphicsConsoleControllerDriverStart,
  GraphicsConsoleControllerDriverStop,
  0x10,
  NULL,
  NULL
};

//
// Body of the driver
//
EFI_DRIVER_ENTRY_POINT (InitializeGraphicsConsole)

EFI_STATUS
EFIAPI
InitializeGraphicsConsole (
  IN  EFI_HANDLE         ImageHandle,
  IN  EFI_SYSTEM_TABLE   *SystemTable
  )
/*++
  Routine Description:
  
    This function is the entry point of Graphics Console driver. It will install a Graphics Console.
  
  Arguments:
  
    ImageHandle - A handle for the image that is initializing this driver.
         
    SystemTable - A pointer to the EFI system table.
        
  Returns:
  
    EFI_SUCCESS
       only returns this status code.

--*/
{
  return INSTALL_ALL_DRIVER_PROTOCOLS (
          ImageHandle,
          SystemTable,
          &gGraphicsConsoleDriverBinding,
          ImageHandle,
          &gGraphicsConsoleComponentName,
          NULL,
          NULL
          );
}

EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                   Status;
  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
  EFI_UGA_DRAW_PROTOCOL        *UgaDraw;
  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;

  UgaDraw = NULL;
  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiGraphicsOutputProtocolGuid,
                  (VOID **) &GraphicsOutput,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    GraphicsOutput = NULL;
    //
    // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
    //
    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiUgaDrawProtocolGuid,
                    (VOID **) &UgaDraw,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  //
  // We need to ensure that we do not layer on top of a virtual handle.
  // We need to ensure that the handles produced by the conspliter do not
  // get used.
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    gBS->CloseProtocol (
          Controller,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          Controller
          );
  } else {
    goto Error;
  }
  //
  // Does Hii Exist?  If not, we aren't ready to run
  //
  Status = EfiLocateHiiProtocol ();

  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
Error:
  if (GraphicsOutput != NULL) {
    gBS->CloseProtocol (
          Controller,
          &gEfiGraphicsOutputProtocolGuid,
          This->DriverBindingHandle,
          Controller
          );
  } else {
    gBS->CloseProtocol (
          Controller,
          &gEfiUgaDrawProtocolGuid,
          This->DriverBindingHandle,
          Controller
          );
  }

  return Status;
}

EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
/*++

  Routine Description:

    Start the controller.

  Arguments:

    This                - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    Controller          - The handle of the controller to start.
    RemainingDevicePath - A pointer to the remaining portion of a devcie path.

  Returns:

    EFI_SUCCESS          - Return successfully.
    EFI_OUT_OF_RESOURCES - Out of resources.

--*/
{
  EFI_STATUS                           Status;
  GRAPHICS_CONSOLE_DEV                 *Private;
  EFI_HII_PACKAGES                     *Package;
  EFI_HII_FONT_PACK                    *FontPack;
  UINTN                                NarrowFontSize;
  UINT32                               HorizontalResolution;
  UINT32                               VerticalResolution;
  UINT32                               ColorDepth;
  UINT32                               RefreshRate;
  UINTN                                MaxMode;
  UINTN                                Columns;
  UINTN                                Rows;
  UINT8                                *Location;
  UINT32                               ModeNumber;
  UINTN                                SizeOfInfo;
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;

  ModeNumber = 0;

  //
  // Initialize the Graphics Console device instance
  //
  Private = EfiLibAllocateCopyPool (
              sizeof (GRAPHICS_CONSOLE_DEV),
              &mGraphicsConsoleDevTemplate
              );
  if (Private == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode);

  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiGraphicsOutputProtocolGuid,
                  (VOID **) &Private->GraphicsOutput,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    Private->GraphicsOutput = NULL;

    Status = gBS->OpenProtocol (
                    Controller,
                    &gEfiUgaDrawProtocolGuid,
                    (VOID **) &Private->UgaDraw,
                    This->DriverBindingHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (EFI_ERROR (Status)) {
      goto Error;
    }
  }

  //
  // Get the HII protocol. If Supported() succeeds, do we really
  // need to get HII protocol again?
  //
  Status = EfiLocateHiiProtocol ();
  if (EFI_ERROR (Status)) {
    goto Error;
  }

  NarrowFontSize  = ReturnNarrowFontSize ();

  FontPack        = EfiLibAllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);
  ASSERT (FontPack);

  FontPack->Header.Length         = (UINT32) (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);
  FontPack->Header.Type           = EFI_HII_FONT;
  FontPack->NumberOfNarrowGlyphs  = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH));

  Location                        = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8));
  EfiCopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize);

  //
  // Register our Fonts into the global database
  //
  Package = PreparePackages (1, NULL, FontPack);
  mHii->NewPack (mHii, Package, &(Private->HiiHandle));
  gBS->FreePool (Package);

  //
  // Free the font database
  //
  gBS->FreePool (FontPack);

  //
  // If the current mode information can not be retrieved, then attemp to set the default mode
  // of 800x600, 32 bit colot, 60 Hz refresh.
  //
  HorizontalResolution  = 800;
  VerticalResolution    = 600;

  if (Private->GraphicsOutput != NULL) {
    //
    // The console is build on top of Graphics Output Protocol, find the mode number for 800x600
    //
    for (ModeNumber = 0; ModeNumber < Private->GraphicsOutput->Mode->MaxMode; ModeNumber++) {
      Status = Private->GraphicsOutput->QueryMode (
                         Private->GraphicsOutput,
                         ModeNumber,
                         &SizeOfInfo,
                         &Info
                         );
      if (!EFI_ERROR (Status)) {
        if ((Info->HorizontalResolution == 800) &&
            (Info->VerticalResolution == 600)) {
          Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber);
          if (!EFI_ERROR (Status)) {
            gBS->FreePool (Info);
            break;
          }
        }
        gBS->FreePool (Info);
      }
    }

    if (EFI_ERROR (Status) || (ModeNumber == Private->GraphicsOutput->Mode->MaxMode)) {
      //
      // Set default mode failed or device don't support default mode, then get the current mode information
      //
      HorizontalResolution = Private->GraphicsOutput->Mode->Info->HorizontalResolution;
      VerticalResolution = Private->GraphicsOutput->Mode->Info->VerticalResolution;
      ModeNumber = Private->GraphicsOutput->Mode->Mode;
    }
  } else {
    //
    // The console is build on top of UGA Draw Protocol
    //
    ColorDepth            = 32;
    RefreshRate           = 60;
    Status = Private->UgaDraw->SetMode (
                                Private->UgaDraw,
                                HorizontalResolution,
                                VerticalResolution,
                                ColorDepth,
                                RefreshRate

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?