X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FConsole%2FConSplitterDxe%2FConSplitter.c;h=6fc0e4796f9c2fa02615e0645af0d69a0a049418;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hp=b33471f92f40da3e623d7318fffa0047703ce321;hpb=f184c104afbf790a323b49d6386f88d892693eba;p=mirror_edk2.git
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
index b33471f92f..6fc0e4796f 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
@@ -16,19 +16,20 @@
never removed. Such design ensures sytem function well during none console
device situation.
-Copyright (c) 2006 - 2010, 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.
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "ConSplitter.h"
+//
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.
+// default not connect
+//
+BOOLEAN mConInIsConnect = FALSE;
+
//
// Text In Splitter Private Data template
//
@@ -60,6 +61,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {
(LIST_ENTRY *) NULL,
(LIST_ENTRY *) NULL
},
+ (EFI_KEY_DATA *) NULL,
+ 0,
+ 0,
+ FALSE,
{
ConSplitterSimplePointerReset,
@@ -169,7 +174,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,
0,
0,
- TRUE,
0,
(TEXT_OUT_AND_GOP_DATA *) NULL,
@@ -225,7 +229,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,
0,
0,
- TRUE,
0,
(TEXT_OUT_AND_GOP_DATA *) NULL,
@@ -295,6 +298,122 @@ EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding =
NULL
};
+/**
+ Key notify for toggle state sync.
+
+ @param KeyData A pointer to a buffer that is filled in with
+ the keystroke information for the key that was
+ pressed.
+
+ @retval EFI_SUCCESS Toggle state sync successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ToggleStateSyncKeyNotify (
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ UINTN Index;
+
+ if (((KeyData->KeyState.KeyToggleState & KEY_STATE_VALID_EXPOSED) == KEY_STATE_VALID_EXPOSED) &&
+ (KeyData->KeyState.KeyToggleState != mConIn.PhysicalKeyToggleState)) {
+ //
+ // There is toggle state change, sync to other console input devices.
+ //
+ for (Index = 0; Index < mConIn.CurrentNumberOfExConsoles; Index++) {
+ mConIn.TextInExList[Index]->SetState (
+ mConIn.TextInExList[Index],
+ &KeyData->KeyState.KeyToggleState
+ );
+ }
+ mConIn.PhysicalKeyToggleState = KeyData->KeyState.KeyToggleState;
+ DEBUG ((EFI_D_INFO, "Current toggle state is 0x%02x\n", mConIn.PhysicalKeyToggleState));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialization for toggle state sync.
+
+ @param Private Text In Splitter pointer.
+
+**/
+VOID
+ToggleStateSyncInitialization (
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private
+ )
+{
+ EFI_KEY_DATA KeyData;
+ VOID *NotifyHandle;
+
+ //
+ // Initialize PhysicalKeyToggleState that will be synced to new console
+ // input device to turn on physical TextInEx partial key report for
+ // toggle state sync.
+ //
+ Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;
+
+ //
+ // Initialize VirtualKeyStateExported to let the virtual TextInEx not report
+ // the partial key even though the physical TextInEx turns on the partial
+ // key report. The virtual TextInEx will report the partial key after it is
+ // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
+ //
+ Private->VirtualKeyStateExported = FALSE;
+
+ //
+ // Register key notify for toggle state sync.
+ //
+ KeyData.Key.ScanCode = SCAN_NULL;
+ KeyData.Key.UnicodeChar = CHAR_NULL;
+ KeyData.KeyState.KeyShiftState = 0;
+ KeyData.KeyState.KeyToggleState = 0;
+ Private->TextInEx.RegisterKeyNotify (
+ &Private->TextInEx,
+ &KeyData,
+ ToggleStateSyncKeyNotify,
+ &NotifyHandle
+ );
+}
+
+/**
+ Reinitialization for toggle state sync.
+
+ @param Private Text In Splitter pointer.
+
+**/
+VOID
+ToggleStateSyncReInitialization (
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private
+ )
+{
+ UINTN Index;
+
+ //
+ // Reinitialize PhysicalKeyToggleState that will be synced to new console
+ // input device to turn on physical TextInEx partial key report for
+ // toggle state sync.
+ //
+ Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;
+
+ //
+ // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report
+ // the partial key even though the physical TextInEx turns on the partial
+ // key report. The virtual TextInEx will report the partial key after it is
+ // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
+ //
+ Private->VirtualKeyStateExported = FALSE;
+
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
+ Private->TextInExList[Index]->SetState (
+ Private->TextInExList[Index],
+ &Private->PhysicalKeyToggleState
+ );
+ }
+}
+
/**
The Entry Point for module ConSplitter. The user code starts with this function.
@@ -379,7 +498,7 @@ ConSplitterDriverEntry(
FeaturePcdGet (PcdConOutUgaSupport));
//
- // The driver creates virtual handles for ConIn, ConOut.
+ // The driver creates virtual handles for ConIn, ConOut, StdErr.
// The virtual handles will always exist even if no console exist in the
// system. This is need to support hotplug devices like USB.
//
@@ -414,49 +533,12 @@ ConSplitterDriverEntry(
//
Status = ConSplitterTextOutConstructor (&mConOut);
if (!EFI_ERROR (Status)) {
- if (!FeaturePcdGet (PcdConOutGopSupport)) {
- //
- // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed
- // on the virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiSimpleTextOutProtocolGuid,
- &mConOut.TextOut,
- &gEfiUgaDrawProtocolGuid,
- &mConOut.UgaDraw,
- NULL
- );
- } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
- //
- // If UGA Draw protocol not supported, Graphics Output Protocol is installed
- // on virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiSimpleTextOutProtocolGuid,
- &mConOut.TextOut,
- &gEfiGraphicsOutputProtocolGuid,
- &mConOut.GraphicsOutput,
- NULL
- );
- } else {
- //
- // Boot Graphics Output protocol and UGA Draw protocol are supported,
- // both they will be installed on virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiSimpleTextOutProtocolGuid,
- &mConOut.TextOut,
- &gEfiGraphicsOutputProtocolGuid,
- &mConOut.GraphicsOutput,
- &gEfiUgaDrawProtocolGuid,
- &mConOut.UgaDraw,
- NULL
- );
- }
-
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mConOut.VirtualHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &mConOut.TextOut,
+ NULL
+ );
if (!EFI_ERROR (Status)) {
//
// Update the EFI System Table with new virtual console
@@ -467,6 +549,28 @@ ConSplitterDriverEntry(
}
}
+
+ //
+ // Create virtual device handle for StdErr Splitter
+ //
+ Status = ConSplitterTextOutConstructor (&mStdErr);
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mStdErr.VirtualHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &mStdErr.TextOut,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update the EFI System Table with new virtual console
+ // and update the pointer to Text Output protocol.
+ //
+ gST->StandardErrorHandle = mStdErr.VirtualHandle;
+ gST->StdErr = &mStdErr.TextOut;
+ }
+ }
+
//
// Update the CRC32 in the EFI System Table header
//
@@ -498,6 +602,7 @@ ConSplitterTextInConstructor (
)
{
EFI_STATUS Status;
+ UINTN TextInExListCount;
//
// Allocate buffer for Simple Text Input device
@@ -523,6 +628,19 @@ ConSplitterTextInConstructor (
);
ASSERT_EFI_ERROR (Status);
+ //
+ // Allocate buffer for KeyQueue
+ //
+ TextInExListCount = ConInPrivate->TextInExListCount;
+ Status = ConSplitterGrowBuffer (
+ sizeof (EFI_KEY_DATA),
+ &TextInExListCount,
+ (VOID **) &ConInPrivate->KeyQueue
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
//
// Allocate buffer for Simple Text Input Ex device
//
@@ -548,6 +666,8 @@ ConSplitterTextInConstructor (
InitializeListHead (&ConInPrivate->NotifyList);
+ ToggleStateSyncInitialization (ConInPrivate);
+
ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;
//
// Allocate buffer for Absolute Pointer device
@@ -594,6 +714,18 @@ ConSplitterTextInConstructor (
ConInPrivate,
&ConInPrivate->SimplePointer.WaitForInput
);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Create Event to signal ConIn connection request
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ EfiEventEmptyFunction,
+ NULL,
+ &gConnectConInEventGuid,
+ &ConInPrivate->ConnectConInEvent
+ );
return Status;
}
@@ -1277,7 +1409,7 @@ ConSplitterConOutDriverBindingStart (
FreePool (Info);
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ } else if (UgaDraw != NULL) {
Status = UgaDraw->GetMode (
UgaDraw,
&mConOut.UgaHorizontalResolution,
@@ -1315,27 +1447,6 @@ ConSplitterStdErrDriverBindingStart (
EFI_STATUS Status;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
- if (mStdErr.CurrentNumberOfConsoles == 0) {
- //
- // Construct console output devices' private data
- //
- Status = ConSplitterTextOutConstructor (&mStdErr);
- if (!EFI_ERROR (Status)) {
- //
- // Create virtual device handle for StdErr Splitter
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mStdErr.VirtualHandle,
- &gEfiSimpleTextOutProtocolGuid,
- &mStdErr.TextOut,
- NULL
- );
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
//
// Start ConSplitter on ControllerHandle, and create the virtual
// agrogated console device on first call Start for a StandardError handle.
@@ -1364,23 +1475,6 @@ ConSplitterStdErrDriverBindingStart (
//
Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (mStdErr.CurrentNumberOfConsoles == 1) {
- gST->StandardErrorHandle = mStdErr.VirtualHandle;
- gST->StdErr = &mStdErr.TextOut;
- //
- // Update the CRC32 in the EFI System Table header
- //
- gST->Hdr.CRC32 = 0;
- gBS->CalculateCrc32 (
- (UINT8 *) &gST->Hdr,
- gST->Hdr.HeaderSize,
- &gST->Hdr.CRC32
- );
- }
return Status;
}
@@ -1718,48 +1812,17 @@ ConSplitterStdErrDriverBindingStop (
//
// Delete this console error out device's data structures.
//
- Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (mStdErr.CurrentNumberOfConsoles == 0) {
- mStdErr.VirtualHandle = NULL;
-
- gST->StandardErrorHandle = NULL;
- gST->StdErr = NULL;
- //
- // Update the CRC32 in the EFI System Table header
- //
- gST->Hdr.CRC32 = 0;
- gBS->CalculateCrc32 (
- (UINT8 *) &gST->Hdr,
- gST->Hdr.HeaderSize,
- &gST->Hdr.CRC32
- );
-
- //
- // Uninstall Simple Text Output protocol from StdErr Handle.
- //
- gBS->UninstallMultipleProtocolInterfaces (
- mStdErr.VirtualHandle,
- &gEfiSimpleTextOutProtocolGuid,
- &mStdErr.TextOut,
- NULL
- );
- }
-
- return Status;
+ return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
}
/**
- Take the passed in Buffer of size SizeOfCount and grow the buffer
- by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
- bytes. Copy the current data in Buffer to the new version of Buffer
- and free the old version of buffer.
+ Take the passed in Buffer of size ElementSize and grow the buffer
+ by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.
+ Copy the current data in Buffer to the new version of Buffer and
+ free the old version of buffer.
- @param SizeOfCount Size of element in array.
+ @param ElementSize Size of element in array.
@param Count Current number of elements in array.
@param Buffer Bigger version of passed in Buffer with all the
data.
@@ -1770,7 +1833,7 @@ ConSplitterStdErrDriverBindingStop (
**/
EFI_STATUS
ConSplitterGrowBuffer (
- IN UINTN SizeOfCount,
+ IN UINTN ElementSize,
IN OUT UINTN *Count,
IN OUT VOID **Buffer
)
@@ -1782,15 +1845,15 @@ ConSplitterGrowBuffer (
// copy the old buffer's content to the new-size buffer,
// then free the old buffer.
//
- *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;
Ptr = ReallocatePool (
- SizeOfCount * ((*Count) - CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT),
- SizeOfCount * (*Count),
+ ElementSize * (*Count),
+ ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT),
*Buffer
);
if (Ptr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+ *Count += CONSOLE_SPLITTER_ALLOC_UNIT;
*Buffer = Ptr;
return EFI_SUCCESS;
}
@@ -1865,7 +1928,7 @@ ConSplitterTextInDeleteDevice (
//
for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
if (Private->TextInList[Index] == TextIn) {
- for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {
+ for (; Index < Private->CurrentNumberOfConsoles - 1; Index++) {
Private->TextInList[Index] = Private->TextInList[Index + 1];
}
@@ -1893,12 +1956,39 @@ ConSplitterTextInExAddDevice (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
+ UINTN TextInExListCount;
//
- // If the Text Input Ex List is full, enlarge it by calling ConSplitterGrowBuffer().
+ // Enlarge the NotifyHandleList and the TextInExList
//
if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
+ TextInExListCount = Private->TextInExListCount;
+
+ Status = ConSplitterGrowBuffer (
+ sizeof (EFI_HANDLE),
+ &TextInExListCount,
+ (VOID **) &CurrentNotify->NotifyHandleList
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ TextInExListCount = Private->TextInExListCount;
+ Status = ConSplitterGrowBuffer (
+ sizeof (EFI_KEY_DATA),
+ &TextInExListCount,
+ (VOID **) &Private->KeyQueue
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
Status = ConSplitterGrowBuffer (
sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),
&Private->TextInExListCount,
@@ -1908,12 +1998,41 @@ ConSplitterTextInExAddDevice (
return EFI_OUT_OF_RESOURCES;
}
}
+
+ //
+ // Register the key notify in the new text-in device
+ //
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
+ Status = TextInEx->RegisterKeyNotify (
+ TextInEx,
+ &CurrentNotify->KeyData,
+ CurrentNotify->KeyNotificationFn,
+ &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
+ );
+ if (EFI_ERROR (Status)) {
+ for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) {
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
+ TextInEx->UnregisterKeyNotify (
+ TextInEx,
+ CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
+ );
+ }
+ return Status;
+ }
+ }
+
//
// Add the new text-in device data structure into the Text Input Ex List.
//
Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;
Private->CurrentNumberOfExConsoles++;
+ //
+ // Sync current toggle state to this new console input device.
+ //
+ TextInEx->SetState (TextInEx, &Private->PhysicalKeyToggleState);
+
//
// Extra CheckEvent added to reduce the double CheckEvent().
//
@@ -1945,7 +2064,7 @@ ConSplitterTextInExDeleteDevice (
//
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
if (Private->TextInExList[Index] == TextInEx) {
- for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {
+ for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {
Private->TextInExList[Index] = Private->TextInExList[Index + 1];
}
@@ -2022,7 +2141,7 @@ ConSplitterSimplePointerDeleteDevice (
//
for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
if (Private->PointerList[Index] == SimplePointer) {
- for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {
+ for (; Index < Private->CurrentNumberOfPointers - 1; Index++) {
Private->PointerList[Index] = Private->PointerList[Index + 1];
}
@@ -2099,7 +2218,7 @@ ConSplitterAbsolutePointerDeleteDevice (
//
for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
if (Private->AbsolutePointerList[Index] == AbsolutePointer) {
- for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {
+ for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {
Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];
}
@@ -2134,6 +2253,8 @@ ConSplitterGrowMapTable (
INT32 *OldTextOutModeMap;
INT32 *SrcAddress;
INT32 Index;
+ UINTN OldStepSize;
+ UINTN NewStepSize;
NewSize = Private->TextOutListCount * sizeof (INT32);
OldTextOutModeMap = Private->TextOutModeMap;
@@ -2171,14 +2292,26 @@ ConSplitterGrowMapTable (
Size = Private->CurrentNumberOfConsoles * sizeof (INT32);
Index = 0;
SrcAddress = OldTextOutModeMap;
+ NewStepSize = NewSize / sizeof(INT32);
+ // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap
+ // is not NULL, it indicates that the original TextOutModeMap is not enough
+ // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns.
+ //
+ OldStepSize = NewStepSize - CONSOLE_SPLITTER_ALLOC_UNIT;
//
// Copy the old data to the new one
//
while (Index < Private->TextOutMode.MaxMode) {
CopyMem (TextOutModeMap, SrcAddress, Size);
- TextOutModeMap += NewSize;
- SrcAddress += Size;
+ //
+ // Go to next row of new TextOutModeMap.
+ //
+ TextOutModeMap += NewStepSize;
+ //
+ // Go to next row of old TextOutModeMap.
+ //
+ SrcAddress += OldStepSize;
Index++;
}
//
@@ -2526,7 +2659,7 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
//
// Find the intersection of the two set of modes. If they actually intersect, the
- // correponding entry in the map table is set to 1.
+ // corresponding entry in the map table is set to 1.
//
Mode = 0;
while (Mode < ConOutMaxMode) {
@@ -2786,7 +2919,7 @@ ConSplitterAddGraphicsOutputMode (
}
}
}
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ } else if (UgaDraw != NULL) {
//
// Graphics console driver can ensure the same mode for all GOP devices
// so we can get the current mode from this video device
@@ -2826,16 +2959,14 @@ Done:
if (GraphicsOutput != NULL) {
Private->CurrentNumberOfGraphicsOutput++;
}
- if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ if (UgaDraw != NULL) {
Private->CurrentNumberOfUgaDraw++;
}
//
// Force GraphicsOutput mode to be set,
- // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
//
- Private->HardwareNeedsStarting = TRUE;
-
+
Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];
if ((GraphicsOutput != NULL) &&
(Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&
@@ -2905,6 +3036,7 @@ ConsplitterSetConsoleOutMode (
UINTN MaxMode;
EFI_STATUS Status;
CONSOLE_OUT_MODE ModeInfo;
+ CONSOLE_OUT_MODE MaxModeInfo;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
PreferMode = 0xFF;
@@ -2912,8 +3044,10 @@ ConsplitterSetConsoleOutMode (
TextOut = &Private->TextOut;
MaxMode = (UINTN) (TextOut->Mode->MaxMode);
- ModeInfo.Column = PcdGet32 (PcdConOutColumn);
- ModeInfo.Row = PcdGet32 (PcdConOutRow);
+ MaxModeInfo.Column = 0;
+ MaxModeInfo.Row = 0;
+ ModeInfo.Column = PcdGet32 (PcdConOutColumn);
+ ModeInfo.Row = PcdGet32 (PcdConOutRow);
//
// To find the prefer mode and basic mode from Text Out mode list
@@ -2921,8 +3055,23 @@ ConsplitterSetConsoleOutMode (
for (Mode = 0; Mode < MaxMode; Mode++) {
Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);
if (!EFI_ERROR(Status)) {
- if (Col == ModeInfo.Column && Row == ModeInfo.Row) {
- PreferMode = Mode;
+ if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {
+ //
+ // Use user defined column and row
+ //
+ if (Col == ModeInfo.Column && Row == ModeInfo.Row) {
+ PreferMode = Mode;
+ }
+ } else {
+ //
+ // If user sets PcdConOutColumn or PcdConOutRow to 0,
+ // find and set the highest text mode.
+ //
+ if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {
+ MaxModeInfo.Column = Col;
+ MaxModeInfo.Row = Row;
+ PreferMode = Mode;
+ }
}
if (Col == 80 && Row == 25) {
BaseMode = Mode;
@@ -2941,8 +3090,10 @@ ConsplitterSetConsoleOutMode (
Status = TextOut->SetMode (TextOut, BaseMode);
ASSERT(!EFI_ERROR(Status));
- PcdSet32 (PcdConOutColumn, 80);
- PcdSet32 (PcdConOutRow, 25);
+ Status = PcdSet32S (PcdConOutColumn, 80);
+ ASSERT(!EFI_ERROR(Status));
+ Status = PcdSet32S (PcdConOutRow, 25);
+ ASSERT(!EFI_ERROR(Status));
}
return ;
@@ -3033,13 +3184,13 @@ ConSplitterTextOutAddDevice (
ASSERT (MaxMode >= 1);
DeviceStatus = EFI_DEVICE_ERROR;
- if (FeaturePcdGet (PcdConOutGopSupport)) {
- //
- // If GOP is produced by Consplitter, this device display mode will be added into Graphics Ouput modes.
- //
- if ((GraphicsOutput != NULL) || (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport))) {
- DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
- }
+ Status = EFI_DEVICE_ERROR;
+
+ //
+ // This device display mode will be added into Graphics Ouput modes.
+ //
+ if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {
+ DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
}
if (FeaturePcdGet (PcdConOutUgaSupport)) {
@@ -3058,7 +3209,7 @@ ConSplitterTextOutAddDevice (
FreePool (Info);
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ } else if (UgaDraw != NULL) {
Status = UgaDraw->GetMode (
UgaDraw,
&UgaHorizontalResolution,
@@ -3093,6 +3244,46 @@ ConSplitterTextOutAddDevice (
}
}
+ if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) &&
+ ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1)) {
+ if (!FeaturePcdGet (PcdConOutGopSupport)) {
+ //
+ // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed
+ // on the virtual handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mConOut.VirtualHandle,
+ &gEfiUgaDrawProtocolGuid,
+ &mConOut.UgaDraw,
+ NULL
+ );
+ } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
+ //
+ // If UGA Draw protocol not supported, Graphics Output Protocol is installed
+ // on virtual handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mConOut.VirtualHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &mConOut.GraphicsOutput,
+ NULL
+ );
+ } else {
+ //
+ // Boot Graphics Output protocol and UGA Draw protocol are supported,
+ // both they will be installed on virtual handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mConOut.VirtualHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &mConOut.GraphicsOutput,
+ &gEfiUgaDrawProtocolGuid,
+ &mConOut.UgaDraw,
+ NULL
+ );
+ }
+ }
+
//
// After adding new console device, all existing console devices should be
// synced to the current shared mode.
@@ -3133,14 +3324,14 @@ ConSplitterTextOutDeleteDevice (
TextOutList = Private->TextOutList;
while (Index >= 0) {
if (TextOutList->TextOut == TextOut) {
- CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
- CurrentNumOfConsoles--;
- if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ if (TextOutList->UgaDraw != NULL) {
Private->CurrentNumberOfUgaDraw--;
}
if (TextOutList->GraphicsOutput != NULL) {
Private->CurrentNumberOfGraphicsOutput--;
}
+ CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
+ CurrentNumOfConsoles--;
break;
}
@@ -3154,6 +3345,35 @@ ConSplitterTextOutDeleteDevice (
return EFI_NOT_FOUND;
}
+ if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) {
+ //
+ // If there is not any physical GOP and UGA device in system,
+ // Consplitter GOP or UGA protocol will be uninstalled
+ //
+ if (!FeaturePcdGet (PcdConOutGopSupport)) {
+ Status = gBS->UninstallProtocolInterface (
+ Private->VirtualHandle,
+ &gEfiUgaDrawProtocolGuid,
+ &Private->UgaDraw
+ );
+ } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
+ Status = gBS->UninstallProtocolInterface (
+ Private->VirtualHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Private->GraphicsOutput
+ );
+ } else {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Private->VirtualHandle,
+ &gEfiUgaDrawProtocolGuid,
+ &Private->UgaDraw,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Private->GraphicsOutput,
+ NULL
+ );
+ }
+ }
+
if (CurrentNumOfConsoles == 0) {
//
// If the number of consoles is zero, reset all parameters
@@ -3244,9 +3464,48 @@ ConSplitterTextInReset (
}
}
+ if (!EFI_ERROR (ReturnStatus)) {
+ ToggleStateSyncReInitialization (Private);
+ //
+ // Empty the key queue.
+ //
+ Private->CurrentNumberOfKeys = 0;
+ }
+
return ReturnStatus;
}
+/**
+ Dequeue the saved key from internal key queue.
+
+ @param Private Protocol instance pointer.
+ @param KeyData A pointer to a buffer that is filled in with the
+ keystroke state data for the key that was
+ pressed.
+ @retval EFI_NOT_FOUND Queue is empty.
+ @retval EFI_SUCCESS First key is dequeued and returned.
+**/
+EFI_STATUS
+ConSplitterTextInExDequeueKey (
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
+ OUT EFI_KEY_DATA *KeyData
+ )
+{
+ if (Private->CurrentNumberOfKeys == 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Return the first saved key.
+ //
+ CopyMem (KeyData, &Private->KeyQueue[0], sizeof (EFI_KEY_DATA));
+ Private->CurrentNumberOfKeys--;
+ CopyMem (
+ &Private->KeyQueue[0],
+ &Private->KeyQueue[1],
+ Private->CurrentNumberOfKeys * sizeof (EFI_KEY_DATA)
+ );
+ return EFI_SUCCESS;
+}
/**
Reads the next keystroke from the input device. The WaitForKey Event can
@@ -3270,7 +3529,21 @@ ConSplitterTextInPrivateReadKeyStroke (
{
EFI_STATUS Status;
UINTN Index;
- EFI_INPUT_KEY CurrentKey;
+ EFI_KEY_DATA KeyData;
+
+ //
+ // Return the first saved non-NULL key.
+ //
+ while (TRUE) {
+ Status = ConSplitterTextInExDequeueKey (Private, &KeyData);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
+ return Status;
+ }
+ }
Key->UnicodeChar = 0;
Key->ScanCode = SCAN_NULL;
@@ -3280,14 +3553,25 @@ ConSplitterTextInPrivateReadKeyStroke (
// if any physical console input device has key input,
// return the key and EFI_SUCCESS.
//
- for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
+ for (Index = 0; Index < Private->CurrentNumberOfConsoles;) {
Status = Private->TextInList[Index]->ReadKeyStroke (
Private->TextInList[Index],
- &CurrentKey
+ &KeyData.Key
);
if (!EFI_ERROR (Status)) {
- *Key = CurrentKey;
- return Status;
+ //
+ // If it is not partial keystorke, return the key. Otherwise, continue
+ // to read key from THIS physical console input device.
+ //
+ if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
+ return Status;
+ }
+ } else {
+ //
+ // Continue to read key from NEXT physical console input device.
+ //
+ Index++;
}
}
@@ -3295,6 +3579,7 @@ ConSplitterTextInPrivateReadKeyStroke (
}
+
/**
Reads the next keystroke from the input device. The WaitForKey Event can
be used to test for existance of a keystroke via WaitForEvent () call.
@@ -3321,6 +3606,15 @@ ConSplitterTextInReadKeyStroke (
Private->KeyEventSignalState = FALSE;
+ //
+ // Signal ConnectConIn event on first call in Lazy ConIn mode
+ //
+ if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
+ DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
+ gBS->SignalEvent (Private->ConnectConInEvent);
+ mConInIsConnect = TRUE;
+ }
+
return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
}
@@ -3455,6 +3749,14 @@ ConSplitterTextInResetEx (
}
}
+ if (!EFI_ERROR (ReturnStatus)) {
+ ToggleStateSyncReInitialization (Private);
+ //
+ // Empty the key queue.
+ //
+ Private->CurrentNumberOfKeys = 0;
+ }
+
return ReturnStatus;
}
@@ -3486,6 +3788,7 @@ ConSplitterTextInReadKeyStrokeEx (
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
EFI_STATUS Status;
UINTN Index;
+ EFI_KEY_STATE KeyState;
EFI_KEY_DATA CurrentKeyData;
@@ -3497,25 +3800,91 @@ ConSplitterTextInReadKeyStrokeEx (
Private->KeyEventSignalState = FALSE;
- KeyData->Key.UnicodeChar = 0;
- KeyData->Key.ScanCode = SCAN_NULL;
+ //
+ // Signal ConnectConIn event on first call in Lazy ConIn mode
+ //
+ if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
+ DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
+ gBS->SignalEvent (Private->ConnectConInEvent);
+ mConInIsConnect = TRUE;
+ }
//
- // if no physical console input device exists, return EFI_NOT_READY;
- // if any physical console input device has key input,
- // return the key and EFI_SUCCESS.
+ // Return the first saved key.
+ //
+ Status = ConSplitterTextInExDequeueKey (Private, KeyData);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ ASSERT (Private->CurrentNumberOfKeys == 0);
+
+ ZeroMem (&KeyState, sizeof (KeyState));
+
+ //
+ // Iterate through all physical consoles to get key state.
+ // Some physical consoles may return valid key.
+ // Queue the valid keys.
//
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
+ ZeroMem (&CurrentKeyData, sizeof (EFI_KEY_DATA));
Status = Private->TextInExList[Index]->ReadKeyStrokeEx (
- Private->TextInExList[Index],
- &CurrentKeyData
- );
+ Private->TextInExList[Index],
+ &CurrentKeyData
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+ continue;
+ }
+
+ //
+ // Consolidate the key state from all physical consoles.
+ //
+ if ((CurrentKeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) {
+ KeyState.KeyShiftState |= CurrentKeyData.KeyState.KeyShiftState;
+ }
+ if ((CurrentKeyData.KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != 0) {
+ KeyState.KeyToggleState |= CurrentKeyData.KeyState.KeyToggleState;
+ }
+
if (!EFI_ERROR (Status)) {
- CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));
- return Status;
+ //
+ // If virtual KeyState has been required to be exposed, or it is not
+ // partial keystorke, queue the key.
+ // It's possible that user presses at multiple keyboards at the same moment,
+ // Private->KeyQueue[] are the storage to save all the keys.
+ //
+ if ((Private->VirtualKeyStateExported) ||
+ (CurrentKeyData.Key.ScanCode != CHAR_NULL) ||
+ (CurrentKeyData.Key.UnicodeChar != SCAN_NULL)) {
+ CopyMem (
+ &Private->KeyQueue[Private->CurrentNumberOfKeys],
+ &CurrentKeyData,
+ sizeof (EFI_KEY_DATA)
+ );
+ Private->CurrentNumberOfKeys++;
+ }
}
}
+ //
+ // Consolidate the key state for all keys in Private->KeyQueue[]
+ //
+ for (Index = 0; Index < Private->CurrentNumberOfKeys; Index++) {
+ CopyMem (&Private->KeyQueue[Index].KeyState, &KeyState, sizeof (EFI_KEY_STATE));
+ }
+
+ //
+ // Return the first saved key.
+ //
+ Status = ConSplitterTextInExDequeueKey (Private, KeyData);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Always return the key state even there is no key pressed.
+ //
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
+ CopyMem (&KeyData->KeyState, &KeyState, sizeof (KeyData->KeyState));
return EFI_NOT_READY;
}
@@ -3545,6 +3914,7 @@ ConSplitterTextInSetState (
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
EFI_STATUS Status;
UINTN Index;
+ EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState;
if (KeyToggleState == NULL) {
return EFI_INVALID_PARAMETER;
@@ -3552,6 +3922,12 @@ ConSplitterTextInSetState (
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
+ //
+ // Always turn on physical TextInEx partial key report for
+ // toggle state sync.
+ //
+ PhysicalKeyToggleState = *KeyToggleState | EFI_KEY_STATE_EXPOSED;
+
//
// if no physical console input device exists, return EFI_SUCCESS;
// otherwise return the status of setting state of physical console input device
@@ -3559,13 +3935,22 @@ ConSplitterTextInSetState (
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
Status = Private->TextInExList[Index]->SetState (
Private->TextInExList[Index],
- KeyToggleState
+ &PhysicalKeyToggleState
);
if (EFI_ERROR (Status)) {
return Status;
}
}
+ //
+ // Record the physical KeyToggleState.
+ //
+ Private->PhysicalKeyToggleState = PhysicalKeyToggleState;
+ //
+ // Get if virtual KeyState has been required to be exposed.
+ //
+ Private->VirtualKeyStateExported = (((*KeyToggleState) & EFI_KEY_STATE_EXPOSED) != 0);
+
return EFI_SUCCESS;
}
@@ -3575,11 +3960,14 @@ ConSplitterTextInSetState (
Register a notification function for a particular keystroke for the input device.
@param This Protocol instance pointer.
- @param KeyData A pointer to a buffer that is filled in with the
- keystroke information data for the key that was
- pressed.
+ @param KeyData A pointer to a buffer that is filled in with
+ the keystroke information for the key that was
+ pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
+ and KeyData.KeyState.KeyShiftState are 0, then any incomplete
+ keystroke will trigger a notification of the KeyNotificationFunction.
@param KeyNotificationFunction Points to the function to be called when the key
- sequence is typed specified by KeyData.
+ sequence is typed specified by KeyData. This notification function
+ should be called at <=TPL_CALLBACK.
@param NotifyHandle Points to the unique handle assigned to the
registered notification.
@@ -3596,7 +3984,7 @@ ConSplitterTextInRegisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_DATA *KeyData,
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
- OUT EFI_HANDLE *NotifyHandle
+ OUT VOID **NotifyHandle
)
{
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
@@ -3613,14 +4001,6 @@ ConSplitterTextInRegisterKeyNotify (
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
- //
- // If no physical console input device exists,
- // return EFI_SUCCESS directly.
- //
- if (Private->CurrentNumberOfExConsoles <= 0) {
- return EFI_SUCCESS;
- }
-
//
// Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
//
@@ -3628,7 +4008,7 @@ ConSplitterTextInRegisterKeyNotify (
CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
- *NotifyHandle = CurrentNotify->NotifyHandle;
+ *NotifyHandle = CurrentNotify;
return EFI_SUCCESS;
}
}
@@ -3641,15 +4021,14 @@ ConSplitterTextInRegisterKeyNotify (
if (NewNotify == NULL) {
return EFI_OUT_OF_RESOURCES;
}
- NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);
+ NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount);
if (NewNotify->NotifyHandleList == NULL) {
gBS->FreePool (NewNotify);
return EFI_OUT_OF_RESOURCES;
}
NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;
NewNotify->KeyNotificationFn = KeyNotificationFunction;
- NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;
- CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
//
// Return the wrong status of registering key notify of
@@ -3663,15 +4042,24 @@ ConSplitterTextInRegisterKeyNotify (
&NewNotify->NotifyHandleList[Index]
);
if (EFI_ERROR (Status)) {
+ //
+ // Un-register the key notify on all physical console input devices
+ //
+ while (Index-- != 0) {
+ Private->TextInExList[Index]->UnregisterKeyNotify (
+ Private->TextInExList[Index],
+ NewNotify->NotifyHandleList[Index]
+ );
+ }
gBS->FreePool (NewNotify->NotifyHandleList);
gBS->FreePool (NewNotify);
return Status;
}
}
- InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);
+ InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);
- *NotifyHandle = NewNotify->NotifyHandle;
+ *NotifyHandle = NewNotify;
return EFI_SUCCESS;
@@ -3694,11 +4082,10 @@ EFI_STATUS
EFIAPI
ConSplitterTextInUnregisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN EFI_HANDLE NotificationHandle
+ IN VOID *NotificationHandle
)
{
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
- EFI_STATUS Status;
UINTN Index;
TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
LIST_ENTRY *Link;
@@ -3707,31 +4094,16 @@ ConSplitterTextInUnregisterKeyNotify (
return EFI_INVALID_PARAMETER;
}
- if (((TEXT_IN_EX_SPLITTER_NOTIFY *) NotificationHandle)->Signature != TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
- //
- // if no physical console input device exists,
- // return EFI_SUCCESS directly.
- //
- if (Private->CurrentNumberOfExConsoles <= 0) {
- return EFI_SUCCESS;
- }
-
for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
- if (CurrentNotify->NotifyHandle == NotificationHandle) {
+ if (CurrentNotify == NotificationHandle) {
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
- Status = Private->TextInExList[Index]->UnregisterKeyNotify (
- Private->TextInExList[Index],
- CurrentNotify->NotifyHandleList[Index]
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ Private->TextInExList[Index]->UnregisterKeyNotify (
+ Private->TextInExList[Index],
+ CurrentNotify->NotifyHandleList[Index]
+ );
}
RemoveEntryList (&CurrentNotify->NotifyEntry);
@@ -4017,7 +4389,18 @@ ConSplitterAbsolutePointerGetState (
EFI_STATUS ReturnStatus;
UINTN Index;
EFI_ABSOLUTE_POINTER_STATE CurrentState;
-
+ UINT64 MinX;
+ UINT64 MinY;
+ UINT64 MinZ;
+ UINT64 MaxX;
+ UINT64 MaxY;
+ UINT64 MaxZ;
+ UINT64 VirtualMinX;
+ UINT64 VirtualMinY;
+ UINT64 VirtualMinZ;
+ UINT64 VirtualMaxX;
+ UINT64 VirtualMaxY;
+ UINT64 VirtualMaxZ;
Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
@@ -4028,6 +4411,13 @@ ConSplitterAbsolutePointerGetState (
State->CurrentZ = 0;
State->ActiveButtons = 0;
+ VirtualMinX = Private->AbsolutePointerMode.AbsoluteMinX;
+ VirtualMinY = Private->AbsolutePointerMode.AbsoluteMinY;
+ VirtualMinZ = Private->AbsolutePointerMode.AbsoluteMinZ;
+ VirtualMaxX = Private->AbsolutePointerMode.AbsoluteMaxX;
+ VirtualMaxY = Private->AbsolutePointerMode.AbsoluteMaxY;
+ VirtualMaxZ = Private->AbsolutePointerMode.AbsoluteMaxZ;
+
//
// if no physical pointer device exists, return EFI_NOT_READY;
// if any physical pointer device has changed state,
@@ -4045,16 +4435,47 @@ ConSplitterAbsolutePointerGetState (
ReturnStatus = EFI_SUCCESS;
}
+ MinX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinX;
+ MinY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinY;
+ MinZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinZ;
+ MaxX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxX;
+ MaxY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxY;
+ MaxZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxZ;
+
State->ActiveButtons = CurrentState.ActiveButtons;
- if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {
- State->CurrentX = CurrentState.CurrentX;
+ //
+ // Rescale to Con Splitter virtual Absolute Pointer's resolution.
+ //
+ if (!(MinX == 0 && MaxX == 0)) {
+ State->CurrentX = VirtualMinX + DivU64x64Remainder (
+ MultU64x64 (
+ CurrentState.CurrentX,
+ VirtualMaxX - VirtualMinX
+ ),
+ MaxX - MinX,
+ NULL
+ );
}
- if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {
- State->CurrentY = CurrentState.CurrentY;
+ if (!(MinY == 0 && MaxY == 0)) {
+ State->CurrentY = VirtualMinY + DivU64x64Remainder (
+ MultU64x64 (
+ CurrentState.CurrentY,
+ VirtualMaxY - VirtualMinY
+ ),
+ MaxY - MinY,
+ NULL
+ );
}
- if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {
- State->CurrentZ = CurrentState.CurrentZ;
+ if (!(MinZ == 0 && MaxZ == 0)) {
+ State->CurrentZ = VirtualMinZ + DivU64x64Remainder (
+ MultU64x64 (
+ CurrentState.CurrentZ,
+ VirtualMaxZ - VirtualMinZ
+ ),
+ MaxZ - MinZ,
+ NULL
+ );
}
} else if (Status == EFI_DEVICE_ERROR) {
@@ -4189,37 +4610,21 @@ ConSplitterTextOutOutputString (
EFI_STATUS Status;
TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
UINTN Index;
- UINTN BackSpaceCount;
EFI_STATUS ReturnStatus;
- CHAR16 *TargetString;
+ UINTN MaxColumn;
+ UINTN MaxRow;
This->SetAttribute (This, This->Mode->Attribute);
Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
- BackSpaceCount = 0;
-
- for (TargetString = WString; *TargetString != L'\0'; TargetString++) {
- if (*TargetString == CHAR_BACKSPACE) {
- BackSpaceCount++;
- }
- }
-
- if (BackSpaceCount == 0) {
- TargetString = WString;
- } else {
- TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));
- ASSERT (TargetString != NULL);
-
- StrCpy (TargetString, WString);
- }
//
// return the worst status met
//
for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
Status = Private->TextOutList[Index].TextOut->OutputString (
Private->TextOutList[Index].TextOut,
- TargetString
+ WString
);
if (EFI_ERROR (Status)) {
ReturnStatus = Status;
@@ -4229,10 +4634,50 @@ ConSplitterTextOutOutputString (
if (Private->CurrentNumberOfConsoles > 0) {
Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;
Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;
- }
+ } else {
+ //
+ // When there is no real console devices in system,
+ // update cursor position for the virtual device in consplitter.
+ //
+ Private->TextOut.QueryMode (
+ &Private->TextOut,
+ Private->TextOutMode.Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ for (; *WString != CHAR_NULL; WString++) {
+ switch (*WString) {
+ case CHAR_BACKSPACE:
+ if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {
+ Private->TextOutMode.CursorRow--;
+ Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);
+ } else if (Private->TextOutMode.CursorColumn > 0) {
+ Private->TextOutMode.CursorColumn--;
+ }
+ break;
+
+ case CHAR_LINEFEED:
+ if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
+ Private->TextOutMode.CursorRow++;
+ }
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ Private->TextOutMode.CursorColumn = 0;
+ break;
- if (BackSpaceCount > 0) {
- FreePool (TargetString);
+ default:
+ if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {
+ Private->TextOutMode.CursorColumn++;
+ } else {
+ Private->TextOutMode.CursorColumn = 0;
+ if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
+ Private->TextOutMode.CursorRow++;
+ }
+ }
+ break;
+ }
+ }
}
return ReturnStatus;
@@ -4456,7 +4901,7 @@ ConSplitterTextOutSetAttribute (
//
// Check whether param Attribute is valid.
//
- if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {
+ if ((Attribute | 0x7F) != 0x7F) {
return EFI_UNSUPPORTED;
}
@@ -4655,4 +5100,3 @@ ConSplitterTextOutEnableCursor (
return ReturnStatus;
}
-