0,\r
(EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
0,\r
+ {\r
+ ConSplitterTextInResetEx,\r
+ ConSplitterTextInReadKeyStrokeEx,\r
+ (EFI_EVENT) NULL,\r
+ ConSplitterTextInSetState,\r
+ ConSplitterTextInRegisterKeyNotify,\r
+ ConSplitterTextInUnregisterKeyNotify\r
+ },\r
+ 0,\r
+ (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
+ 0,\r
+ {\r
+ (struct _LIST_ENTRY *) NULL,\r
+ (struct _LIST_ENTRY *) NULL\r
+ },\r
\r
{\r
ConSplitterSimplePointerReset,\r
(EFI_SIMPLE_POINTER_PROTOCOL **) NULL,\r
0,\r
\r
+ {\r
+ ConSplitterAbsolutePointerReset,\r
+ ConSplitterAbsolutePointerGetState,\r
+ (EFI_EVENT) NULL,\r
+ (EFI_ABSOLUTE_POINTER_MODE *) NULL\r
+ },\r
+\r
+ {\r
+ 0, //AbsoluteMinX\r
+ 0, //AbsoluteMinY\r
+ 0, //AbsoluteMinZ\r
+ 0x10000, //AbsoluteMaxX\r
+ 0x10000, //AbsoluteMaxY\r
+ 0x10000, //AbsoluteMaxZ\r
+ 0 //Attributes\r
+ },\r
+ 0,\r
+ (EFI_ABSOLUTE_POINTER_PROTOCOL **) NULL,\r
+ 0,\r
+ FALSE,\r
+\r
FALSE,\r
{\r
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
FALSE\r
};\r
\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL gUgaDrawProtocolTemplate = {\r
+ ConSpliterUgaDrawGetMode,\r
+ ConSpliterUgaDrawSetMode,\r
+ ConSpliterUgaDrawBlt\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL gGraphicsOutputProtocolTemplate = {\r
+ ConSpliterGraphicsOutputQueryMode,\r
+ ConSpliterGraphicsOutputSetMode,\r
+ ConSpliterGraphicsOutputBlt,\r
+ NULL\r
+};\r
+\r
STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {\r
TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
(EFI_HANDLE) NULL,\r
FALSE,\r
},\r
{\r
- ConSpliterGraphicsOutputQueryMode,\r
- ConSpliterGraphicsOutputSetMode,\r
- ConSpliterGraphicsOutputBlt,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ },\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ (EFI_UGA_PIXEL *) NULL,\r
+ {\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
NULL\r
},\r
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
- (TEXT_OUT_GOP_MODE *) NULL,\r
+ (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
+ 0,\r
0,\r
TRUE,\r
{\r
FALSE,\r
},\r
{\r
- ConSpliterGraphicsOutputQueryMode,\r
- ConSpliterGraphicsOutputSetMode,\r
- ConSpliterGraphicsOutputBlt,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ },\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ (EFI_UGA_PIXEL *) NULL,\r
+ {\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
NULL\r
},\r
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
- (TEXT_OUT_GOP_MODE *) NULL,\r
+ (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
+ 0,\r
0,\r
TRUE,\r
{\r
NULL\r
};\r
\r
+//\r
+// Driver binding instance for Absolute Pointer protocol\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding = {\r
+ ConSplitterAbsolutePointerDriverBindingSupported,\r
+ ConSplitterAbsolutePointerDriverBindingStart,\r
+ ConSplitterAbsolutePointerDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = {\r
ConSplitterConOutDriverBindingSupported,\r
ConSplitterConOutDriverBindingStart,\r
/**\r
The user Entry Point for module ConSplitter. The user code starts with this function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
@param[in] SystemTable A pointer to the EFI System Table.\r
- \r
+\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval other Some error occurs when executing this entry point.\r
\r
//\r
// Install driver model protocol(s).\r
//\r
- Status = EfiLibInstallAllDriverProtocols (\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
&gConSplitterConInDriverBinding,\r
ImageHandle,\r
&gConSplitterConInComponentName,\r
- NULL,\r
- NULL\r
+ &gConSplitterConInComponentName2\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = EfiLibInstallAllDriverProtocols (\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
&gConSplitterSimplePointerDriverBinding,\r
NULL,\r
&gConSplitterSimplePointerComponentName,\r
+ &gConSplitterSimplePointerComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gConSplitterAbsolutePointerDriverBinding,\r
NULL,\r
- NULL\r
+ &gConSplitterAbsolutePointerComponentName,\r
+ &gConSplitterAbsolutePointerComponentName2\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = EfiLibInstallAllDriverProtocols (\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
&gConSplitterConOutDriverBinding,\r
NULL,\r
&gConSplitterConOutComponentName,\r
- NULL,\r
- NULL\r
+ &gConSplitterConOutComponentName2\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = EfiLibInstallAllDriverProtocols (\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
&gConSplitterStdErrDriverBinding,\r
NULL,\r
&gConSplitterStdErrComponentName,\r
- NULL,\r
- NULL\r
+ &gConSplitterStdErrComponentName2\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
{\r
EFI_STATUS Status;\r
\r
+ ASSERT (FeaturePcdGet (PcdConOutGopSupport) ||\r
+ FeaturePcdGet (PcdConOutUgaSupport));\r
//\r
// The driver creates virtual handles for ConIn, ConOut, and StdErr.\r
// The virtual handles will always exist even if no console exist in the\r
&mConIn.VirtualHandle,\r
&gEfiSimpleTextInProtocolGuid,\r
&mConIn.TextIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &mConIn.TextInEx,\r
&gEfiSimplePointerProtocolGuid,\r
&mConIn.SimplePointer,\r
+ &gEfiAbsolutePointerProtocolGuid,\r
+ &mConIn.AbsolutePointer,\r
&gEfiPrimaryConsoleInDeviceGuid,\r
NULL,\r
NULL\r
//\r
Status = ConSplitterTextOutConstructor (&mConOut);\r
if (!EFI_ERROR (Status)) {\r
- //\r
- // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mConOut.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mConOut.TextOut,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &mConOut.GraphicsOutput,\r
- &gEfiConsoleControlProtocolGuid,\r
- &mConOut.ConsoleControl,\r
- &gEfiPrimaryConsoleOutDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
+ if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+ //\r
+ // In EFI mode, UGA Draw protocol is installed\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &mConOut.TextOut,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &mConOut.UgaDraw,\r
+ &gEfiConsoleControlProtocolGuid,\r
+ &mConOut.ConsoleControl,\r
+ &gEfiPrimaryConsoleOutDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ //\r
+ // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &mConOut.TextOut,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &mConOut.GraphicsOutput,\r
+ &gEfiConsoleControlProtocolGuid,\r
+ &mConOut.ConsoleControl,\r
+ &gEfiPrimaryConsoleOutDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ } else {\r
+ //\r
+ // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are\r
+ // installed on virtual handle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &mConOut.TextOut,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &mConOut.GraphicsOutput,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &mConOut.UgaDraw,\r
+ &gEfiConsoleControlProtocolGuid,\r
+ &mConOut.ConsoleControl,\r
+ &gEfiPrimaryConsoleOutDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
\r
if (!EFI_ERROR (Status)) {\r
//\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Buffer for Simple Text Input Ex Protocol\r
+ //\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &ConInPrivate->TextInExListCount,\r
+ (VOID **) &ConInPrivate->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ ConSplitterTextInWaitForKey,\r
+ ConInPrivate,\r
+ &ConInPrivate->TextInEx.WaitForKeyEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InitializeListHead (&ConInPrivate->NotifyList);\r
+\r
+ //\r
+ // Allocate Buffer and Create Event for Absolute Pointer and Simple Pointer Protocols\r
+ //\r
+ ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
+\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
+ &ConInPrivate->AbsolutePointerListCount,\r
+ (VOID **) &ConInPrivate->AbsolutePointerList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ ConSplitterAbsolutePointerWaitForInput,\r
+ ConInPrivate,\r
+ &ConInPrivate->AbsolutePointer.WaitForInput\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
\r
Status = ConSplitterGrowBuffer (\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
+\r
+ //\r
+ // Copy protocols template\r
+ //\r
+ if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ CopyMem (&ConOutPrivate->UgaDraw, &gUgaDrawProtocolTemplate, sizeof (EFI_UGA_DRAW_PROTOCOL));\r
+ }\r
+\r
+ if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+ CopyMem (&ConOutPrivate->GraphicsOutput, &gGraphicsOutputProtocolTemplate, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL));\r
+ }\r
\r
//\r
// Initilize console output splitter's private data.\r
//\r
ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
\r
+ //\r
+ // When new console device is added, the new mode will be set later,\r
+ // so put current mode back to init state.\r
+ //\r
+ ConOutPrivate->TextOutMode.Mode = 0xFF;\r
+\r
Status = ConSplitterGrowBuffer (\r
sizeof (TEXT_OUT_AND_GOP_DATA),\r
&ConOutPrivate->TextOutListCount,\r
ConOutPrivate->TextOutQueryData[0].Rows = 25;\r
DevNullTextOutSetMode (ConOutPrivate, 0);\r
\r
- //\r
- // Setup resource for mode information in Graphics Output Protocol interface\r
- //\r
- if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
- //\r
- if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ //\r
+ // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel\r
+ //\r
+ ConSpliterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);\r
}\r
- ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;\r
- ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;\r
+ if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+ //\r
+ // Setup resource for mode information in Graphics Output Protocol interface\r
+ //\r
+ if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
+ // DevNull will be updated to user-defined mode after driver has started.\r
+ //\r
+ if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Info = &ConOutPrivate->GraphicsOutputModeBuffer[0];\r
+ Info->Version = 0;\r
+ Info->HorizontalResolution = 800;\r
+ Info->VerticalResolution = 600;\r
+ Info->PixelFormat = PixelBltOnly;\r
+ Info->PixelsPerScanLine = 800;\r
+ CopyMem (ConOutPrivate->GraphicsOutput.Mode->Info, Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
+ ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
\r
- //\r
- // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
- // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat\r
- // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
- //\r
- ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
- ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
- ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
- ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
- ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
+ //\r
+ // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
+ // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
+ //\r
+ ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
+ ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
\r
- ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
- //\r
- // Initial current mode to unknow state, and then set to mode 0\r
- //\r
- ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
- ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
+ ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
+ //\r
+ // Initial current mode to unknow state, and then set to mode 0\r
+ //\r
+ ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
+ ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
+ }\r
\r
return Status;\r
}\r
);\r
}\r
\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Absolute Pointer Supported Check\r
+\r
+Arguments:\r
+ This - Pointer to protocol.\r
+ ControllerHandle - Controller handle.\r
+ RemainingDevicePath - Remaining device path.\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
+{\r
+ return ConSplitterSupported (\r
+ This,\r
+ ControllerHandle,\r
+ &gEfiAbsolutePointerProtocolGuid\r
+ );\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterConOutDriverBindingSupported (\r
{\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
return Status;\r
}\r
\r
- return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
+ Status = ConSplitterTextInAddDevice (&mConIn, TextIn);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ mConIn.VirtualHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
+\r
+ return Status;\r
}\r
\r
EFI_STATUS\r
return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);\r
}\r
\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Start ConSplitter on ControllerHandle, and create the virtual\r
+ agrogated console device on first call Start for a ConIn handle.\r
+\r
+Arguments:\r
+ This - Pointer to protocol.\r
+ ControllerHandle - Controller handle.\r
+ RemainingDevicePath - Remaining device path.\r
+\r
+Returns:\r
+\r
+ EFI_ERROR if a AbsolutePointer protocol is not started.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;\r
+\r
+ Status = ConSplitterStart (\r
+ This,\r
+ ControllerHandle,\r
+ mConIn.VirtualHandle,\r
+ &gEfiAbsolutePointerProtocolGuid,\r
+ &gEfiAbsolutePointerProtocolGuid,\r
+ (VOID **) &AbsolutePointer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return ConSplitterAbsolutePointerAddDevice (&mConIn, AbsolutePointer);\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterConOutDriverBindingStart (\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
+ GraphicsOutput = NULL;\r
+ UgaDraw = NULL;\r
//\r
// Try to Open Graphics Output protocol\r
//\r
mConOut.VirtualHandle,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
- if (EFI_ERROR (Status)) {\r
- GraphicsOutput = NULL;\r
+\r
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ //\r
+ // Open UGA_DRAW protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ (VOID **) &UgaDraw,\r
+ This->DriverBindingHandle,\r
+ mConOut.VirtualHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
}\r
+\r
//\r
- // Open UGA_DRAW protocol\r
+ // When new console device is added, the new mode will be set later,\r
+ // so put current mode back to init state.\r
//\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiUgaDrawProtocolGuid,\r
- (VOID **) &UgaDraw,\r
- This->DriverBindingHandle,\r
- mConOut.VirtualHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- UgaDraw = NULL;\r
- }\r
+ mConOut.TextOutMode.Mode = 0xFF;\r
+\r
//\r
// If both ConOut and StdErr incorporate the same Text Out device,\r
// their MaxMode and QueryData should be the intersection of both.\r
Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
\r
+ if (FeaturePcdGet (PcdConOutUgaSupport) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ //\r
+ // Match the UGA mode data of ConOut with the current mode\r
+ //\r
+ if (UgaDraw != NULL) {\r
+ UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &mConOut.UgaHorizontalResolution,\r
+ &mConOut.UgaVerticalResolution,\r
+ &mConOut.UgaColorDepth,\r
+ &mConOut.UgaRefreshRate\r
+ );\r
+ }\r
+ }\r
return Status;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
+ //\r
+ // When new console device is added, the new mode will be set later,\r
+ // so put current mode back to init state.\r
+ //\r
+ mStdErr.TextOutMode.Mode = 0xFF;\r
+\r
//\r
// If both ConOut and StdErr incorporate the same Text Out device,\r
// their MaxMode and QueryData should be the intersection of both.\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
if (NumberOfChildren == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+\r
Status = ConSplitterStop (\r
This,\r
ControllerHandle,\r
\r
EFI_STATUS\r
EFIAPI\r
-ConSplitterConOutDriverBindingStop (\r
+ConSplitterAbsolutePointerDriverBindingStop (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN UINTN NumberOfChildren,\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
+ EFI_STATUS Status;\r
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;\r
\r
if (NumberOfChildren == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
Status = ConSplitterStop (\r
- This,\r
- ControllerHandle,\r
- mConOut.VirtualHandle,\r
- &gEfiConsoleOutDeviceGuid,\r
- &gEfiSimpleTextOutProtocolGuid,\r
+ This,\r
+ ControllerHandle,\r
+ mConIn.VirtualHandle,\r
+ &gEfiAbsolutePointerProtocolGuid,\r
+ &gEfiAbsolutePointerProtocolGuid,\r
+ (VOID **) &AbsolutePointer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Delete this console input device's data structures.\r
+ //\r
+ return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterConOutDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+ (Standard DriverBinding Protocol Stop() function)\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
+\r
+ if (NumberOfChildren == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = ConSplitterStop (\r
+ This,\r
+ ControllerHandle,\r
+ mConOut.VirtualHandle,\r
+ &gEfiConsoleOutDeviceGuid,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
(VOID **) &TextOut\r
);\r
if (EFI_ERROR (Status)) {\r
return EFI_NOT_FOUND;\r
}\r
\r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If the TextInEx List is full, enlarge it by calling growbuffer().\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &Private->TextInExListCount,\r
+ (VOID **) &Private->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // Add the new text-in device data structure into the Text In List.\r
+ //\r
+ Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
+ Private->CurrentNumberOfExConsoles++;\r
+\r
+ //\r
+ // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
+ //\r
+ gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ UINTN Index;\r
+ //\r
+ // Remove the specified text-in device data structure from the Text In List,\r
+ // and rearrange the remaining data structures in the Text In List.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ if (Private->TextInExList[Index] == TextInEx) {\r
+ for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+ Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
+ }\r
+\r
+ Private->CurrentNumberOfExConsoles--;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
EFI_STATUS\r
ConSplitterSimplePointerAddDevice (\r
IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
return EFI_NOT_FOUND;\r
}\r
\r
+EFI_STATUS\r
+ConSplitterAbsolutePointerAddDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If the Absolute Pointer List is full, enlarge it by calling growbuffer().\r
+ //\r
+ if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
+ &Private->AbsolutePointerListCount,\r
+ (VOID **) &Private->AbsolutePointerList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // Add the new text-in device data structure into the Text In List.\r
+ //\r
+ Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;\r
+ Private->CurrentNumberOfAbsolutePointers++;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterAbsolutePointerDeleteDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ //\r
+ // Remove the specified text-in device data structure from the Text In List,\r
+ // and rearrange the remaining data structures in the Text In List.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+ if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
+ for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
+ Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
+ }\r
+\r
+ Private->CurrentNumberOfAbsolutePointers--;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
STATIC\r
EFI_STATUS\r
ConSplitterGrowMapTable (\r
Mode = 0;\r
Index = 0;\r
while (Mode < MaxMode) {\r
- TextOut->QueryMode (\r
- TextOut,\r
- Mode,\r
- &Private->TextOutQueryData[Mode].Columns,\r
- &Private->TextOutQueryData[Mode].Rows\r
- );\r
+ Status = TextOut->QueryMode (\r
+ TextOut,\r
+ Mode,\r
+ &Private->TextOutQueryData[Mode].Columns,\r
+ &Private->TextOutQueryData[Mode].Rows\r
+ );\r
+ //\r
+ // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData\r
+ // is clear to 0x0.\r
+ //\r
+ if ((EFI_ERROR(Status)) && (Mode == 1)) {\r
+ Private->TextOutQueryData[Mode].Columns = 0;\r
+ Private->TextOutQueryData[Mode].Rows = 0;\r
+ }\r
Private->TextOutModeMap[Index] = Mode;\r
Mode++;\r
Index += Private->TextOutListCount;\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Reconstruct TextOutModeMap to get intersection of modes\r
+\r
+ This routine reconstruct TextOutModeMap to get the intersection\r
+ of modes for all console out devices. Because EFI/UEFI spec require\r
+ mode 0 is 80x25, mode 1 is 80x50, this routine will not check the\r
+ intersection for mode 0 and mode 1.\r
+\r
+ @parm TextOutModeMap Current text out mode map, begin with the mode 80x25\r
+ @parm NewlyAddedMap New text out mode map, begin with the mode 80x25\r
+ @parm MapStepSize Mode step size for one console device\r
+ @parm NewMapStepSize Mode step size for one console device\r
+ @parm MaxMode Current max text mode\r
+ @parm CurrentMode Current text mode\r
+\r
+ @retval None\r
+\r
+**/\r
STATIC\r
VOID\r
ConSplitterGetIntersection (\r
INT32 CurrentMaxMode;\r
INT32 Mode;\r
\r
- Index = 0;\r
- CurrentMapEntry = TextOutModeMap;\r
- NextMapEntry = TextOutModeMap;\r
+ //\r
+ // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved\r
+ // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection\r
+ // for mode 0 and mode 1, mode number starts from 2.\r
+ //\r
+ Index = 2;\r
+ CurrentMapEntry = &TextOutModeMap[MapStepSize * 2];\r
+ NextMapEntry = &TextOutModeMap[MapStepSize * 2];\r
+ NewlyAddedMap = &NewlyAddedMap[NewMapStepSize * 2];\r
+\r
CurrentMaxMode = *MaxMode;\r
Mode = *CurrentMode;\r
\r
INT32 Index;\r
INT32 *TextOutModeMap;\r
INT32 *MapTable;\r
+ INT32 QueryMode;\r
TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;\r
UINTN Rows;\r
UINTN Columns;\r
UINTN StepSize;\r
+ EFI_STATUS Status;\r
\r
//\r
// Must make sure that current mode won't change even if mode number changes\r
Mode = 0;\r
MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
while (Mode < TextOut->Mode->MaxMode) {\r
- TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
-\r
+ Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
+ if (EFI_ERROR(Status)) {\r
+ if (Mode == 1) {\r
+ MapTable[StepSize] = Mode;\r
+ TextOutQueryData[Mode].Columns = 0;\r
+ TextOutQueryData[Mode].Rows = 0;\r
+ }\r
+ Mode++;\r
+ continue;\r
+ }\r
//\r
- // Search the QueryData database to see if they intersects\r
+ // Search the intersection map and QueryData database to see if they intersects\r
//\r
Index = 0;\r
while (Index < CurrentMaxMode) {\r
- if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
+ QueryMode = *(TextOutModeMap + Index * StepSize);\r
+ if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) {\r
MapTable[Index * StepSize] = Mode;\r
break;\r
}\r
\r
Returns:\r
\r
- None\r
+ EFI_SUCCESS\r
EFI_OUT_OF_RESOURCES\r
\r
--*/\r
TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;\r
UINTN Indexi;\r
UINTN Indexj;\r
- UINTN Rows;\r
- UINTN Columns;\r
+ UINTN ConOutRows;\r
+ UINTN ConOutColumns;\r
+ UINTN StdErrRows;\r
+ UINTN StdErrColumns;\r
INT32 ConOutMaxMode;\r
INT32 StdErrMaxMode;\r
+ INT32 ConOutMode;\r
+ INT32 StdErrMode;\r
INT32 Mode;\r
INT32 Index;\r
INT32 *ConOutModeMap;\r
INT32 *StdErrMapTable;\r
TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;\r
TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;\r
+ UINTN ConOutStepSize;\r
+ UINTN StdErrStepSize;\r
BOOLEAN FoundTheSameTextOut;\r
UINTN ConOutMapTableSize;\r
UINTN StdErrMapTableSize;\r
//\r
ConOutMaxMode = mConOut.TextOutMode.MaxMode;\r
ConOutModeMap = mConOut.TextOutModeMap;\r
+ ConOutStepSize = mConOut.TextOutListCount;\r
ConOutQueryData = mConOut.TextOutQueryData;\r
\r
StdErrMaxMode = mStdErr.TextOutMode.MaxMode;\r
StdErrModeMap = mStdErr.TextOutModeMap;\r
+ StdErrStepSize = mStdErr.TextOutListCount;\r
StdErrQueryData = mStdErr.TextOutQueryData;\r
\r
//\r
Mode = 0;\r
while (Mode < ConOutMaxMode) {\r
//\r
- // Search the other's QueryData database to see if they intersect\r
+ // Search the intersection map and QueryData database to see if they intersect\r
//\r
- Index = 0;\r
- Rows = ConOutQueryData[Mode].Rows;\r
- Columns = ConOutQueryData[Mode].Columns;\r
+ Index = 0;\r
+ ConOutMode = *(ConOutModeMap + Mode * ConOutStepSize);\r
+ ConOutRows = ConOutQueryData[ConOutMode].Rows;\r
+ ConOutColumns = ConOutQueryData[ConOutMode].Columns;\r
while (Index < StdErrMaxMode) {\r
- if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
+ StdErrMode = *(StdErrModeMap + Index * StdErrStepSize);\r
+ StdErrRows = StdErrQueryData[StdErrMode].Rows;\r
+ StdErrColumns = StdErrQueryData[StdErrMode].Columns;\r
+ if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) {\r
ConOutMapTable[Mode] = 1;\r
StdErrMapTable[Index] = 1;\r
break;\r
{\r
EFI_STATUS Status;\r
UINTN Index;\r
- TEXT_OUT_GOP_MODE *Mode;\r
+ UINTN CurrentIndex;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;\r
UINTN SizeOfInfo;\r
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;\r
- TEXT_OUT_GOP_MODE *ModeBuffer;\r
- TEXT_OUT_GOP_MODE *MatchedMode;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;\r
UINTN NumberIndex;\r
BOOLEAN Match;\r
+ BOOLEAN AlreadyExist;\r
+ UINT32 UgaHorizontalResolution;\r
+ UINT32 UgaVerticalResolution;\r
+ UINT32 UgaColorDepth;\r
+ UINT32 UgaRefreshRate;\r
\r
if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
return EFI_UNSUPPORTED;\r
\r
CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
\r
+ Index = 0;\r
+ CurrentIndex = 0;\r
+\r
+ if (Private->CurrentNumberOfUgaDraw != 0) {\r
+ //\r
+ // If any UGA device has already been added, then there is no need to\r
+ // calculate intersection of display mode of different GOP/UGA device,\r
+ // since only one display mode will be exported (i.e. user-defined mode)\r
+ //\r
+ goto Done;\r
+ }\r
+\r
if (GraphicsOutput != NULL) {\r
if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
//\r
//\r
// Allocate resource for the private mode buffer\r
//\r
- ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);\r
+ ModeBuffer = AllocatePool (GraphicsOutput->Mode->SizeOfInfo * GraphicsOutput->Mode->MaxMode);\r
if (ModeBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- Mode->HorizontalResolution = Info->HorizontalResolution;\r
- Mode->VerticalResolution = Info->VerticalResolution;\r
+ CopyMem (Mode, Info, SizeOfInfo);\r
Mode++;\r
FreePool (Info);\r
}\r
//\r
// Check intersection of display mode\r
//\r
- ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);\r
+ ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);\r
if (ModeBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
return Status;\r
}\r
if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
- (Info->VerticalResolution == Mode->VerticalResolution)){\r
+ (Info->VerticalResolution == Mode->VerticalResolution)) {\r
Match = TRUE;\r
FreePool (Info);\r
break;\r
}\r
\r
if (Match) {\r
- CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));\r
- MatchedMode++;\r
+ AlreadyExist = FALSE;\r
+\r
+ for (Info = ModeBuffer; Info < MatchedMode; Info++) {\r
+ if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
+ (Info->VerticalResolution == Mode->VerticalResolution)) {\r
+ AlreadyExist = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!AlreadyExist) {\r
+ CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
+\r
+ //\r
+ // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly\r
+ //\r
+ MatchedMode->Version = 0;\r
+ MatchedMode->PixelFormat = PixelBltOnly;\r
+ ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
+\r
+ MatchedMode++;\r
+ }\r
}\r
\r
Mode++;\r
//\r
// Physical frame buffer is no longer available when there are more than one physical GOP devices\r
//\r
- CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));\r
+ CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
}\r
\r
//\r
- // Select a prefered Display mode 800x600\r
+ // Graphics console driver can ensure the same mode for all GOP devices\r
//\r
for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
Mode = &Private->GraphicsOutputModeBuffer[Index];\r
- if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
+ if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) &&\r
+ (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) {\r
+ CurrentIndex = Index;\r
break;\r
}\r
}\r
- //\r
- // Prefered mode is not found, set to mode 0\r
- //\r
if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
- Index = 0;\r
+ //\r
+ // if user defined mode is not found, set to default mode 800x600\r
+ //\r
+ for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
+ Mode = &Private->GraphicsOutputModeBuffer[Index];\r
+ if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
+ CurrentIndex = Index;\r
+ break;\r
+ }\r
+ }\r
}\r
-\r
- //\r
- // Current mode number may need update now, so set it to an invalide mode number\r
- //\r
- CurrentGraphicsOutputMode->Mode = 0xffff;\r
- } else {\r
+ }\r
+ if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
//\r
- // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
- // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\r
+ // Graphics console driver can ensure the same mode for all GOP devices\r
+ // so we can get the current mode from this video device\r
//\r
+ UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &UgaHorizontalResolution,\r
+ &UgaVerticalResolution,\r
+ &UgaColorDepth,\r
+ &UgaRefreshRate\r
+ );\r
+\r
CurrentGraphicsOutputMode->MaxMode = 1;\r
- CurrentGraphicsOutputMode->Info->Version = 0;\r
- CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;\r
- CurrentGraphicsOutputMode->Info->VerticalResolution = 600;\r
- CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
- CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;\r
+ Info = CurrentGraphicsOutputMode->Info;\r
+ Info->Version = 0;\r
+ Info->HorizontalResolution = UgaHorizontalResolution;\r
+ Info->VerticalResolution = UgaVerticalResolution;\r
+ Info->PixelFormat = PixelBltOnly;\r
+ Info->PixelsPerScanLine = UgaHorizontalResolution;\r
CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
//\r
// Update the private mode buffer\r
//\r
- ModeBuffer = &Private->GraphicsOutputModeBuffer[0];\r
- ModeBuffer->HorizontalResolution = 800;\r
- ModeBuffer->VerticalResolution = 600;\r
+ CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
\r
//\r
- // Current mode is unknow now, set it to an invalid mode number 0xffff\r
+ // Only mode 0 is available to be set\r
//\r
- CurrentGraphicsOutputMode->Mode = 0xffff;\r
- Index = 0;\r
+ CurrentIndex = 0;\r
+ }\r
+\r
+Done:\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ Private->CurrentNumberOfGraphicsOutput++;\r
+ }\r
+ if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Private->CurrentNumberOfUgaDraw++;\r
}\r
\r
//\r
// regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
//\r
Private->HardwareNeedsStarting = TRUE;\r
- Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
+ //\r
+ // Current mode number may need update now, so set it to an invalid mode number\r
+ //\r
+ CurrentGraphicsOutputMode->Mode = 0xffff;\r
+ //\r
+ // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.\r
+ //\r
+ Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);\r
\r
- Private->CurrentNumberOfGraphicsOutput++;\r
+ //\r
+ // If user defined mode is not valid for UGA, set to the default mode 800x600.\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;\r
+ (Private->GraphicsOutputModeBuffer[0]).VerticalResolution = 600;\r
+ Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);\r
+ }\r
\r
return Status;\r
}\r
\r
+VOID\r
+ConsplitterSetConsoleOutMode (\r
+ IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine will get the current console mode information (column, row)\r
+ from ConsoleOutMode variable and set it; if the variable does not exist,\r
+ set to user defined console mode.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN Col;\r
+ UINTN Row;\r
+ UINTN Mode;\r
+ UINTN PreferMode;\r
+ UINTN BaseMode;\r
+ UINTN ModeInfoSize;\r
+ UINTN MaxMode;\r
+ EFI_STATUS Status;\r
+ CONSOLE_OUT_MODE *ModeInfo;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
+\r
+ PreferMode = 0xFF;\r
+ BaseMode = 0xFF;\r
+ TextOut = &Private->TextOut;\r
+ MaxMode = (UINTN) (TextOut->Mode->MaxMode);\r
+ ModeInfoSize = sizeof (CONSOLE_OUT_MODE);\r
+\r
+ ModeInfo = AllocateZeroPool (sizeof(CONSOLE_OUT_MODE));\r
+ ASSERT(ModeInfo != NULL);\r
+\r
+ Status = gRT->GetVariable (\r
+ VarConOutMode,\r
+ &gEfiGenericPlatformVariableGuid,\r
+ NULL,\r
+ &ModeInfoSize,\r
+ ModeInfo\r
+ );\r
+\r
+ //\r
+ // Set to the default mode 80 x 25 required by EFI/UEFI spec;\r
+ // user can also define other valid default console mode here.\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ ModeInfo->Column = 80;\r
+ ModeInfo->Row = 25;\r
+ Status = gRT->SetVariable (\r
+ VarConOutMode,\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (CONSOLE_OUT_MODE),\r
+ ModeInfo\r
+ );\r
+ }\r
+\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);\r
+ if (!EFI_ERROR(Status)) {\r
+ if (Col == ModeInfo->Column && Row == ModeInfo->Row) {\r
+ PreferMode = Mode;\r
+ }\r
+ if (Col == 80 && Row == 25) {\r
+ BaseMode = Mode;\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = TextOut->SetMode (TextOut, PreferMode);\r
+\r
+ //\r
+ // if current mode setting is failed, default 80x25 mode will be set.\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ Status = TextOut->SetMode (TextOut, BaseMode);\r
+ ASSERT(!EFI_ERROR(Status));\r
+\r
+ ModeInfo->Column = 80;\r
+ ModeInfo->Row = 25;\r
+\r
+ //\r
+ // Update ConOutMode variable\r
+ //\r
+ Status = gRT->SetVariable (\r
+ VarConOutMode,\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (CONSOLE_OUT_MODE),\r
+ ModeInfo\r
+ );\r
+ }\r
+\r
+ gBS->FreePool (ModeInfo);\r
+}\r
+\r
+\r
EFI_STATUS\r
ConSplitterTextOutAddDevice (\r
IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
UINTN CurrentNumOfConsoles;\r
INT32 CurrentMode;\r
INT32 MaxMode;\r
+ UINT32 UgaHorizontalResolution;\r
+ UINT32 UgaVerticalResolution;\r
+ UINT32 UgaColorDepth;\r
+ UINT32 UgaRefreshRate;\r
TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
\r
Status = EFI_SUCCESS;\r
\r
if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
//\r
- // If No UGA device then use the ConOut device\r
+ // If No GOP/UGA device then use the ConOut device\r
//\r
TextAndGop->TextOutEnabled = TRUE;\r
} else {\r
//\r
- // If UGA device use ConOut device only used if UGA screen is in Text mode\r
+ // If GOP/UGA device use ConOut device only used if screen is in Text mode\r
//\r
TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
}\r
MaxMode = Private->TextOutMode.MaxMode;\r
ASSERT (MaxMode >= 1);\r
\r
- if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
- ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
+ //\r
+ // Update DevNull mode according to current video device\r
+ //\r
+ if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+ if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
+ ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
+ }\r
+ }\r
+ if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Status = UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &UgaHorizontalResolution,\r
+ &UgaVerticalResolution,\r
+ &UgaColorDepth,\r
+ &UgaRefreshRate\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = ConSpliterUgaDrawSetMode (\r
+ &Private->UgaDraw,\r
+ UgaHorizontalResolution,\r
+ UgaVerticalResolution,\r
+ UgaColorDepth,\r
+ UgaRefreshRate\r
+ );\r
+ }\r
+ //\r
+ // If GetMode/SetMode is failed, set to 800x600 mode\r
+ //\r
+ if(EFI_ERROR (Status)) {\r
+ Status = ConSpliterUgaDrawSetMode (\r
+ &Private->UgaDraw,\r
+ 800,\r
+ 600,\r
+ 32,\r
+ 60\r
+ );\r
+ }\r
+ }\r
}\r
\r
if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
//\r
- // We just added a new UGA device in graphics mode\r
+ // We just added a new GOP or UGA device in graphics mode\r
//\r
- DevNullGopSync (Private, GraphicsOutput, UgaDraw);\r
+ if (FeaturePcdGet (PcdConOutGopSupport)) {\r
+ DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+ } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
+ }\r
} else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
//\r
// The new console supports the same mode of the current console so sync up\r
//\r
- DevNullSyncGopStdOut (Private);\r
+ DevNullSyncStdOut (Private);\r
} else {\r
//\r
// If ConOut, then set the mode to Mode #0 which us 80 x 25\r
Private->TextOut.SetMode (&Private->TextOut, 0);\r
}\r
\r
+ //\r
+ // After adding new console device, all existing console devices should be\r
+ // synced to the current shared mode.\r
+ //\r
+ ConsplitterSetConsoleOutMode (Private);\r
+\r
return Status;\r
}\r
\r
if (TextOutList->TextOut == TextOut) {\r
CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
CurrentNumOfConsoles--;\r
+ if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Private->CurrentNumberOfUgaDraw--;\r
+ }\r
+ if (TextOutList->GraphicsOutput != NULL) {\r
+ Private->CurrentNumberOfGraphicsOutput--;\r
+ }\r
break;\r
}\r
\r
}\r
}\r
\r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed.\r
+\r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+\r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE;\r
+ }\r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could\r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN Index;\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ //\r
+ // return the worst status met\r
+ //\r
+ for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->Reset (\r
+ Private->TextInExList[Index],\r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can\r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to\r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL.\r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_KEY_DATA CurrentKeyData;\r
+\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+ if (Private->PasswordEnabled) {\r
+ //\r
+ // If StdIn Locked return not ready\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ KeyData->Key.UnicodeChar = 0;\r
+ KeyData->Key.ScanCode = SCAN_NULL;\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_NOT_READY;\r
+ // if any physical console input device has key input,\r
+ // return the key and EFI_SUCCESS.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
+ Private->TextInExList[Index],\r
+ &CurrentKeyData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
+ state for the input device.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could\r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL.\r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_SUCCESS;\r
+ // otherwise return the status of setting state of physical console input device\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->SetState (\r
+ Private->TextInExList[Index],\r
+ KeyToggleState\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke\r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key\r
+ sequence is typed specified by KeyData.\r
+ NotifyHandle - Points to the unique handle assigned to the registered notification.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.\r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
+\r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists,\r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link,\r
+ TEXT_IN_EX_SPLITTER_NOTIFY,\r
+ NotifyEntry,\r
+ TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate resource to save the notification function\r
+ //\r
+ NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+ if (NewNotify->NotifyHandleList == NULL) {\r
+ gBS->FreePool (NewNotify);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;\r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+\r
+ //\r
+ // Return the wrong status of registering key notify of\r
+ // physical console input device if meet problems\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ KeyData,\r
+ KeyNotificationFunction,\r
+ &NewNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (NewNotify->NotifyHandleList);\r
+ gBS->FreePool (NewNotify);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+\r
+ *NotifyHandle = NewNotify->NotifyHandle;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database.\r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists,\r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ CurrentNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry);\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify->NotifyHandleList);\r
+ gBS->FreePool (CurrentNotify);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterSimplePointerReset (\r
}\r
}\r
\r
+//\r
+// Absolute Pointer Protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerReset (\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Resets the pointer device hardware.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could\r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN Index;\r
+\r
+ Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
+\r
+ Private->AbsoluteInputEventSignalState = FALSE;\r
+\r
+ if (Private->CurrentNumberOfAbsolutePointers == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // return the worst status met\r
+ //\r
+ for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+ Status = Private->AbsolutePointerList[Index]->Reset (\r
+ Private->AbsolutePointerList[Index],\r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterAbsolutePointerGetState (\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
+ IN OUT EFI_ABSOLUTE_POINTER_STATE *State\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves the current state of a pointer device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ State - A pointer to the state information on the pointer device.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The state of the pointer device was returned in State..\r
+ EFI_NOT_READY - The state of the pointer device has not changed since the last call to\r
+ GetState().\r
+ EFI_DEVICE_ERROR - A device error occurred while attempting to retrieve the pointer\r
+ device's current state.\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ UINTN Index;\r
+ EFI_ABSOLUTE_POINTER_STATE CurrentState;\r
+\r
+\r
+ Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
+ if (Private->PasswordEnabled) {\r
+ //\r
+ // If StdIn Locked return not ready\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Private->AbsoluteInputEventSignalState = FALSE;\r
+\r
+ State->CurrentX = 0;\r
+ State->CurrentY = 0;\r
+ State->CurrentZ = 0;\r
+ State->ActiveButtons = 0;\r
+\r
+ //\r
+ // if no physical pointer device exists, return EFI_NOT_READY;\r
+ // if any physical pointer device has changed state,\r
+ // return the state and EFI_SUCCESS.\r
+ //\r
+ ReturnStatus = EFI_NOT_READY;\r
+ for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+\r
+ Status = Private->AbsolutePointerList[Index]->GetState (\r
+ Private->AbsolutePointerList[Index],\r
+ &CurrentState\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (ReturnStatus == EFI_NOT_READY) {\r
+ ReturnStatus = EFI_SUCCESS;\r
+ }\r
+\r
+ State->ActiveButtons = CurrentState.ActiveButtons;\r
+\r
+ if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
+ State->CurrentX = CurrentState.CurrentX;\r
+ }\r
+ if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
+ State->CurrentY = CurrentState.CurrentY;\r
+ }\r
+ if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
+ State->CurrentZ = CurrentState.CurrentZ;\r
+ }\r
+\r
+ } else if (Status == EFI_DEVICE_ERROR) {\r
+ ReturnStatus = EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+ConSplitterAbsolutePointerWaitForInput (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This event agregates all the events of the pointer devices in the splitter.\r
+ If the ConIn is password locked then return.\r
+ If any events of physical pointer devices are signaled, signal the pointer\r
+ splitter event. This will cause the calling code to call\r
+ ConSplitterAbsolutePointerGetState ().\r
+\r
+Arguments:\r
+ Event - The Event assoicated with callback.\r
+ Context - Context registered when Event was created.\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN Index;\r
+\r
+ Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
+ if (Private->PasswordEnabled) {\r
+ //\r
+ // If StdIn Locked return not ready\r
+ //\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // if AbsoluteInputEventSignalState is flagged before,\r
+ // and not cleared by Reset() or GetState(), signal it\r
+ //\r
+ if (Private->AbsoluteInputEventSignalState) {\r
+ gBS->SignalEvent (Event);\r
+ return ;\r
+ }\r
+ //\r
+ // if any physical console input device has key input, signal the event.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
+ Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->SignalEvent (Event);\r
+ Private->AbsoluteInputEventSignalState = TRUE;\r
+ }\r
+ }\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterTextOutReset (\r
--*/\r
{\r
TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN CurrentMode;\r
+ INT32 *TextOutModeMap;\r
\r
Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
\r
return EFI_UNSUPPORTED;\r
}\r
\r
- *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
- *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
+ //\r
+ // We get the available mode from mode intersection map if it's available\r
+ //\r
+ if (Private->TextOutModeMap != NULL) {\r
+ TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
+ CurrentMode = (UINTN)(*TextOutModeMap);\r
+ *Columns = Private->TextOutQueryData[CurrentMode].Columns;\r
+ *Rows = Private->TextOutQueryData[CurrentMode].Rows;\r
+ } else {\r
+ *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
+ *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
+ }\r
\r
if (*Columns <= 0 && *Rows <= 0) {\r
return EFI_UNSUPPORTED;\r
TextOutModeMap[Index]\r
);\r
//\r
- // If this console device is based on a UGA device, then sync up the bitmap from\r
- // the UGA splitter and reclear the text portion of the display in the new mode.\r
+ // If this console device is based on a GOP or UGA device, then sync up the bitmap from\r
+ // the GOP/UGA splitter and reclear the text portion of the display in the new mode.\r
//\r
if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
EFI_STATUS ReturnStatus;\r
UINTN MaxColumn;\r
UINTN MaxRow;\r
+ INT32 *TextOutModeMap;\r
+ INT32 ModeNumber;\r
+ INT32 CurrentMode;\r
\r
Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+ TextOutModeMap = NULL;\r
+ ModeNumber = Private->TextOutMode.Mode;\r
\r
- MaxColumn = Private->TextOutQueryData[Private->TextOutMode.Mode].Columns;\r
- MaxRow = Private->TextOutQueryData[Private->TextOutMode.Mode].Rows;\r
+ //\r
+ // Get current MaxColumn and MaxRow from intersection map\r
+ //\r
+ if (Private->TextOutModeMap != NULL) {\r
+ TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
+ CurrentMode = *TextOutModeMap;\r
+ } else {\r
+ CurrentMode = ModeNumber;\r
+ }\r
+\r
+ MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;\r
+ MaxRow = Private->TextOutQueryData[CurrentMode].Rows;\r
\r
if (Column >= MaxColumn || Row >= MaxRow) {\r
return EFI_UNSUPPORTED;\r
\r
return ReturnStatus;\r
}\r
+\r