diff --git a/Include/Library/OcConfigurationLib.h b/Include/Library/OcConfigurationLib.h index ab938617..011734dd 100644 --- a/Include/Library/OcConfigurationLib.h +++ b/Include/Library/OcConfigurationLib.h @@ -489,7 +489,8 @@ OC_DECLARE (OC_UEFI_INPUT) _(BOOLEAN , ProvideEarlyConsole , , FALSE , ()) \ _(BOOLEAN , ReplaceTabWithSpace , , FALSE , ()) \ _(BOOLEAN , ReconnectOnResChange , , FALSE , ()) \ - _(BOOLEAN , SanitiseClearScreen , , FALSE , ()) + _(BOOLEAN , SanitiseClearScreen , , FALSE , ()) \ + _(BOOLEAN , DirectGopRendering , , FALSE , ()) OC_DECLARE (OC_UEFI_OUTPUT) /// diff --git a/Include/Library/OcConsoleLib.h b/Include/Library/OcConsoleLib.h index e195bc54..37eca7c1 100644 --- a/Include/Library/OcConsoleLib.h +++ b/Include/Library/OcConsoleLib.h @@ -139,6 +139,14 @@ OcReconnectConsole ( VOID ); +/** + Use direct GOP renderer for console. +**/ +EFI_STATUS +OcUseDirectGop ( + VOID + ); + /** Allocate new System Table with disabled text output. diff --git a/Library/OcConfigurationLib/OcConfigurationLib.c b/Library/OcConfigurationLib/OcConfigurationLib.c index ac955be7..6c9fb341 100644 --- a/Library/OcConfigurationLib/OcConfigurationLib.c +++ b/Library/OcConfigurationLib/OcConfigurationLib.c @@ -561,6 +561,7 @@ OC_SCHEMA mUefiOutputSchema[] = { OC_SCHEMA_BOOLEAN_IN ("ClearScreenOnModeSwitch",OC_GLOBAL_CONFIG, Uefi.Output.ClearScreenOnModeSwitch), OC_SCHEMA_STRING_IN ("ConsoleMode", OC_GLOBAL_CONFIG, Uefi.Output.ConsoleMode), + OC_SCHEMA_BOOLEAN_IN ("DirectGopRendering", OC_GLOBAL_CONFIG, Uefi.Output.DirectGopRendering), OC_SCHEMA_BOOLEAN_IN ("IgnoreTextInGraphics", OC_GLOBAL_CONFIG, Uefi.Output.IgnoreTextInGraphics), OC_SCHEMA_BOOLEAN_IN ("ProvideConsoleGop", OC_GLOBAL_CONFIG, Uefi.Output.ProvideConsoleGop), OC_SCHEMA_BOOLEAN_IN ("ProvideEarlyConsole", OC_GLOBAL_CONFIG, Uefi.Output.ProvideEarlyConsole), diff --git a/Library/OcConsoleLib/ConsoleGop.c b/Library/OcConsoleLib/ConsoleGop.c index 83aa124e..c0eb06fb 100644 --- a/Library/OcConsoleLib/ConsoleGop.c +++ b/Library/OcConsoleLib/ConsoleGop.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,14 @@ STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL * mConsoleGraphicsOutput; +STATIC +FRAME_BUFFER_CONFIGURE * +mFramebufferContext; + +STATIC +EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE +mOriginalGopSetMode; + STATIC EFI_STATUS EFIAPI @@ -166,6 +175,110 @@ OcProvideConsoleGop ( } } +STATIC +FRAME_BUFFER_CONFIGURE * +EFIAPI +DirectGopFromTarget ( + IN EFI_PHYSICAL_ADDRESS FramebufferBase, + IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info + ) +{ + EFI_STATUS Status; + UINTN ConfigureSize; + FRAME_BUFFER_CONFIGURE *Context; + + ConfigureSize = 0; + Status = FrameBufferBltConfigure ( + (VOID *) FramebufferBase, + Info, + NULL, + &ConfigureSize + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + return NULL; + } + + Context = AllocatePool (ConfigureSize); + if (Context == NULL) { + return NULL; + } + + Status = FrameBufferBltConfigure ( + (VOID *) FramebufferBase, + Info, + Context, + &ConfigureSize + ); + if (EFI_ERROR (Status)) { + FreePool (Context); + return NULL; + } + + return Context; +} + +STATIC +EFI_STATUS +EFIAPI +DirectGopSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ) +{ + EFI_STATUS Status; + + Status = This->SetMode (This, ModeNumber); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mFramebufferContext != NULL) { + FreePool (mFramebufferContext); + mFramebufferContext = NULL; + } + + mFramebufferContext = DirectGopFromTarget (This->Mode->FrameBufferBase, This->Mode->Info); + if (mFramebufferContext == NULL) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +DirectGopBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + if (mFramebufferContext != NULL) { + return FrameBufferBlt ( + mFramebufferContext, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + } + + return EFI_DEVICE_ERROR; +} + VOID OcReconnectConsole ( VOID @@ -219,3 +332,38 @@ OcReconnectConsole ( DEBUG ((DEBUG_WARN, "OCC: Failed to find any text output handles\n")); } } + +EFI_STATUS +OcUseDirectGop ( + VOID + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + + DEBUG ((DEBUG_INFO, "OCC: Switching to direct GOP renderer...\n")); + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Gop + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OCC: Cannot find console GOP for direct GOP - %r\n", Status)); + return Status; + } + + mFramebufferContext = DirectGopFromTarget (Gop->Mode->FrameBufferBase, Gop->Mode->Info); + if (mFramebufferContext == NULL) { + DEBUG ((DEBUG_INFO, "OCC: Delaying direct GOP configuration...\n")); + // + // This is possible at the start. + // + } + + mOriginalGopSetMode = Gop->SetMode; + Gop->SetMode = DirectGopSetMode; + Gop->Blt = DirectGopBlt; + return EFI_SUCCESS; +} diff --git a/Library/OcConsoleLib/OcConsoleLib.inf b/Library/OcConsoleLib/OcConsoleLib.inf index 5628d1c8..194bf8f4 100644 --- a/Library/OcConsoleLib/OcConsoleLib.inf +++ b/Library/OcConsoleLib/OcConsoleLib.inf @@ -49,6 +49,7 @@ [Packages] EfiPkg/EfiPkg.dec + MdeModulePkg/MdeModulePkg.dec MdePkg/MdePkg.dec OcSupportPkg/OcSupportPkg.dec @@ -56,5 +57,6 @@ BaseLib BaseMemoryLib DebugLib + FrameBufferBltLib UefiBootServicesTableLib UefiRuntimeServicesTableLib diff --git a/OcSupportPkg.dsc b/OcSupportPkg.dsc index ec8d19ab..703ba713 100644 --- a/OcSupportPkg.dsc +++ b/OcSupportPkg.dsc @@ -33,6 +33,7 @@ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf