mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 19:02:32 +00:00
281 lines
8.4 KiB
C
281 lines
8.4 KiB
C
/*
|
|
* COPYRIGHT: See COPYING.ARM in the top level directory
|
|
* PROJECT: ReactOS UEFI Boot Library
|
|
* FILE: boot/environ/lib/io/display/efi/gop.c
|
|
* PURPOSE: Boot Library EFI GOP Routines
|
|
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "bl.h"
|
|
|
|
/* DATA VARIABLES ************************************************************/
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
NTSTATUS
|
|
ConsoleEfiGopGetGraphicalFormat (
|
|
_In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo,
|
|
_Out_ PULONG PixelDepth
|
|
)
|
|
{
|
|
/* Convert the format to depth */
|
|
if (ModeInfo->PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
|
|
{
|
|
*PixelDepth = 32;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
if (ModeInfo->PixelFormat == PixelBitMask)
|
|
{
|
|
*PixelDepth = 24;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
BOOLEAN
|
|
ConsoleEfiGopIsPixelFormatSupported (
|
|
_In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode
|
|
)
|
|
{
|
|
BOOLEAN Supported;
|
|
EFI_PIXEL_BITMASK PixelMask;
|
|
|
|
Supported = FALSE;
|
|
|
|
/* Check if it's simple BGR8 */
|
|
if (Mode->PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
|
|
{
|
|
Supported = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise, we can check if it's a masked format */
|
|
if (Mode->PixelFormat == PixelBitMask)
|
|
{
|
|
/* Check if the masked format is BGR8 */
|
|
PixelMask.BlueMask = 0xFF;
|
|
PixelMask.GreenMask = 0xFF00;
|
|
PixelMask.RedMask = 0xFF0000;
|
|
PixelMask.ReservedMask = 0;
|
|
if (RtlEqualMemory(&Mode->PixelInformation,
|
|
&PixelMask,
|
|
sizeof(PixelMask)))
|
|
{
|
|
Supported = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return if the format was supported */
|
|
return Supported;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ConsoleEfiGopFindModeFromAllowed (
|
|
_In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol,
|
|
_In_ PBL_DISPLAY_MODE SupportedModes,
|
|
_In_ ULONG MaximumIndex,
|
|
_Out_ PULONG SupportedMode
|
|
)
|
|
{
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleEfiGopEnable (
|
|
_In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
|
|
)
|
|
{
|
|
PVOID FrameBuffer;
|
|
UINTN CurrentMode, Dummy;
|
|
ULONG Mode, PixelDepth;
|
|
UINTN FrameBufferSize;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL* Protocol;
|
|
NTSTATUS Status;
|
|
PHYSICAL_ADDRESS FrameBufferPhysical;
|
|
|
|
/* Capture the current mode and protocol */
|
|
Mode = GraphicsConsole->Mode;
|
|
Protocol = GraphicsConsole->Protocol;
|
|
|
|
/* Get the current mode and its information */
|
|
Status = EfiGopGetCurrentMode(Protocol, &CurrentMode, &ModeInformation);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Check if we're not in the mode we should be */
|
|
if (CurrentMode != Mode)
|
|
{
|
|
/* Switch modes */
|
|
Status = EfiGopSetMode(Protocol, Mode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Reset the OEM bitmap and get the new more information */
|
|
BlDisplayInvalidateOemBitmap();
|
|
EfiGopGetCurrentMode(Protocol, &Dummy, &ModeInformation);
|
|
}
|
|
|
|
/* Get the pixel depth for this mode */
|
|
Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Get the framebuffer for this mode */
|
|
EfiGopGetFrameBuffer(Protocol, &FrameBufferPhysical, &FrameBufferSize);
|
|
|
|
/* Map the framebuffer, try as writeback first */
|
|
FrameBuffer = NULL;
|
|
Status = BlMmMapPhysicalAddressEx(&FrameBuffer,
|
|
BlMemoryWriteBack,
|
|
FrameBufferSize,
|
|
FrameBufferPhysical);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* That didn't work, so try uncached next */
|
|
Status = BlMmMapPhysicalAddressEx(&FrameBuffer,
|
|
BlMemoryUncached,
|
|
FrameBufferSize,
|
|
FrameBufferPhysical);
|
|
}
|
|
}
|
|
|
|
/* Check if getting all the required information worked out */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Capture the resolution, depth, and framebuffer information */
|
|
GraphicsConsole->DisplayMode.HRes = ModeInformation.HorizontalResolution;
|
|
GraphicsConsole->DisplayMode.VRes = ModeInformation.VerticalResolution;
|
|
GraphicsConsole->DisplayMode.HRes2 = ModeInformation.PixelsPerScanLine;
|
|
GraphicsConsole->PixelDepth = PixelDepth;
|
|
GraphicsConsole->FrameBuffer = FrameBuffer;
|
|
GraphicsConsole->FrameBufferSize = FrameBufferSize;
|
|
GraphicsConsole->PixelsPerScanLine = ModeInformation.PixelsPerScanLine;
|
|
|
|
/* All good */
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else if (CurrentMode != GraphicsConsole->Mode)
|
|
{
|
|
/* We failed somewhere, reset the mode and the OEM bitmap back */
|
|
EfiGopSetMode(Protocol, CurrentMode);
|
|
BlDisplayInvalidateOemBitmap();
|
|
}
|
|
|
|
/* Return back to caller */
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
ConsoleEfiGopClose (
|
|
_In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
|
|
)
|
|
{
|
|
ULONG OldMode;
|
|
|
|
/* Did we switch modes when we turned on the console? */
|
|
OldMode = GraphicsConsole->OldMode;
|
|
if (GraphicsConsole->Mode != OldMode)
|
|
{
|
|
/* Restore the old mode and reset the OEM bitmap in ACPI */
|
|
EfiGopSetMode(GraphicsConsole->Protocol, OldMode);
|
|
BlDisplayInvalidateOemBitmap();
|
|
}
|
|
|
|
/* Close the GOP protocol */
|
|
EfiCloseProtocol(GraphicsConsole->Handle,
|
|
&EfiGraphicsOutputProtocol);
|
|
}
|
|
|
|
NTSTATUS
|
|
ConsoleEfiGopOpen (
|
|
_In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol;
|
|
ULONG Mode, PixelDepth;
|
|
UINTN CurrentMode;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation;
|
|
BOOLEAN CurrentModeOk;
|
|
|
|
/* Open a handle to GOP */
|
|
Status = EfiOpenProtocol(GraphicsConsole->Handle,
|
|
&EfiGraphicsOutputProtocol,
|
|
(PVOID*)&GopProtocol);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"GOP OPEN failed: %lx\r\n", Status);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* Get the current mode */
|
|
Status = EfiGopGetCurrentMode(GopProtocol, &CurrentMode, &ModeInformation);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
EfiPrintf(L"GOP mode failed: %lx\r\n", Status);
|
|
goto Quickie;
|
|
}
|
|
|
|
Mode = CurrentMode;
|
|
|
|
/* Check if any custom BCD options were provided */
|
|
if (ConsoleGraphicalResolutionListFlags &
|
|
(BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG |
|
|
BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG))
|
|
{
|
|
/* We'll have to find a mode */
|
|
CurrentModeOk = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Then we should be in the default mode, check if the pixel format is OK */
|
|
CurrentModeOk = ConsoleEfiGopIsPixelFormatSupported(&ModeInformation);
|
|
}
|
|
|
|
/* Is the mode/format OK? */
|
|
if (!CurrentModeOk)
|
|
{
|
|
/* Nope -- we'll have to go find one */
|
|
Status = ConsoleEfiGopFindModeFromAllowed(GopProtocol,
|
|
ConsoleGraphicalResolutionList,
|
|
ConsoleGraphicalResolutionListSize,
|
|
&Mode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Quickie;
|
|
}
|
|
}
|
|
|
|
/* Store mode information */
|
|
GraphicsConsole->Protocol = GopProtocol;
|
|
GraphicsConsole->Mode = Mode;
|
|
GraphicsConsole->OldMode = CurrentMode;
|
|
|
|
/* Get format information */
|
|
Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Store it */
|
|
GraphicsConsole->OldDisplayMode.HRes = ModeInformation.HorizontalResolution;
|
|
GraphicsConsole->OldDisplayMode.VRes = ModeInformation.VerticalResolution;
|
|
GraphicsConsole->OldDisplayMode.HRes2 = ModeInformation.PixelsPerScanLine;
|
|
GraphicsConsole->PixelDepth = PixelDepth;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Quickie:
|
|
/* We failed, close the protocol and return the failure code */
|
|
EfiPrintf(L"Get format failed: %lx\r\n", Status);
|
|
EfiCloseProtocol(GraphicsConsole->Handle, &EfiGraphicsOutputProtocol);
|
|
return Status;
|
|
}
|
|
|