提交 159a06d6 编写于 作者: V vit9696

OcConsoleLib: Split ConsoleControl and ConOut

上级 ffbf9ba7
/** @file
Copyright (C) 2019, vit9696. All rights reserved.
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.
**/
#include <Protocol/ConsoleControl.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextOut.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcConsoleLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcGuardLib.h>
#include <Library/UefiBootServicesTableLib.h>
//
// Current reported console mode.
//
STATIC
EFI_CONSOLE_CONTROL_SCREEN_MODE
mConsoleMode = EfiConsoleControlScreenText;
//
// Stick to previously set console mode.
//
STATIC
BOOLEAN
mForceConsoleMode = FALSE;
//
// Disable text output in graphics mode.
//
STATIC
BOOLEAN
mIgnoreTextInGraphics = FALSE;
//
// Clear screen when switching from graphics mode to text mode.
//
STATIC
BOOLEAN
mClearScreenOnModeSwitch = FALSE;
//
// Replace tab character with a space in output.
//
STATIC
BOOLEAN
mReplaceTabWithSpace = FALSE;
//
// Original text output function.
//
STATIC
EFI_TEXT_STRING
mOriginalOutputString;
//
// Original clear screen function.
//
STATIC
EFI_TEXT_CLEAR_SCREEN
mOriginalClearScreen;
//
// Original console control protocol functions.
//
STATIC
EFI_CONSOLE_CONTROL_PROTOCOL
mOriginalConsoleControlProtocol;
STATIC
EFI_STATUS
EFIAPI
ControlledOutputString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
UINTN Index;
UINTN Length;
CHAR16 *StringCopy;
EFI_STATUS Status;
if (mConsoleMode == EfiConsoleControlScreenText || !mIgnoreTextInGraphics) {
if (mReplaceTabWithSpace) {
Length = StrLen(String);
if (Length == MAX_UINTN) {
return EFI_UNSUPPORTED;
}
StringCopy = AllocatePool ((Length + 1) * sizeof(CHAR16));
if (StringCopy == NULL) {
return mOriginalOutputString (This, String);
}
for (Index = 0; Index < Length; Index++) {
if (String[Index] == '\t') {
StringCopy[Index] = ' ';
}
else {
StringCopy[Index] = String[Index];
}
}
StringCopy[Length] = 0;
Status = mOriginalOutputString (This, StringCopy);
FreePool(StringCopy);
return Status;
}
else {
return mOriginalOutputString (This, String);
}
}
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
ControlledClearScreen (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
UINT32 Width;
UINT32 Height;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &GraphicsOutput
);
if (!EFI_ERROR (Status)) {
Status = GraphicsOutput->QueryMode (
GraphicsOutput,
GraphicsOutput->Mode->Mode,
&SizeOfInfo,
&Info
);
if (!EFI_ERROR (Status)) {
Width = Info->HorizontalResolution;
Height = Info->VerticalResolution;
FreePool (Info);
} else {
GraphicsOutput = NULL;
}
} else {
GraphicsOutput = NULL;
}
//
// On APTIO V with large resolution (e.g. 2K or 4K) ClearScreen
// invocation resets resolution to 1024x768. To avoid the glitches
// we clear the screen manually, doing with other methods results
// in screen flashes and other problems.
//
if (GraphicsOutput != NULL) {
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mGraphicsEfiColors[8] = {
//
// B G R reserved
//
{0x00, 0x00, 0x00, 0x00}, // BLACK
{0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE
{0x00, 0x98, 0x00, 0x00}, // LIGHGREEN
{0x98, 0x98, 0x00, 0x00}, // LIGHCYAN
{0x00, 0x00, 0x98, 0x00}, // LIGHRED
{0x98, 0x00, 0x98, 0x00}, // MAGENTA
{0x00, 0x98, 0x98, 0x00}, // BROWN
{0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
};
Status = GraphicsOutput->Blt (
GraphicsOutput,
&mGraphicsEfiColors[BitFieldRead32 ((UINT32) This->Mode->Attribute, 4, 6)],
EfiBltVideoFill,
0,
0,
0,
0,
Width,
Height,
0
);
This->SetCursorPosition (This, 0, 0);
} else {
Status = mOriginalClearScreen (This);
}
return Status;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlGetMode (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
OUT BOOLEAN *GopUgaExists OPTIONAL,
OUT BOOLEAN *StdInLocked OPTIONAL
)
{
EFI_STATUS Status;
if (mOriginalConsoleControlProtocol.GetMode != NULL && !mForceConsoleMode) {
Status = mOriginalConsoleControlProtocol.GetMode (
This,
Mode,
GopUgaExists,
StdInLocked
);
if (!EFI_ERROR (Status)) {
mConsoleMode = *Mode;
}
return Status;
}
*Mode = mConsoleMode;
if (GopUgaExists) {
*GopUgaExists = TRUE;
}
if (StdInLocked) {
*StdInLocked = FALSE;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlSetMode (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
DEBUG ((DEBUG_INFO, "OCC: Setting cc mode %d -> %d\n", mConsoleMode, Mode));
mConsoleMode = Mode;
if (mClearScreenOnModeSwitch && Mode == EfiConsoleControlScreenText) {
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &GraphicsOutput
);
if (!EFI_ERROR (Status)) {
Background.Red = 0;
Background.Green = 0;
Background.Blue = 0;
Status = GraphicsOutput->Blt (
GraphicsOutput,
&Background,
EfiBltVideoFill,
0,
0,
0,
0,
GraphicsOutput->Mode->Info->HorizontalResolution,
GraphicsOutput->Mode->Info->VerticalResolution,
0
);
}
}
if (mOriginalConsoleControlProtocol.SetMode != NULL && !mForceConsoleMode) {
return mOriginalConsoleControlProtocol.SetMode (
This,
Mode
);
}
//
// Disable and hide flashing cursor when switching to graphics from text.
// This may be the case when we formerly handled text input or output.
// mOriginalOutputString check is here to signalise that the problem only exists
// on platforms that require IgnoreTextOutput quirk, and this is the extension
// of its implementation.
//
if (Mode == EfiConsoleControlScreenGraphics && mOriginalOutputString != NULL) {
OcConsoleDisableCursor ();
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlLockStdIn (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
IN CHAR16 *Password
)
{
if (mOriginalConsoleControlProtocol.LockStdIn != NULL) {
return mOriginalConsoleControlProtocol.LockStdIn (
This,
Password
);
}
return EFI_DEVICE_ERROR;
}
STATIC
EFI_CONSOLE_CONTROL_PROTOCOL
mConsoleControlProtocol = {
ConsoleControlGetMode,
ConsoleControlSetMode,
ConsoleControlLockStdIn
};
/**
Locate Console Control protocol.
@retval Console control protocol instance or NULL.
**/
EFI_CONSOLE_CONTROL_PROTOCOL *
OcConsoleControlInstallProtocol (
IN BOOLEAN Reinstall
)
{
EFI_STATUS Status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
EFI_HANDLE NewHandle;
Status = gBS->LocateProtocol (
&gEfiConsoleControlProtocolGuid,
NULL,
(VOID *) &ConsoleControl
);
DEBUG ((
DEBUG_INFO,
"OCC: Install console control %d - %r\n",
Reinstall,
Status
));
//
// Native implementation exists, overwrite on force.
//
if (!EFI_ERROR (Status)) {
if (Reinstall) {
CopyMem (
&mOriginalConsoleControlProtocol,
ConsoleControl,
sizeof (mOriginalConsoleControlProtocol)
);
CopyMem (
ConsoleControl,
&mConsoleControlProtocol,
sizeof (mOriginalConsoleControlProtocol)
);
}
return ConsoleControl;
}
NewHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&NewHandle,
&gEfiConsoleControlProtocolGuid,
&mConsoleControlProtocol,
NULL
);
return &mConsoleControlProtocol;
}
VOID
OcConsoleControlConfigure (
IN BOOLEAN IgnoreTextOutput,
IN BOOLEAN SanitiseClearScreen,
IN BOOLEAN ClearScreenOnModeSwitch,
IN BOOLEAN ReplaceTabWithSpace
)
{
DEBUG ((
DEBUG_INFO,
"OCC: Configuring console ignore %d san clear %d clear switch %d replace tab %ds\n",
IgnoreTextOutput,
SanitiseClearScreen,
ClearScreenOnModeSwitch,
ReplaceTabWithSpace
));
mIgnoreTextInGraphics = IgnoreTextOutput;
mClearScreenOnModeSwitch = ClearScreenOnModeSwitch;
mReplaceTabWithSpace = ReplaceTabWithSpace;
if (IgnoreTextOutput || ReplaceTabWithSpace) {
mOriginalOutputString = gST->ConOut->OutputString;
gST->ConOut->OutputString = ControlledOutputString;
}
if (SanitiseClearScreen) {
mOriginalClearScreen = gST->ConOut->ClearScreen;
gST->ConOut->ClearScreen = ControlledClearScreen;
}
}
EFI_STATUS
ConsoleControlSetBehaviourForHandle (
IN EFI_HANDLE Handle,
IN OC_CONSOLE_CONTROL_BEHAVIOUR Behaviour
)
{
EFI_STATUS Status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
DEBUG ((
DEBUG_INFO,
"OCC: Configuring behaviour %u\n",
Behaviour
));
if (Behaviour == OcConsoleControlDefault) {
return EFI_SUCCESS;
}
if (Handle != NULL) {
Status = gBS->HandleProtocol (
Handle,
&gEfiConsoleControlProtocolGuid,
(VOID *) &ConsoleControl
);
} else {
Status = gBS->LocateProtocol (
&gEfiConsoleControlProtocolGuid,
NULL,
(VOID *) &ConsoleControl
);
}
if (EFI_ERROR (Status)) {
return Status;
}
if (Behaviour == OcConsoleControlText) {
return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
}
if (Behaviour == OcConsoleControlGraphics) {
return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
}
//
// We are setting a forced mode, do not let console changes.
//
mForceConsoleMode = TRUE;
if (Behaviour == OcConsoleControlForceText) {
mConsoleMode = EfiConsoleControlScreenText;
} else {
mConsoleMode = EfiConsoleControlScreenGraphics;
}
//
// Ensure that the mode is changed if original protocol is available.
//
if (mOriginalConsoleControlProtocol.SetMode != NULL) {
Status = mOriginalConsoleControlProtocol.SetMode (
ConsoleControl,
mConsoleMode
);
}
return Status;
}
EFI_STATUS
OcConsoleControlSetBehaviour (
IN OC_CONSOLE_CONTROL_BEHAVIOUR Behaviour
)
{
return ConsoleControlSetBehaviourForHandle (NULL, Behaviour);
}
......@@ -12,6 +12,8 @@
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OcConsoleLibInternal.h"
#include <Protocol/ConsoleControl.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextOut.h>
......@@ -25,488 +27,6 @@
#include <Library/OcGuardLib.h>
#include <Library/UefiBootServicesTableLib.h>
//
// Current reported console mode.
//
STATIC
EFI_CONSOLE_CONTROL_SCREEN_MODE
mConsoleMode = EfiConsoleControlScreenText;
//
// Stick to previously set console mode.
//
STATIC
BOOLEAN
mForceConsoleMode = FALSE;
//
// Disable text output in graphics mode.
//
STATIC
BOOLEAN
mIgnoreTextInGraphics = FALSE;
//
// Clear screen when switching from graphics mode to text mode.
//
STATIC
BOOLEAN
mClearScreenOnModeSwitch = FALSE;
//
// Replace tab character with a space in output.
//
STATIC
BOOLEAN
mReplaceTabWithSpace = FALSE;
//
// Original text output function.
//
STATIC
EFI_TEXT_STRING
mOriginalOutputString;
//
// Original clear screen function.
//
STATIC
EFI_TEXT_CLEAR_SCREEN
mOriginalClearScreen;
//
// Original console control protocol functions.
//
STATIC
EFI_CONSOLE_CONTROL_PROTOCOL
mOriginalConsoleControlProtocol;
STATIC
EFI_STATUS
EFIAPI
ControlledOutputString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
UINTN Index;
UINTN Length;
CHAR16 *StringCopy;
EFI_STATUS Status;
if (mConsoleMode == EfiConsoleControlScreenText || !mIgnoreTextInGraphics) {
if (mReplaceTabWithSpace) {
Length = StrLen(String);
if (Length == MAX_UINTN) {
return EFI_UNSUPPORTED;
}
StringCopy = AllocatePool((Length + 1) * sizeof(CHAR16));
if (StringCopy == NULL) {
return mOriginalOutputString (This, String);
}
for (Index = 0; Index < Length; Index++) {
if (String[Index] == '\t') {
StringCopy[Index] = ' ';
}
else {
StringCopy[Index] = String[Index];
}
}
StringCopy[Length] = 0;
Status = mOriginalOutputString (This, StringCopy);
FreePool(StringCopy);
return Status;
}
else {
return mOriginalOutputString (This, String);
}
}
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
EFIAPI
ControlledClearScreen (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
UINT32 Width;
UINT32 Height;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &GraphicsOutput
);
if (!EFI_ERROR (Status)) {
Status = GraphicsOutput->QueryMode (
GraphicsOutput,
GraphicsOutput->Mode->Mode,
&SizeOfInfo,
&Info
);
if (!EFI_ERROR (Status)) {
Width = Info->HorizontalResolution;
Height = Info->VerticalResolution;
FreePool (Info);
} else {
GraphicsOutput = NULL;
}
} else {
GraphicsOutput = NULL;
}
//
// On APTIO V with large resolution (e.g. 2K or 4K) ClearScreen
// invocation resets resolution to 1024x768. To avoid the glitches
// we clear the screen manually, doing with other methods results
// in screen flashes and other problems.
//
if (GraphicsOutput != NULL) {
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mGraphicsEfiColors[8] = {
//
// B G R reserved
//
{0x00, 0x00, 0x00, 0x00}, // BLACK
{0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE
{0x00, 0x98, 0x00, 0x00}, // LIGHGREEN
{0x98, 0x98, 0x00, 0x00}, // LIGHCYAN
{0x00, 0x00, 0x98, 0x00}, // LIGHRED
{0x98, 0x00, 0x98, 0x00}, // MAGENTA
{0x00, 0x98, 0x98, 0x00}, // BROWN
{0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
};
Status = GraphicsOutput->Blt (
GraphicsOutput,
&mGraphicsEfiColors[BitFieldRead32 ((UINT32) This->Mode->Attribute, 4, 6)],
EfiBltVideoFill,
0,
0,
0,
0,
Width,
Height,
0
);
This->SetCursorPosition (This, 0, 0);
} else {
Status = mOriginalClearScreen (This);
}
return Status;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlGetMode (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
OUT BOOLEAN *GopUgaExists OPTIONAL,
OUT BOOLEAN *StdInLocked OPTIONAL
)
{
EFI_STATUS Status;
if (mOriginalConsoleControlProtocol.GetMode != NULL && !mForceConsoleMode) {
Status = mOriginalConsoleControlProtocol.GetMode (
This,
Mode,
GopUgaExists,
StdInLocked
);
if (!EFI_ERROR (Status)) {
mConsoleMode = *Mode;
}
return Status;
}
*Mode = mConsoleMode;
if (GopUgaExists) {
*GopUgaExists = TRUE;
}
if (StdInLocked) {
*StdInLocked = FALSE;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlSetMode (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
DEBUG ((DEBUG_INFO, "OCC: Setting cc mode %d -> %d\n", mConsoleMode, Mode));
mConsoleMode = Mode;
if (mClearScreenOnModeSwitch && Mode == EfiConsoleControlScreenText) {
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &GraphicsOutput
);
if (!EFI_ERROR (Status)) {
Background.Red = 0;
Background.Green = 0;
Background.Blue = 0;
Status = GraphicsOutput->Blt (
GraphicsOutput,
&Background,
EfiBltVideoFill,
0,
0,
0,
0,
GraphicsOutput->Mode->Info->HorizontalResolution,
GraphicsOutput->Mode->Info->VerticalResolution,
0
);
}
}
if (mOriginalConsoleControlProtocol.SetMode != NULL && !mForceConsoleMode) {
return mOriginalConsoleControlProtocol.SetMode (
This,
Mode
);
}
//
// Disable and hide flashing cursor when switching to graphics from text.
// This may be the case when we formerly handled text input or output.
// mOriginalOutputString check is here to signalise that the problem only exists
// on platforms that require IgnoreTextOutput quirk, and this is the extension
// of its implementation.
//
if (Mode == EfiConsoleControlScreenGraphics && mOriginalOutputString != NULL) {
OcConsoleDisableCursor ();
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
ConsoleControlLockStdIn (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
IN CHAR16 *Password
)
{
if (mOriginalConsoleControlProtocol.LockStdIn != NULL) {
return mOriginalConsoleControlProtocol.LockStdIn (
This,
Password
);
}
return EFI_DEVICE_ERROR;
}
STATIC
EFI_CONSOLE_CONTROL_PROTOCOL
mConsoleControlProtocol = {
ConsoleControlGetMode,
ConsoleControlSetMode,
ConsoleControlLockStdIn
};
/**
Locate Console Control protocol.
@retval Console control protocol instance or NULL.
**/
EFI_CONSOLE_CONTROL_PROTOCOL *
OcConsoleControlInstallProtocol (
IN BOOLEAN Reinstall
)
{
EFI_STATUS Status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
EFI_HANDLE NewHandle;
Status = gBS->LocateProtocol (
&gEfiConsoleControlProtocolGuid,
NULL,
(VOID *) &ConsoleControl
);
DEBUG ((
DEBUG_INFO,
"OCC: Install console control %d - %r\n",
Reinstall,
Status
));
//
// Native implementation exists, overwrite on force.
//
if (!EFI_ERROR (Status)) {
if (Reinstall) {
CopyMem (
&mOriginalConsoleControlProtocol,
ConsoleControl,
sizeof (mOriginalConsoleControlProtocol)
);
CopyMem (
ConsoleControl,
&mConsoleControlProtocol,
sizeof (mOriginalConsoleControlProtocol)
);
}
return ConsoleControl;
}
NewHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&NewHandle,
&gEfiConsoleControlProtocolGuid,
&mConsoleControlProtocol,
NULL
);
return &mConsoleControlProtocol;
}
VOID
OcConsoleControlConfigure (
IN BOOLEAN IgnoreTextOutput,
IN BOOLEAN SanitiseClearScreen,
IN BOOLEAN ClearScreenOnModeSwitch,
IN BOOLEAN ReplaceTabWithSpace
)
{
DEBUG ((
DEBUG_INFO,
"OCC: Configuring console ignore %d san clear %d clear switch %d replace tab %ds\n",
IgnoreTextOutput,
SanitiseClearScreen,
ClearScreenOnModeSwitch,
ReplaceTabWithSpace
));
mIgnoreTextInGraphics = IgnoreTextOutput;
mClearScreenOnModeSwitch = ClearScreenOnModeSwitch;
mReplaceTabWithSpace = ReplaceTabWithSpace;
if (IgnoreTextOutput || ReplaceTabWithSpace) {
mOriginalOutputString = gST->ConOut->OutputString;
gST->ConOut->OutputString = ControlledOutputString;
}
if (SanitiseClearScreen) {
mOriginalClearScreen = gST->ConOut->ClearScreen;
gST->ConOut->ClearScreen = ControlledClearScreen;
}
}
STATIC
EFI_STATUS
OcConsoleControlSetBehaviourForHandle (
IN EFI_HANDLE Handle,
IN OC_CONSOLE_CONTROL_BEHAVIOUR Behaviour
)
{
EFI_STATUS Status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
DEBUG ((
DEBUG_INFO,
"OCC: Configuring behaviour %u\n",
Behaviour
));
if (Behaviour == OcConsoleControlDefault) {
return EFI_SUCCESS;
}
if (Handle != NULL) {
Status = gBS->HandleProtocol (
Handle,
&gEfiConsoleControlProtocolGuid,
(VOID *) &ConsoleControl
);
} else {
Status = gBS->LocateProtocol (
&gEfiConsoleControlProtocolGuid,
NULL,
(VOID *) &ConsoleControl
);
}
if (EFI_ERROR (Status)) {
return Status;
}
if (Behaviour == OcConsoleControlText) {
return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
}
if (Behaviour == OcConsoleControlGraphics) {
return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
}
//
// We are setting a forced mode, do not let console changes.
//
mForceConsoleMode = TRUE;
if (Behaviour == OcConsoleControlForceText) {
mConsoleMode = EfiConsoleControlScreenText;
} else {
mConsoleMode = EfiConsoleControlScreenGraphics;
}
//
// Ensure that the mode is changed if original protocol is available.
//
if (mOriginalConsoleControlProtocol.SetMode != NULL) {
Status = mOriginalConsoleControlProtocol.SetMode (
ConsoleControl,
mConsoleMode
);
}
return Status;
}
EFI_STATUS
OcConsoleControlSetBehaviour (
IN OC_CONSOLE_CONTROL_BEHAVIOUR Behaviour
)
{
return OcConsoleControlSetBehaviourForHandle (NULL, Behaviour);
}
VOID
OcConsoleDisableCursor (
VOID
......@@ -518,151 +38,6 @@ OcConsoleDisableCursor (
}
}
/**
Parse resolution string.
@param[in] String Resolution in WxH@Bpp or WxH format.
@param[out] Width Parsed width or 0.
@param[out] Height Parsed height or 0.
@param[out] Bpp Parsed Bpp or 0, optional to force WxH format.
@param[out] Max Set to TRUE when String equals to Max.
**/
STATIC
VOID
ParseResolution (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT UINT32 *Bpp OPTIONAL,
OUT BOOLEAN *Max
)
{
UINT32 TmpWidth;
UINT32 TmpHeight;
*Width = 0;
*Height = 0;
*Max = FALSE;
if (Bpp != NULL) {
*Bpp = 0;
}
if (AsciiStrCmp (String, "Max") == 0) {
*Max = TRUE;
return;
}
if (*String == '\0' || *String < '0' || *String > '9') {
return;
}
TmpWidth = TmpHeight = 0;
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpWidth, 10, *String++ - '0', &TmpWidth)) {
return;
}
}
if (*String++ != 'x' || *String < '0' || *String > '9') {
return;
}
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpHeight, 10, *String++ - '0', &TmpHeight)) {
return;
}
}
if (*String != '\0' && (*String != '@' || Bpp == NULL)) {
return;
}
*Width = TmpWidth;
*Height = TmpHeight;
if (*String == '\0') {
return;
}
TmpWidth = 0;
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpWidth, 10, *String++ - '0', &TmpWidth)) {
return;
}
}
if (*String != '\0') {
return;
}
*Bpp = TmpWidth;
}
VOID
ParseScreenResolution (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT UINT32 *Bpp,
OUT BOOLEAN *Max
)
{
ASSERT (String != NULL);
ASSERT (Width != NULL);
ASSERT (Height != NULL);
ASSERT (Bpp != NULL);
ASSERT (Max != NULL);
ParseResolution (String, Width, Height, Bpp, Max);
}
VOID
ParseConsoleMode (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT BOOLEAN *Max
)
{
ASSERT (String != NULL);
ASSERT (Width != NULL);
ASSERT (Height != NULL);
ASSERT (Max != NULL);
ParseResolution (String, Width, Height, NULL, Max);
}
OC_CONSOLE_CONTROL_BEHAVIOUR
ParseConsoleControlBehaviour (
IN CONST CHAR8 *Behaviour
)
{
if (Behaviour[0] == '\0') {
return OcConsoleControlDefault;
}
if (AsciiStrCmp (Behaviour, "Graphics") == 0) {
return OcConsoleControlGraphics;
}
if (AsciiStrCmp (Behaviour, "Text") == 0) {
return OcConsoleControlText;
}
if (AsciiStrCmp (Behaviour, "ForceGraphics") == 0) {
return OcConsoleControlForceGraphics;
}
if (AsciiStrCmp (Behaviour, "ForceText") == 0) {
return OcConsoleControlForceText;
}
return OcConsoleControlDefault;
}
STATIC
EFI_STATUS
SetConsoleResolutionForProtocol (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
......@@ -833,7 +208,6 @@ SetConsoleResolutionForProtocol (
return Status;
}
STATIC
EFI_STATUS
SetConsoleModeForProtocol (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
......
......@@ -34,8 +34,10 @@
gEfiUgaDrawProtocolGuid
[Sources]
ConsoleControl.c
OcConsoleLib.c
OcConsoleLibInternal.h
ResolutionParsing.c
UgaPassThrough.c
[Packages]
......
......@@ -17,6 +17,7 @@
#include <Library/OcConsoleLib.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextOut.h>
#include <Protocol/UgaDraw.h>
typedef struct {
......@@ -33,6 +34,19 @@ SetConsoleResolutionForProtocol (
IN BOOLEAN Reconnect
);
EFI_STATUS
SetConsoleModeForProtocol (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
IN UINT32 Width,
IN UINT32 Height
);
EFI_STATUS
ConsoleControlSetBehaviourForHandle (
IN EFI_HANDLE Handle,
IN OC_CONSOLE_CONTROL_BEHAVIOUR Behaviour
);
VOID
OcProvideUgaPassThrough (
VOID
......
/** @file
Copyright (C) 2019, vit9696. All rights reserved.
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.
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/OcConsoleLib.h>
#include <Library/OcGuardLib.h>
/**
Parse resolution string.
@param[in] String Resolution in WxH@Bpp or WxH format.
@param[out] Width Parsed width or 0.
@param[out] Height Parsed height or 0.
@param[out] Bpp Parsed Bpp or 0, optional to force WxH format.
@param[out] Max Set to TRUE when String equals to Max.
**/
STATIC
VOID
ParseResolution (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT UINT32 *Bpp OPTIONAL,
OUT BOOLEAN *Max
)
{
UINT32 TmpWidth;
UINT32 TmpHeight;
*Width = 0;
*Height = 0;
*Max = FALSE;
if (Bpp != NULL) {
*Bpp = 0;
}
if (AsciiStrCmp (String, "Max") == 0) {
*Max = TRUE;
return;
}
if (*String == '\0' || *String < '0' || *String > '9') {
return;
}
TmpWidth = TmpHeight = 0;
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpWidth, 10, *String++ - '0', &TmpWidth)) {
return;
}
}
if (*String++ != 'x' || *String < '0' || *String > '9') {
return;
}
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpHeight, 10, *String++ - '0', &TmpHeight)) {
return;
}
}
if (*String != '\0' && (*String != '@' || Bpp == NULL)) {
return;
}
*Width = TmpWidth;
*Height = TmpHeight;
if (*String == '\0') {
return;
}
TmpWidth = 0;
while (*String >= '0' && *String <= '9') {
if (OcOverflowMulAddU32 (TmpWidth, 10, *String++ - '0', &TmpWidth)) {
return;
}
}
if (*String != '\0') {
return;
}
*Bpp = TmpWidth;
}
VOID
ParseScreenResolution (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT UINT32 *Bpp,
OUT BOOLEAN *Max
)
{
ASSERT (String != NULL);
ASSERT (Width != NULL);
ASSERT (Height != NULL);
ASSERT (Bpp != NULL);
ASSERT (Max != NULL);
ParseResolution (String, Width, Height, Bpp, Max);
}
VOID
ParseConsoleMode (
IN CONST CHAR8 *String,
OUT UINT32 *Width,
OUT UINT32 *Height,
OUT BOOLEAN *Max
)
{
ASSERT (String != NULL);
ASSERT (Width != NULL);
ASSERT (Height != NULL);
ASSERT (Max != NULL);
ParseResolution (String, Width, Height, NULL, Max);
}
OC_CONSOLE_CONTROL_BEHAVIOUR
ParseConsoleControlBehaviour (
IN CONST CHAR8 *Behaviour
)
{
if (Behaviour[0] == '\0') {
return OcConsoleControlDefault;
}
if (AsciiStrCmp (Behaviour, "Graphics") == 0) {
return OcConsoleControlGraphics;
}
if (AsciiStrCmp (Behaviour, "Text") == 0) {
return OcConsoleControlText;
}
if (AsciiStrCmp (Behaviour, "ForceGraphics") == 0) {
return OcConsoleControlForceGraphics;
}
if (AsciiStrCmp (Behaviour, "ForceText") == 0) {
return OcConsoleControlForceText;
}
return OcConsoleControlDefault;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册