123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /** @file
- This file implements the Graphics Output protocol for Arm platforms
- Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DevicePathLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiRuntimeServicesTableLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Guid/GlobalVariable.h>
- #include "LcdGraphicsOutputDxe.h"
- //
- // Global variables
- //
- BOOLEAN mDisplayInitialized = FALSE;
- LCD_INSTANCE mLcdTemplate = {
- LCD_INSTANCE_SIGNATURE,
- NULL, // Handle
- { // ModeInfo
- 0, // Version
- 0, // HorizontalResolution
- 0, // VerticalResolution
- PixelBltOnly, // PixelFormat
- { 0 }, // PixelInformation
- 0, // PixelsPerScanLine
- },
- {
- 0, // MaxMode;
- 0, // Mode;
- NULL, // Info;
- 0, // SizeOfInfo;
- 0, // FrameBufferBase;
- 0 // FrameBufferSize;
- },
- { // Gop
- LcdGraphicsQueryMode, // QueryMode
- LcdGraphicsSetMode, // SetMode
- LcdGraphicsBlt, // Blt
- NULL // *Mode
- },
- { // DevicePath
- {
- {
- HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
- {
- (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
- (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
- },
- },
- // Hardware Device Path for Lcd
- EFI_CALLER_ID_GUID // Use the driver's GUID
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- sizeof (EFI_DEVICE_PATH_PROTOCOL),
- 0
- }
- }
- },
- (EFI_EVENT)NULL // ExitBootServicesEvent
- };
- EFI_STATUS
- LcdInstanceContructor (
- OUT LCD_INSTANCE** NewInstance
- )
- {
- LCD_INSTANCE* Instance;
- Instance = AllocateCopyPool (sizeof (LCD_INSTANCE), &mLcdTemplate);
- if (Instance == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Instance->Gop.Mode = &Instance->Mode;
- Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
- Instance->Mode.Info = &Instance->ModeInfo;
- *NewInstance = Instance;
- return EFI_SUCCESS;
- }
- //
- // Function Definitions
- //
- EFI_STATUS
- InitializeDisplay (
- IN LCD_INSTANCE* Instance
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- EFI_PHYSICAL_ADDRESS VramBaseAddress;
- UINTN VramSize;
- Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- // Setup the LCD
- Status = LcdInitialize (VramBaseAddress);
- if (EFI_ERROR (Status)) {
- goto EXIT_ERROR_LCD_SHUTDOWN;
- }
- Status = LcdPlatformInitializeDisplay (Instance->Handle);
- if (EFI_ERROR (Status)) {
- goto EXIT_ERROR_LCD_SHUTDOWN;
- }
- // Setup all the relevant mode information
- Instance->Gop.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
- Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
- // Set the flag before changing the mode, to avoid infinite loops
- mDisplayInitialized = TRUE;
- // All is ok, so don't deal with any errors
- goto EXIT;
- EXIT_ERROR_LCD_SHUTDOWN:
- DEBUG ((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
- LcdShutdown ();
- EXIT:
- return Status;
- }
- EFI_STATUS
- EFIAPI
- LcdGraphicsOutputDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- LCD_INSTANCE* Instance;
- Status = LcdIdentify ();
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
- Status = LcdInstanceContructor (&Instance);
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
- // Install the Graphics Output Protocol and the Device Path
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Instance->Handle,
- &gEfiGraphicsOutputProtocolGuid,
- &Instance->Gop,
- &gEfiDevicePathProtocolGuid,
- &Instance->DevicePath,
- NULL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
- goto EXIT;
- }
- // Register for an ExitBootServicesEvent
- // When ExitBootServices starts, this function will make sure that the
- // graphics driver shuts down properly, i.e. it will free up all
- // allocated memory and perform any necessary hardware re-configuration.
- Status = gBS->CreateEvent (
- EVT_SIGNAL_EXIT_BOOT_SERVICES,
- TPL_NOTIFY,
- LcdGraphicsExitBootServicesEvent,
- NULL,
- &Instance->ExitBootServicesEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
- goto EXIT_ERROR_UNINSTALL_PROTOCOL;
- }
- // To get here, everything must be fine, so just exit
- goto EXIT;
- EXIT_ERROR_UNINSTALL_PROTOCOL:
- // The following function could return an error message,
- // however, to get here something must have gone wrong already,
- // so preserve the original error, i.e. don't change
- // the Status variable, even it fails to uninstall the protocol.
- gBS->UninstallMultipleProtocolInterfaces (
- Instance->Handle,
- &gEfiGraphicsOutputProtocolGuid,
- &Instance->Gop, // Uninstall Graphics Output protocol
- &gEfiDevicePathProtocolGuid,
- &Instance->DevicePath, // Uninstall device path
- NULL
- );
- EXIT:
- return Status;
- }
- /** This function should be called
- on Event: ExitBootServices
- to free up memory, stop the driver
- and uninstall the protocols
- **/
- VOID
- LcdGraphicsExitBootServicesEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- // By default, this PCD is FALSE. But if a platform starts a predefined OS
- // that does not use a framebuffer then we might want to disable the display
- // controller to avoid to display corrupted information on the screen.
- if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {
- // Turn-off the Display controller
- LcdShutdown ();
- }
- }
- /** GraphicsOutput Protocol function, mapping to
- EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
- **/
- EFI_STATUS
- EFIAPI
- LcdGraphicsQueryMode (
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
- IN UINT32 ModeNumber,
- OUT UINTN *SizeOfInfo,
- OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- LCD_INSTANCE *Instance;
- Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
- // Setup the hardware if not already done
- if (!mDisplayInitialized) {
- Status = InitializeDisplay (Instance);
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
- }
- // Error checking
- if ((This == NULL) ||
- (Info == NULL) ||
- (SizeOfInfo == NULL) ||
- (ModeNumber >= This->Mode->MaxMode)) {
- DEBUG ((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber));
- Status = EFI_INVALID_PARAMETER;
- goto EXIT;
- }
- *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
- if (*Info == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto EXIT;
- }
- *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
- Status = LcdPlatformQueryMode (ModeNumber, *Info);
- if (EFI_ERROR (Status)) {
- FreePool (*Info);
- }
- EXIT:
- return Status;
- }
- /** GraphicsOutput Protocol function, mapping to
- EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
- **/
- EFI_STATUS
- EFIAPI
- LcdGraphicsSetMode (
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
- IN UINT32 ModeNumber
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;
- LCD_INSTANCE* Instance;
- LCD_BPP Bpp;
- Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
- // Setup the hardware if not already done
- if (!mDisplayInitialized) {
- Status = InitializeDisplay (Instance);
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
- }
- // Check if this mode is supported
- if (ModeNumber >= This->Mode->MaxMode) {
- DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber));
- Status = EFI_UNSUPPORTED;
- goto EXIT;
- }
- // Set the oscillator frequency to support the new mode
- Status = LcdPlatformSetMode (ModeNumber);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto EXIT;
- }
- // Update the UEFI mode information
- This->Mode->Mode = ModeNumber;
- LcdPlatformQueryMode (ModeNumber, &Instance->ModeInfo);
- Status = LcdPlatformGetBpp (ModeNumber, &Bpp);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));
- goto EXIT;
- }
- This->Mode->FrameBufferSize = Instance->ModeInfo.VerticalResolution
- * Instance->ModeInfo.PixelsPerScanLine
- * GetBytesPerPixel (Bpp);
- // Set the hardware to the new mode
- Status = LcdSetMode (ModeNumber);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto EXIT;
- }
- // The UEFI spec requires that we now clear the visible portions of the
- // output display to black.
- // Set the fill colour to black
- SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
- // Fill the entire visible area with the same colour.
- Status = This->Blt (
- This,
- &FillColour,
- EfiBltVideoFill,
- 0,
- 0,
- 0,
- 0,
- This->Mode->Info->HorizontalResolution,
- This->Mode->Info->VerticalResolution,
- 0
- );
- EXIT:
- return Status;
- }
- UINTN
- GetBytesPerPixel (
- IN LCD_BPP Bpp
- )
- {
- switch (Bpp) {
- case LCD_BITS_PER_PIXEL_24:
- return 4;
- case LCD_BITS_PER_PIXEL_16_565:
- case LCD_BITS_PER_PIXEL_16_555:
- case LCD_BITS_PER_PIXEL_12_444:
- return 2;
- case LCD_BITS_PER_PIXEL_8:
- case LCD_BITS_PER_PIXEL_4:
- case LCD_BITS_PER_PIXEL_2:
- case LCD_BITS_PER_PIXEL_1:
- return 1;
- default:
- return 0;
- }
- }
|