2 Console Splitter Driver. Any Handle that attatched
3 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
5 So far it works like any other driver by opening a SimpleTextIn and/or
6 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
7 difference is this driver does not layer a protocol on the passed in
8 handle, or construct a child handle like a standard device or bus driver.
9 This driver produces three virtual handles as children, one for console input
10 splitter, one for console output splitter and one for error output splitter.
11 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
12 identify the splitter type.
14 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
15 and Console I/O protocol, will be produced in the driver entry point.
16 The virtual handle are added on driver entry and never removed.
17 Such design ensures sytem function well during none console device situation.
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "ConSplitter.h"
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
39 ConSplitterTextInReset
,
40 ConSplitterTextInReadKeyStroke
,
44 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
48 ConSplitterSimplePointerReset
,
49 ConSplitterSimplePointerGetState
,
51 (EFI_SIMPLE_POINTER_MODE
*) NULL
61 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
84 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
85 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
88 ConSplitterTextOutReset
,
89 ConSplitterTextOutOutputString
,
90 ConSplitterTextOutTestString
,
91 ConSplitterTextOutQueryMode
,
92 ConSplitterTextOutSetMode
,
93 ConSplitterTextOutSetAttribute
,
94 ConSplitterTextOutClearScreen
,
95 ConSplitterTextOutSetCursorPosition
,
96 ConSplitterTextOutEnableCursor
,
97 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
108 ConSpliterGraphicsOutputQueryMode
,
109 ConSpliterGraphicsOutputSetMode
,
110 ConSpliterGraphicsOutputBlt
,
113 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
114 (TEXT_OUT_GOP_MODE
*) NULL
,
118 ConSpliterConsoleControlGetMode
,
119 ConSpliterConsoleControlSetMode
,
120 ConSpliterConsoleControlLockStdIn
124 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
126 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
130 EfiConsoleControlScreenText
,
137 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
138 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
141 ConSplitterTextOutReset
,
142 ConSplitterTextOutOutputString
,
143 ConSplitterTextOutTestString
,
144 ConSplitterTextOutQueryMode
,
145 ConSplitterTextOutSetMode
,
146 ConSplitterTextOutSetAttribute
,
147 ConSplitterTextOutClearScreen
,
148 ConSplitterTextOutSetCursorPosition
,
149 ConSplitterTextOutEnableCursor
,
150 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
161 ConSpliterGraphicsOutputQueryMode
,
162 ConSpliterGraphicsOutputSetMode
,
163 ConSpliterGraphicsOutputBlt
,
166 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
167 (TEXT_OUT_GOP_MODE
*) NULL
,
171 ConSpliterConsoleControlGetMode
,
172 ConSpliterConsoleControlSetMode
,
173 ConSpliterConsoleControlLockStdIn
177 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
179 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
183 EfiConsoleControlScreenText
,
190 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
191 ConSplitterConInDriverBindingSupported
,
192 ConSplitterConInDriverBindingStart
,
193 ConSplitterConInDriverBindingStop
,
199 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
200 ConSplitterSimplePointerDriverBindingSupported
,
201 ConSplitterSimplePointerDriverBindingStart
,
202 ConSplitterSimplePointerDriverBindingStop
,
208 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
209 ConSplitterConOutDriverBindingSupported
,
210 ConSplitterConOutDriverBindingStart
,
211 ConSplitterConOutDriverBindingStop
,
217 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
218 ConSplitterStdErrDriverBindingSupported
,
219 ConSplitterStdErrDriverBindingStart
,
220 ConSplitterStdErrDriverBindingStop
,
227 The user Entry Point for module ConSplitter. The user code starts with this function.
229 @param[in] ImageHandle The firmware allocated handle for the EFI image.
230 @param[in] SystemTable A pointer to the EFI System Table.
232 @retval EFI_SUCCESS The entry point is executed successfully.
233 @retval other Some error occurs when executing this entry point.
238 InitializeConSplitter(
239 IN EFI_HANDLE ImageHandle
,
240 IN EFI_SYSTEM_TABLE
*SystemTable
246 // Install driver model protocol(s).
248 Status
= EfiLibInstallDriverBindingComponentName2 (
251 &gConSplitterConInDriverBinding
,
253 &gConSplitterConInComponentName
,
254 &gConSplitterConInComponentName2
256 ASSERT_EFI_ERROR (Status
);
258 Status
= EfiLibInstallDriverBindingComponentName2 (
261 &gConSplitterSimplePointerDriverBinding
,
263 &gConSplitterSimplePointerComponentName
,
264 &gConSplitterSimplePointerComponentName2
266 ASSERT_EFI_ERROR (Status
);
268 Status
= EfiLibInstallDriverBindingComponentName2 (
271 &gConSplitterConOutDriverBinding
,
273 &gConSplitterConOutComponentName
,
274 &gConSplitterConOutComponentName2
276 ASSERT_EFI_ERROR (Status
);
278 Status
= EfiLibInstallDriverBindingComponentName2 (
281 &gConSplitterStdErrDriverBinding
,
283 &gConSplitterStdErrComponentName
,
284 &gConSplitterStdErrComponentName2
286 ASSERT_EFI_ERROR (Status
);
290 // Call the original Entry Point
292 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
300 ConSplitterDriverEntry (
301 IN EFI_HANDLE ImageHandle
,
302 IN EFI_SYSTEM_TABLE
*SystemTable
307 Intialize a virtual console device to act as an agrigator of physical console
311 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
312 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
321 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
322 // The virtual handles will always exist even if no console exist in the
323 // system. This is need to support hotplug devices like USB.
326 // Create virtual device handle for StdErr Splitter
328 Status
= ConSplitterTextOutConstructor (&mStdErr
);
329 if (!EFI_ERROR (Status
)) {
330 Status
= gBS
->InstallMultipleProtocolInterfaces (
331 &mStdErr
.VirtualHandle
,
332 &gEfiSimpleTextOutProtocolGuid
,
334 &gEfiPrimaryStandardErrorDeviceGuid
,
340 // Create virtual device handle for ConIn Splitter
342 Status
= ConSplitterTextInConstructor (&mConIn
);
343 if (!EFI_ERROR (Status
)) {
344 Status
= gBS
->InstallMultipleProtocolInterfaces (
345 &mConIn
.VirtualHandle
,
346 &gEfiSimpleTextInProtocolGuid
,
348 &gEfiSimplePointerProtocolGuid
,
349 &mConIn
.SimplePointer
,
350 &gEfiPrimaryConsoleInDeviceGuid
,
354 if (!EFI_ERROR (Status
)) {
356 // Update the EFI System Table with new virtual console
358 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
359 gST
->ConIn
= &mConIn
.TextIn
;
363 // Create virtual device handle for ConOut Splitter
365 Status
= ConSplitterTextOutConstructor (&mConOut
);
366 if (!EFI_ERROR (Status
)) {
368 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
370 Status
= gBS
->InstallMultipleProtocolInterfaces (
371 &mConOut
.VirtualHandle
,
372 &gEfiSimpleTextOutProtocolGuid
,
374 &gEfiGraphicsOutputProtocolGuid
,
375 &mConOut
.GraphicsOutput
,
376 &gEfiConsoleControlProtocolGuid
,
377 &mConOut
.ConsoleControl
,
378 &gEfiPrimaryConsoleOutDeviceGuid
,
383 if (!EFI_ERROR (Status
)) {
385 // Update the EFI System Table with new virtual console
387 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
388 gST
->ConOut
= &mConOut
.TextOut
;
393 // Update the CRC32 in the EFI System Table header
396 gBS
->CalculateCrc32 (
406 ConSplitterTextInConstructor (
407 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
413 Construct the ConSplitter.
417 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
420 EFI_OUT_OF_RESOURCES - Out of resources.
427 // Initilize console input splitter's private data.
429 Status
= ConSplitterGrowBuffer (
430 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
431 &ConInPrivate
->TextInListCount
,
432 (VOID
**) &ConInPrivate
->TextInList
434 if (EFI_ERROR (Status
)) {
435 return EFI_OUT_OF_RESOURCES
;
438 // Create Event to support locking StdIn Device
440 Status
= gBS
->CreateEvent (
441 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
443 ConSpliterConsoleControlLockStdInEvent
,
445 &ConInPrivate
->LockEvent
447 ASSERT_EFI_ERROR (Status
);
449 Status
= gBS
->CreateEvent (
452 ConSplitterTextInWaitForKey
,
454 &ConInPrivate
->TextIn
.WaitForKey
456 ASSERT_EFI_ERROR (Status
);
458 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
460 Status
= ConSplitterGrowBuffer (
461 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
462 &ConInPrivate
->PointerListCount
,
463 (VOID
**) &ConInPrivate
->PointerList
465 if (EFI_ERROR (Status
)) {
466 return EFI_OUT_OF_RESOURCES
;
469 Status
= gBS
->CreateEvent (
472 ConSplitterSimplePointerWaitForInput
,
474 &ConInPrivate
->SimplePointer
.WaitForInput
481 ConSplitterTextOutConstructor (
482 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
488 // Initilize console output splitter's private data.
490 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
492 Status
= ConSplitterGrowBuffer (
493 sizeof (TEXT_OUT_AND_GOP_DATA
),
494 &ConOutPrivate
->TextOutListCount
,
495 (VOID
**) &ConOutPrivate
->TextOutList
497 if (EFI_ERROR (Status
)) {
498 return EFI_OUT_OF_RESOURCES
;
501 Status
= ConSplitterGrowBuffer (
502 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
503 &ConOutPrivate
->TextOutQueryDataCount
,
504 (VOID
**) &ConOutPrivate
->TextOutQueryData
506 if (EFI_ERROR (Status
)) {
507 return EFI_OUT_OF_RESOURCES
;
510 // Setup the DevNullTextOut console to 80 x 25
512 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
513 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
514 DevNullTextOutSetMode (ConOutPrivate
, 0);
517 // Setup resource for mode information in Graphics Output Protocol interface
519 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
520 return EFI_OUT_OF_RESOURCES
;
522 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
523 return EFI_OUT_OF_RESOURCES
;
526 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
528 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
529 return EFI_OUT_OF_RESOURCES
;
531 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
532 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
535 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
536 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
537 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
539 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
540 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
541 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
542 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
543 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
545 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
547 // Initial current mode to unknow state, and then set to mode 0
549 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
550 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
557 ConSplitterSupported (
558 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
559 IN EFI_HANDLE ControllerHandle
,
565 Generic Supported Check
568 This - Pointer to protocol.
569 ControllerHandle - Controller Handle.
574 EFI_UNSUPPORTED - unsupported.
575 EFI_SUCCESS - operation is OK.
583 // Make sure the Console Splitter does not attempt to attach to itself
585 if (ControllerHandle
== mConIn
.VirtualHandle
) {
586 return EFI_UNSUPPORTED
;
589 if (ControllerHandle
== mConOut
.VirtualHandle
) {
590 return EFI_UNSUPPORTED
;
593 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
594 return EFI_UNSUPPORTED
;
597 // Check to see whether the handle has the ConsoleInDevice GUID on it
599 Status
= gBS
->OpenProtocol (
603 This
->DriverBindingHandle
,
605 EFI_OPEN_PROTOCOL_BY_DRIVER
608 if (EFI_ERROR (Status
)) {
615 This
->DriverBindingHandle
,
624 ConSplitterConInDriverBindingSupported (
625 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
626 IN EFI_HANDLE ControllerHandle
,
627 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
632 Console In Supported Check
635 This - Pointer to protocol.
636 ControllerHandle - Controller handle.
637 RemainingDevicePath - Remaining device path.
645 return ConSplitterSupported (
648 &gEfiConsoleInDeviceGuid
654 ConSplitterSimplePointerDriverBindingSupported (
655 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
656 IN EFI_HANDLE ControllerHandle
,
657 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
662 Standard Error Supported Check
665 This - Pointer to protocol.
666 ControllerHandle - Controller handle.
667 RemainingDevicePath - Remaining device path.
675 return ConSplitterSupported (
678 &gEfiSimplePointerProtocolGuid
684 ConSplitterConOutDriverBindingSupported (
685 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
686 IN EFI_HANDLE ControllerHandle
,
687 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
692 Console Out Supported Check
695 This - Pointer to protocol.
696 ControllerHandle - Controller handle.
697 RemainingDevicePath - Remaining device path.
705 return ConSplitterSupported (
708 &gEfiConsoleOutDeviceGuid
714 ConSplitterStdErrDriverBindingSupported (
715 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
716 IN EFI_HANDLE ControllerHandle
,
717 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
722 Standard Error Supported Check
725 This - Pointer to protocol.
726 ControllerHandle - Controller handle.
727 RemainingDevicePath - Remaining device path.
735 return ConSplitterSupported (
738 &gEfiStandardErrorDeviceGuid
746 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
747 IN EFI_HANDLE ControllerHandle
,
748 IN EFI_HANDLE ConSplitterVirtualHandle
,
749 IN EFI_GUID
*DeviceGuid
,
750 IN EFI_GUID
*InterfaceGuid
,
756 Start ConSplitter on ControllerHandle, and create the virtual
757 agrogated console device on first call Start for a SimpleTextIn handle.
760 (Standard DriverBinding Protocol Start() function)
763 EFI_ERROR if a SimpleTextIn protocol is not started.
771 // Check to see whether the handle has the ConsoleInDevice GUID on it
773 Status
= gBS
->OpenProtocol (
777 This
->DriverBindingHandle
,
779 EFI_OPEN_PROTOCOL_BY_DRIVER
781 if (EFI_ERROR (Status
)) {
785 Status
= gBS
->OpenProtocol (
789 This
->DriverBindingHandle
,
790 ConSplitterVirtualHandle
,
791 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
793 if (EFI_ERROR (Status
)) {
797 return gBS
->OpenProtocol (
801 This
->DriverBindingHandle
,
802 ConSplitterVirtualHandle
,
803 EFI_OPEN_PROTOCOL_GET_PROTOCOL
809 ConSplitterConInDriverBindingStart (
810 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
811 IN EFI_HANDLE ControllerHandle
,
812 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
817 Start ConSplitter on ControllerHandle, and create the virtual
818 agrogated console device on first call Start for a SimpleTextIn handle.
821 This - Pointer to protocol.
822 ControllerHandle - Controller handle.
823 RemainingDevicePath - Remaining device path.
828 EFI_ERROR if a SimpleTextIn protocol is not started.
833 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
836 // Start ConSplitter on ControllerHandle, and create the virtual
837 // agrogated console device on first call Start for a SimpleTextIn handle.
839 Status
= ConSplitterStart (
842 mConIn
.VirtualHandle
,
843 &gEfiConsoleInDeviceGuid
,
844 &gEfiSimpleTextInProtocolGuid
,
847 if (EFI_ERROR (Status
)) {
851 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
856 ConSplitterSimplePointerDriverBindingStart (
857 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
858 IN EFI_HANDLE ControllerHandle
,
859 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
864 Start ConSplitter on ControllerHandle, and create the virtual
865 agrogated console device on first call Start for a SimpleTextIn handle.
868 This - Pointer to protocol.
869 ControllerHandle - Controller handle.
870 RemainingDevicePath - Remaining device path.
874 EFI_ERROR if a SimpleTextIn protocol is not started.
879 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
881 Status
= ConSplitterStart (
884 mConIn
.VirtualHandle
,
885 &gEfiSimplePointerProtocolGuid
,
886 &gEfiSimplePointerProtocolGuid
,
887 (VOID
**) &SimplePointer
889 if (EFI_ERROR (Status
)) {
893 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
898 ConSplitterConOutDriverBindingStart (
899 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
900 IN EFI_HANDLE ControllerHandle
,
901 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
906 Start ConSplitter on ControllerHandle, and create the virtual
907 agrogated console device on first call Start for a SimpleTextIn handle.
910 This - Pointer to protocol.
911 ControllerHandle - Controller handle.
912 RemainingDevicePath - Remaining device path.
915 EFI_ERROR if a SimpleTextIn protocol is not started.
920 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
921 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
922 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
924 Status
= ConSplitterStart (
927 mConOut
.VirtualHandle
,
928 &gEfiConsoleOutDeviceGuid
,
929 &gEfiSimpleTextOutProtocolGuid
,
932 if (EFI_ERROR (Status
)) {
936 // Try to Open Graphics Output protocol
938 Status
= gBS
->OpenProtocol (
940 &gEfiGraphicsOutputProtocolGuid
,
941 (VOID
**) &GraphicsOutput
,
942 This
->DriverBindingHandle
,
943 mConOut
.VirtualHandle
,
944 EFI_OPEN_PROTOCOL_GET_PROTOCOL
946 if (EFI_ERROR (Status
)) {
947 GraphicsOutput
= NULL
;
950 // Open UGA_DRAW protocol
952 Status
= gBS
->OpenProtocol (
954 &gEfiUgaDrawProtocolGuid
,
956 This
->DriverBindingHandle
,
957 mConOut
.VirtualHandle
,
958 EFI_OPEN_PROTOCOL_GET_PROTOCOL
960 if (EFI_ERROR (Status
)) {
964 // If both ConOut and StdErr incorporate the same Text Out device,
965 // their MaxMode and QueryData should be the intersection of both.
967 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
968 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
975 ConSplitterStdErrDriverBindingStart (
976 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
977 IN EFI_HANDLE ControllerHandle
,
978 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
983 Start ConSplitter on ControllerHandle, and create the virtual
984 agrogated console device on first call Start for a SimpleTextIn handle.
987 This - Pointer to protocol.
988 ControllerHandle - Controller handle.
989 RemainingDevicePath - Remaining device path.
992 EFI_ERROR if a SimpleTextIn protocol is not started.
997 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
999 Status
= ConSplitterStart (
1002 mStdErr
.VirtualHandle
,
1003 &gEfiStandardErrorDeviceGuid
,
1004 &gEfiSimpleTextOutProtocolGuid
,
1007 if (EFI_ERROR (Status
)) {
1011 // If both ConOut and StdErr incorporate the same Text Out device,
1012 // their MaxMode and QueryData should be the intersection of both.
1014 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1015 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1016 if (EFI_ERROR (Status
)) {
1020 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1021 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1022 gST
->StdErr
= &mStdErr
.TextOut
;
1024 // Update the CRC32 in the EFI System Table header
1027 gBS
->CalculateCrc32 (
1028 (UINT8
*) &gST
->Hdr
,
1029 gST
->Hdr
.HeaderSize
,
1041 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1042 IN EFI_HANDLE ControllerHandle
,
1043 IN EFI_HANDLE ConSplitterVirtualHandle
,
1044 IN EFI_GUID
*DeviceGuid
,
1045 IN EFI_GUID
*InterfaceGuid
,
1050 Routine Description:
1053 (Standard DriverBinding Protocol Stop() function)
1063 Status
= gBS
->OpenProtocol (
1067 This
->DriverBindingHandle
,
1069 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1071 if (EFI_ERROR (Status
)) {
1075 // close the protocol refered.
1077 gBS
->CloseProtocol (
1080 This
->DriverBindingHandle
,
1081 ConSplitterVirtualHandle
1083 gBS
->CloseProtocol (
1086 This
->DriverBindingHandle
,
1095 ConSplitterConInDriverBindingStop (
1096 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1097 IN EFI_HANDLE ControllerHandle
,
1098 IN UINTN NumberOfChildren
,
1099 IN EFI_HANDLE
*ChildHandleBuffer
1103 Routine Description:
1106 (Standard DriverBinding Protocol Stop() function)
1115 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1117 if (NumberOfChildren
== 0) {
1121 Status
= ConSplitterStop (
1124 mConIn
.VirtualHandle
,
1125 &gEfiConsoleInDeviceGuid
,
1126 &gEfiSimpleTextInProtocolGuid
,
1129 if (EFI_ERROR (Status
)) {
1133 // Delete this console input device's data structures.
1135 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1140 ConSplitterSimplePointerDriverBindingStop (
1141 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1142 IN EFI_HANDLE ControllerHandle
,
1143 IN UINTN NumberOfChildren
,
1144 IN EFI_HANDLE
*ChildHandleBuffer
1148 Routine Description:
1151 (Standard DriverBinding Protocol Stop() function)
1160 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1162 if (NumberOfChildren
== 0) {
1166 Status
= ConSplitterStop (
1169 mConIn
.VirtualHandle
,
1170 &gEfiSimplePointerProtocolGuid
,
1171 &gEfiSimplePointerProtocolGuid
,
1172 (VOID
**) &SimplePointer
1174 if (EFI_ERROR (Status
)) {
1178 // Delete this console input device's data structures.
1180 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1185 ConSplitterConOutDriverBindingStop (
1186 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1187 IN EFI_HANDLE ControllerHandle
,
1188 IN UINTN NumberOfChildren
,
1189 IN EFI_HANDLE
*ChildHandleBuffer
1193 Routine Description:
1196 (Standard DriverBinding Protocol Stop() function)
1205 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1207 if (NumberOfChildren
== 0) {
1211 Status
= ConSplitterStop (
1214 mConOut
.VirtualHandle
,
1215 &gEfiConsoleOutDeviceGuid
,
1216 &gEfiSimpleTextOutProtocolGuid
,
1219 if (EFI_ERROR (Status
)) {
1224 // Delete this console output device's data structures.
1226 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1231 ConSplitterStdErrDriverBindingStop (
1232 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1233 IN EFI_HANDLE ControllerHandle
,
1234 IN UINTN NumberOfChildren
,
1235 IN EFI_HANDLE
*ChildHandleBuffer
1239 Routine Description:
1242 (Standard DriverBinding Protocol Stop() function)
1246 EFI_SUCCESS - Complete successfully.
1251 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1253 if (NumberOfChildren
== 0) {
1257 Status
= ConSplitterStop (
1260 mStdErr
.VirtualHandle
,
1261 &gEfiStandardErrorDeviceGuid
,
1262 &gEfiSimpleTextOutProtocolGuid
,
1265 if (EFI_ERROR (Status
)) {
1269 // Delete this console error out device's data structures.
1271 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1272 if (EFI_ERROR (Status
)) {
1276 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1277 gST
->StandardErrorHandle
= NULL
;
1280 // Update the CRC32 in the EFI System Table header
1283 gBS
->CalculateCrc32 (
1284 (UINT8
*) &gST
->Hdr
,
1285 gST
->Hdr
.HeaderSize
,
1294 ConSplitterGrowBuffer (
1295 IN UINTN SizeOfCount
,
1297 IN OUT VOID
**Buffer
1301 Routine Description:
1302 Take the passed in Buffer of size SizeOfCount and grow the buffer
1303 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1304 bytes. Copy the current data in Buffer to the new version of Buffer
1305 and free the old version of buffer.
1309 SizeOfCount - Size of element in array
1310 Count - Current number of elements in array
1311 Buffer - Bigger version of passed in Buffer with all the data
1314 EFI_SUCCESS - Buffer size has grown
1315 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1326 // grow the buffer to new buffer size,
1327 // copy the old buffer's content to the new-size buffer,
1328 // then free the old buffer.
1330 OldSize
= *Count
* SizeOfCount
;
1331 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1332 NewSize
= *Count
* SizeOfCount
;
1334 Ptr
= AllocateZeroPool (NewSize
);
1336 return EFI_OUT_OF_RESOURCES
;
1339 CopyMem (Ptr
, *Buffer
, OldSize
);
1341 if (*Buffer
!= NULL
) {
1351 ConSplitterTextInAddDevice (
1352 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1353 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1357 Routine Description:
1364 EFI_OUT_OF_RESOURCES
1371 // If the Text In List is full, enlarge it by calling growbuffer().
1373 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1374 Status
= ConSplitterGrowBuffer (
1375 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1376 &Private
->TextInListCount
,
1377 (VOID
**) &Private
->TextInList
1379 if (EFI_ERROR (Status
)) {
1380 return EFI_OUT_OF_RESOURCES
;
1384 // Add the new text-in device data structure into the Text In List.
1386 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1387 Private
->CurrentNumberOfConsoles
++;
1390 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1392 gBS
->CheckEvent (TextIn
->WaitForKey
);
1398 ConSplitterTextInDeleteDevice (
1399 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1400 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1404 Routine Description:
1417 // Remove the specified text-in device data structure from the Text In List,
1418 // and rearrange the remaining data structures in the Text In List.
1420 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1421 if (Private
->TextInList
[Index
] == TextIn
) {
1422 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1423 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1426 Private
->CurrentNumberOfConsoles
--;
1431 return EFI_NOT_FOUND
;
1435 ConSplitterSimplePointerAddDevice (
1436 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1437 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1441 Routine Description:
1447 EFI_OUT_OF_RESOURCES
1455 // If the Text In List is full, enlarge it by calling growbuffer().
1457 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1458 Status
= ConSplitterGrowBuffer (
1459 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1460 &Private
->PointerListCount
,
1461 (VOID
**) &Private
->PointerList
1463 if (EFI_ERROR (Status
)) {
1464 return EFI_OUT_OF_RESOURCES
;
1468 // Add the new text-in device data structure into the Text In List.
1470 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1471 Private
->CurrentNumberOfPointers
++;
1476 ConSplitterSimplePointerDeleteDevice (
1477 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1478 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1482 Routine Description:
1494 // Remove the specified text-in device data structure from the Text In List,
1495 // and rearrange the remaining data structures in the Text In List.
1497 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1498 if (Private
->PointerList
[Index
] == SimplePointer
) {
1499 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1500 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1503 Private
->CurrentNumberOfPointers
--;
1508 return EFI_NOT_FOUND
;
1513 ConSplitterGrowMapTable (
1514 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1518 Routine Description:
1531 INT32
*TextOutModeMap
;
1532 INT32
*OldTextOutModeMap
;
1536 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1537 OldTextOutModeMap
= Private
->TextOutModeMap
;
1538 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1540 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1541 if (TextOutModeMap
== NULL
) {
1542 return EFI_OUT_OF_RESOURCES
;
1545 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1546 Private
->TextOutModeMap
= TextOutModeMap
;
1549 // If TextOutList has been enlarged, need to realloc the mode map table
1550 // The mode map table is regarded as a two dimension array.
1553 // 0 ---------> TextOutListCount ----> TextOutListCount
1554 // | -------------------------------------------
1561 // -------------------------------------------
1564 if (OldTextOutModeMap
!= NULL
) {
1566 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1568 SrcAddress
= OldTextOutModeMap
;
1571 // Copy the old data to the new one
1573 while (Index
< Private
->TextOutMode
.MaxMode
) {
1574 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1575 TextOutModeMap
+= NewSize
;
1580 // Free the old buffer
1582 FreePool (OldTextOutModeMap
);
1590 ConSplitterAddOutputMode (
1591 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1592 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1596 Routine Description:
1611 MaxMode
= TextOut
->Mode
->MaxMode
;
1612 Private
->TextOutMode
.MaxMode
= MaxMode
;
1615 // Grow the buffer if query data buffer is not large enough to
1616 // hold all the mode supported by the first console.
1618 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1619 Status
= ConSplitterGrowBuffer (
1620 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1621 &Private
->TextOutQueryDataCount
,
1622 (VOID
**) &Private
->TextOutQueryData
1624 if (EFI_ERROR (Status
)) {
1625 return EFI_OUT_OF_RESOURCES
;
1629 // Allocate buffer for the output mode map
1631 Status
= ConSplitterGrowMapTable (Private
);
1632 if (EFI_ERROR (Status
)) {
1633 return EFI_OUT_OF_RESOURCES
;
1636 // As the first textout device, directly add the mode in to QueryData
1637 // and at the same time record the mapping between QueryData and TextOut.
1641 while (Mode
< MaxMode
) {
1642 TextOut
->QueryMode (
1645 &Private
->TextOutQueryData
[Mode
].Columns
,
1646 &Private
->TextOutQueryData
[Mode
].Rows
1648 Private
->TextOutModeMap
[Index
] = Mode
;
1650 Index
+= Private
->TextOutListCount
;
1658 ConSplitterGetIntersection (
1659 IN INT32
*TextOutModeMap
,
1660 IN INT32
*NewlyAddedMap
,
1661 IN UINTN MapStepSize
,
1662 IN UINTN NewMapStepSize
,
1664 OUT INT32
*CurrentMode
1668 INT32
*CurrentMapEntry
;
1669 INT32
*NextMapEntry
;
1670 INT32 CurrentMaxMode
;
1674 CurrentMapEntry
= TextOutModeMap
;
1675 NextMapEntry
= TextOutModeMap
;
1676 CurrentMaxMode
= *MaxMode
;
1677 Mode
= *CurrentMode
;
1679 while (Index
< CurrentMaxMode
) {
1680 if (*NewlyAddedMap
== -1) {
1682 // This mode is not supported any more. Remove it. Special care
1683 // must be taken as this remove will also affect current mode;
1685 if (Index
== *CurrentMode
) {
1687 } else if (Index
< *CurrentMode
) {
1692 if (CurrentMapEntry
!= NextMapEntry
) {
1693 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1696 NextMapEntry
+= MapStepSize
;
1699 CurrentMapEntry
+= MapStepSize
;
1700 NewlyAddedMap
+= NewMapStepSize
;
1704 *CurrentMode
= Mode
;
1711 ConSplitterSyncOutputMode (
1712 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1713 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1717 Routine Description:
1720 Private - Private data structure.
1721 TextOut - Text Out Protocol.
1728 INT32 CurrentMaxMode
;
1731 INT32
*TextOutModeMap
;
1733 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1739 // Must make sure that current mode won't change even if mode number changes
1741 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1742 TextOutModeMap
= Private
->TextOutModeMap
;
1743 StepSize
= Private
->TextOutListCount
;
1744 TextOutQueryData
= Private
->TextOutQueryData
;
1747 // Query all the mode that the newly added TextOut supports
1750 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1751 while (Mode
< TextOut
->Mode
->MaxMode
) {
1752 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1755 // Search the QueryData database to see if they intersects
1758 while (Index
< CurrentMaxMode
) {
1759 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1760 MapTable
[Index
* StepSize
] = Mode
;
1770 // Now search the TextOutModeMap table to find the intersection of supported
1771 // mode between ConSplitter and the newly added device.
1773 ConSplitterGetIntersection (
1778 &Private
->TextOutMode
.MaxMode
,
1779 &Private
->TextOutMode
.Mode
1787 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1792 Routine Description:
1799 EFI_OUT_OF_RESOURCES
1803 UINTN ConOutNumOfConsoles
;
1804 UINTN StdErrNumOfConsoles
;
1805 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1806 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1811 INT32 ConOutMaxMode
;
1812 INT32 StdErrMaxMode
;
1815 INT32
*ConOutModeMap
;
1816 INT32
*StdErrModeMap
;
1817 INT32
*ConOutMapTable
;
1818 INT32
*StdErrMapTable
;
1819 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1820 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1821 BOOLEAN FoundTheSameTextOut
;
1822 UINTN ConOutMapTableSize
;
1823 UINTN StdErrMapTableSize
;
1825 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1826 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1827 ConOutTextOutList
= mConOut
.TextOutList
;
1828 StdErrTextOutList
= mStdErr
.TextOutList
;
1831 FoundTheSameTextOut
= FALSE
;
1832 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1834 while (Indexj
< StdErrNumOfConsoles
) {
1835 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1836 FoundTheSameTextOut
= TRUE
;
1841 StdErrTextOutList
++;
1845 ConOutTextOutList
++;
1848 if (!FoundTheSameTextOut
) {
1852 // Must make sure that current mode won't change even if mode number changes
1854 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1855 ConOutModeMap
= mConOut
.TextOutModeMap
;
1856 ConOutQueryData
= mConOut
.TextOutQueryData
;
1858 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1859 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1860 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1863 // Allocate the map table and set the map table's index to -1.
1865 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1866 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1867 if (ConOutMapTable
== NULL
) {
1868 return EFI_OUT_OF_RESOURCES
;
1871 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1873 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1874 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1875 if (StdErrMapTable
== NULL
) {
1876 return EFI_OUT_OF_RESOURCES
;
1879 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
1882 // Find the intersection of the two set of modes. If they actually intersect, the
1883 // correponding entry in the map table is set to 1.
1886 while (Mode
< ConOutMaxMode
) {
1888 // Search the other's QueryData database to see if they intersect
1891 Rows
= ConOutQueryData
[Mode
].Rows
;
1892 Columns
= ConOutQueryData
[Mode
].Columns
;
1893 while (Index
< StdErrMaxMode
) {
1894 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
1895 ConOutMapTable
[Mode
] = 1;
1896 StdErrMapTable
[Index
] = 1;
1906 // Now search the TextOutModeMap table to find the intersection of supported
1907 // mode between ConSplitter and the newly added device.
1909 ConSplitterGetIntersection (
1912 mConOut
.TextOutListCount
,
1914 &(mConOut
.TextOutMode
.MaxMode
),
1915 &(mConOut
.TextOutMode
.Mode
)
1917 if (mConOut
.TextOutMode
.Mode
< 0) {
1918 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
1921 ConSplitterGetIntersection (
1924 mStdErr
.TextOutListCount
,
1926 &(mStdErr
.TextOutMode
.MaxMode
),
1927 &(mStdErr
.TextOutMode
.Mode
)
1929 if (mStdErr
.TextOutMode
.Mode
< 0) {
1930 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
1933 FreePool (ConOutMapTable
);
1934 FreePool (StdErrMapTable
);
1941 ConSplitterAddGraphicsOutputMode (
1942 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1943 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1944 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1948 Routine Description:
1960 TEXT_OUT_GOP_MODE
*Mode
;
1962 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1963 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
1964 TEXT_OUT_GOP_MODE
*ModeBuffer
;
1965 TEXT_OUT_GOP_MODE
*MatchedMode
;
1969 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
1970 return EFI_UNSUPPORTED
;
1973 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
1975 if (GraphicsOutput
!= NULL
) {
1976 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
1978 // This is the first Graphics Output device added
1980 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
1981 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
1982 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
1983 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
1984 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
1985 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
1988 // Allocate resource for the private mode buffer
1990 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
1991 if (ModeBuffer
== NULL
) {
1992 return EFI_OUT_OF_RESOURCES
;
1994 FreePool (Private
->GraphicsOutputModeBuffer
);
1995 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
1998 // Store all supported display modes to the private mode buffer
2001 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2002 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2003 if (EFI_ERROR (Status
)) {
2006 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2007 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2013 // Check intersection of display mode
2015 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2016 if (ModeBuffer
== NULL
) {
2017 return EFI_OUT_OF_RESOURCES
;
2020 MatchedMode
= ModeBuffer
;
2021 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2022 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2025 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2026 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2027 if (EFI_ERROR (Status
)) {
2030 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2031 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2040 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2048 // Drop the old mode buffer, assign it to a new one
2050 FreePool (Private
->GraphicsOutputModeBuffer
);
2051 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2054 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2056 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2057 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2058 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2059 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2060 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2061 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2065 // Select a prefered Display mode 800x600
2067 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2068 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2069 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2074 // Prefered mode is not found, set to mode 0
2076 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2081 // Current mode number may need update now, so set it to an invalide mode number
2083 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2086 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2087 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2089 CurrentGraphicsOutputMode
->MaxMode
= 1;
2090 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2091 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2092 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2093 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2094 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2095 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2096 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2097 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2100 // Update the private mode buffer
2102 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2103 ModeBuffer
->HorizontalResolution
= 800;
2104 ModeBuffer
->VerticalResolution
= 600;
2107 // Current mode is unknow now, set it to an invalid mode number 0xffff
2109 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2114 // Force GraphicsOutput mode to be set,
2115 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2117 Private
->HardwareNeedsStarting
= TRUE
;
2118 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2120 Private
->CurrentNumberOfGraphicsOutput
++;
2126 ConSplitterTextOutAddDevice (
2127 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2128 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2129 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2130 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2134 Routine Description:
2145 UINTN CurrentNumOfConsoles
;
2148 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2150 Status
= EFI_SUCCESS
;
2151 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2154 // If the Text Out List is full, enlarge it by calling growbuffer().
2156 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2157 Status
= ConSplitterGrowBuffer (
2158 sizeof (TEXT_OUT_AND_GOP_DATA
),
2159 &Private
->TextOutListCount
,
2160 (VOID
**) &Private
->TextOutList
2162 if (EFI_ERROR (Status
)) {
2163 return EFI_OUT_OF_RESOURCES
;
2166 // Also need to reallocate the TextOutModeMap table
2168 Status
= ConSplitterGrowMapTable (Private
);
2169 if (EFI_ERROR (Status
)) {
2170 return EFI_OUT_OF_RESOURCES
;
2174 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2176 TextAndGop
->TextOut
= TextOut
;
2177 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2178 TextAndGop
->UgaDraw
= UgaDraw
;
2180 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2182 // If No UGA device then use the ConOut device
2184 TextAndGop
->TextOutEnabled
= TRUE
;
2187 // If UGA device use ConOut device only used if UGA screen is in Text mode
2189 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2192 if (CurrentNumOfConsoles
== 0) {
2194 // Add the first device's output mode to console splitter's mode list
2196 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2198 ConSplitterSyncOutputMode (Private
, TextOut
);
2201 Private
->CurrentNumberOfConsoles
++;
2204 // Scan both TextOutList, for the intersection TextOut device
2205 // maybe both ConOut and StdErr incorporate the same Text Out
2206 // device in them, thus the output of both should be synced.
2208 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2210 CurrentMode
= Private
->TextOutMode
.Mode
;
2211 MaxMode
= Private
->TextOutMode
.MaxMode
;
2212 ASSERT (MaxMode
>= 1);
2214 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2215 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2218 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2220 // We just added a new UGA device in graphics mode
2222 DevNullGopSync (Private
, GraphicsOutput
, UgaDraw
);
2223 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2225 // The new console supports the same mode of the current console so sync up
2227 DevNullSyncGopStdOut (Private
);
2230 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2232 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2239 ConSplitterTextOutDeleteDevice (
2240 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2241 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2245 Routine Description:
2256 UINTN CurrentNumOfConsoles
;
2257 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2261 // Remove the specified text-out device data structure from the Text out List,
2262 // and rearrange the remaining data structures in the Text out List.
2264 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2265 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2266 TextOutList
= Private
->TextOutList
;
2267 while (Index
>= 0) {
2268 if (TextOutList
->TextOut
== TextOut
) {
2269 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2270 CurrentNumOfConsoles
--;
2278 // The specified TextOut is not managed by the ConSplitter driver
2281 return EFI_NOT_FOUND
;
2284 if (CurrentNumOfConsoles
== 0) {
2286 // If the number of consoles is zero clear the Dev NULL device
2288 Private
->CurrentNumberOfConsoles
= 0;
2289 Private
->TextOutMode
.MaxMode
= 1;
2290 Private
->TextOutQueryData
[0].Columns
= 80;
2291 Private
->TextOutQueryData
[0].Rows
= 25;
2292 DevNullTextOutSetMode (Private
, 0);
2297 // Max Mode is realy an intersection of the QueryMode command to all
2298 // devices. So we must copy the QueryMode of the first device to
2302 Private
->TextOutQueryData
,
2303 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2306 FreePool (Private
->TextOutModeMap
);
2307 Private
->TextOutModeMap
= NULL
;
2308 TextOutList
= Private
->TextOutList
;
2311 // Add the first TextOut to the QueryData array and ModeMap table
2313 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2316 // Now add one by one
2319 Private
->CurrentNumberOfConsoles
= 1;
2321 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2322 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2324 Private
->CurrentNumberOfConsoles
++;
2328 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2333 // ConSplitter TextIn member functions
2337 ConSplitterTextInReset (
2338 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2339 IN BOOLEAN ExtendedVerification
2343 Routine Description:
2344 Reset the input device and optionaly run diagnostics
2347 This - Protocol instance pointer.
2348 ExtendedVerification - Driver may perform diagnostics on reset.
2351 EFI_SUCCESS - The device was reset.
2352 EFI_DEVICE_ERROR - The device is not functioning properly and could
2358 EFI_STATUS ReturnStatus
;
2359 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2362 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2364 Private
->KeyEventSignalState
= FALSE
;
2367 // return the worst status met
2369 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2370 Status
= Private
->TextInList
[Index
]->Reset (
2371 Private
->TextInList
[Index
],
2372 ExtendedVerification
2374 if (EFI_ERROR (Status
)) {
2375 ReturnStatus
= Status
;
2379 return ReturnStatus
;
2384 ConSplitterTextInPrivateReadKeyStroke (
2385 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2386 OUT EFI_INPUT_KEY
*Key
2390 Routine Description:
2391 Reads the next keystroke from the input device. The WaitForKey Event can
2392 be used to test for existance of a keystroke via WaitForEvent () call.
2395 This - Protocol instance pointer.
2396 Key - Driver may perform diagnostics on reset.
2399 EFI_SUCCESS - The keystroke information was returned.
2400 EFI_NOT_READY - There was no keystroke data availiable.
2401 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2408 EFI_INPUT_KEY CurrentKey
;
2410 Key
->UnicodeChar
= 0;
2411 Key
->ScanCode
= SCAN_NULL
;
2414 // if no physical console input device exists, return EFI_NOT_READY;
2415 // if any physical console input device has key input,
2416 // return the key and EFI_SUCCESS.
2418 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2419 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2420 Private
->TextInList
[Index
],
2423 if (!EFI_ERROR (Status
)) {
2429 return EFI_NOT_READY
;
2433 ConSpliterConssoleControlStdInLocked (
2438 Routine Description:
2439 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2440 the only device locked.
2447 FALSE - StdIn working normally
2451 return mConIn
.PasswordEnabled
;
2456 ConSpliterConsoleControlLockStdInEvent (
2462 Routine Description:
2463 This timer event will fire when StdIn is locked. It will check the key
2464 sequence on StdIn to see if it matches the password. Any error in the
2465 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2466 TRUE the StdIn splitter will not report any input.
2469 (Standard EFI_EVENT_NOTIFY)
2478 CHAR16 BackSpaceString
[2];
2479 CHAR16 SpaceString
[2];
2482 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2483 if (!EFI_ERROR (Status
)) {
2485 // if it's an ENTER, match password
2487 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2488 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2489 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2491 // Password not match
2493 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2494 mConIn
.PwdIndex
= 0;
2497 // Key matches password sequence
2499 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2500 mConIn
.PasswordEnabled
= FALSE
;
2501 Status
= EFI_NOT_READY
;
2503 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2507 if (mConIn
.PwdIndex
> 0) {
2508 BackSpaceString
[0] = CHAR_BACKSPACE
;
2509 BackSpaceString
[1] = 0;
2511 SpaceString
[0] = ' ';
2514 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2515 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2516 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2520 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2522 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2524 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2525 if (mConIn
.PwdIndex
== 0) {
2526 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2529 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2530 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2535 } while (!EFI_ERROR (Status
));
2540 ConSpliterConsoleControlLockStdIn (
2541 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2546 Routine Description:
2547 If Password is NULL unlock the password state variable and set the event
2548 timer. If the Password is too big return an error. If the Password is valid
2549 Copy the Password and enable state variable and then arm the periodic timer
2554 EFI_SUCCESS - Lock the StdIn device
2555 EFI_INVALID_PARAMETER - Password is NULL
2556 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2560 if (Password
== NULL
) {
2561 return EFI_INVALID_PARAMETER
;
2564 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2566 // Currently have a max password size
2568 return EFI_OUT_OF_RESOURCES
;
2571 // Save the password, initialize state variables and arm event timer
2573 StrCpy (mConIn
.Password
, Password
);
2574 mConIn
.PasswordEnabled
= TRUE
;
2575 mConIn
.PwdIndex
= 0;
2576 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2583 ConSplitterTextInReadKeyStroke (
2584 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2585 OUT EFI_INPUT_KEY
*Key
2589 Routine Description:
2590 Reads the next keystroke from the input device. The WaitForKey Event can
2591 be used to test for existance of a keystroke via WaitForEvent () call.
2592 If the ConIn is password locked make it look like no keystroke is availible
2595 This - Protocol instance pointer.
2596 Key - Driver may perform diagnostics on reset.
2599 EFI_SUCCESS - The keystroke information was returned.
2600 EFI_NOT_READY - There was no keystroke data availiable.
2601 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2606 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2608 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2609 if (Private
->PasswordEnabled
) {
2611 // If StdIn Locked return not ready
2613 return EFI_NOT_READY
;
2616 Private
->KeyEventSignalState
= FALSE
;
2618 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2623 ConSplitterTextInWaitForKey (
2629 Routine Description:
2630 This event agregates all the events of the ConIn devices in the spliter.
2631 If the ConIn is password locked then return.
2632 If any events of physical ConIn devices are signaled, signal the ConIn
2633 spliter event. This will cause the calling code to call
2634 ConSplitterTextInReadKeyStroke ().
2637 Event - The Event assoicated with callback.
2638 Context - Context registered when Event was created.
2646 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2649 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2650 if (Private
->PasswordEnabled
) {
2652 // If StdIn Locked return not ready
2658 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2660 if (Private
->KeyEventSignalState
) {
2661 gBS
->SignalEvent (Event
);
2665 // if any physical console input device has key input, signal the event.
2667 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2668 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2669 if (!EFI_ERROR (Status
)) {
2670 gBS
->SignalEvent (Event
);
2671 Private
->KeyEventSignalState
= TRUE
;
2678 ConSplitterSimplePointerReset (
2679 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2680 IN BOOLEAN ExtendedVerification
2684 Routine Description:
2685 Reset the input device and optionaly run diagnostics
2688 This - Protocol instance pointer.
2689 ExtendedVerification - Driver may perform diagnostics on reset.
2692 EFI_SUCCESS - The device was reset.
2693 EFI_DEVICE_ERROR - The device is not functioning properly and could
2699 EFI_STATUS ReturnStatus
;
2700 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2703 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2705 Private
->InputEventSignalState
= FALSE
;
2707 if (Private
->CurrentNumberOfPointers
== 0) {
2711 // return the worst status met
2713 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2714 Status
= Private
->PointerList
[Index
]->Reset (
2715 Private
->PointerList
[Index
],
2716 ExtendedVerification
2718 if (EFI_ERROR (Status
)) {
2719 ReturnStatus
= Status
;
2723 return ReturnStatus
;
2729 ConSplitterSimplePointerPrivateGetState (
2730 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2731 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2735 Routine Description:
2736 Reads the next keystroke from the input device. The WaitForKey Event can
2737 be used to test for existance of a keystroke via WaitForEvent () call.
2740 This - Protocol instance pointer.
2744 EFI_SUCCESS - The keystroke information was returned.
2745 EFI_NOT_READY - There was no keystroke data availiable.
2746 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2752 EFI_STATUS ReturnStatus
;
2754 EFI_SIMPLE_POINTER_STATE CurrentState
;
2756 State
->RelativeMovementX
= 0;
2757 State
->RelativeMovementY
= 0;
2758 State
->RelativeMovementZ
= 0;
2759 State
->LeftButton
= FALSE
;
2760 State
->RightButton
= FALSE
;
2763 // if no physical console input device exists, return EFI_NOT_READY;
2764 // if any physical console input device has key input,
2765 // return the key and EFI_SUCCESS.
2767 ReturnStatus
= EFI_NOT_READY
;
2768 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2770 Status
= Private
->PointerList
[Index
]->GetState (
2771 Private
->PointerList
[Index
],
2774 if (!EFI_ERROR (Status
)) {
2775 if (ReturnStatus
== EFI_NOT_READY
) {
2776 ReturnStatus
= EFI_SUCCESS
;
2779 if (CurrentState
.LeftButton
) {
2780 State
->LeftButton
= TRUE
;
2783 if (CurrentState
.RightButton
) {
2784 State
->RightButton
= TRUE
;
2787 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2788 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2791 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2792 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2795 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2796 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2798 } else if (Status
== EFI_DEVICE_ERROR
) {
2799 ReturnStatus
= EFI_DEVICE_ERROR
;
2803 return ReturnStatus
;
2808 ConSplitterSimplePointerGetState (
2809 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2810 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2814 Routine Description:
2815 Reads the next keystroke from the input device. The WaitForKey Event can
2816 be used to test for existance of a keystroke via WaitForEvent () call.
2817 If the ConIn is password locked make it look like no keystroke is availible
2820 This - Protocol instance pointer.
2824 EFI_SUCCESS - The keystroke information was returned.
2825 EFI_NOT_READY - There was no keystroke data availiable.
2826 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2831 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2833 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2834 if (Private
->PasswordEnabled
) {
2836 // If StdIn Locked return not ready
2838 return EFI_NOT_READY
;
2841 Private
->InputEventSignalState
= FALSE
;
2843 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2848 ConSplitterSimplePointerWaitForInput (
2854 Routine Description:
2855 This event agregates all the events of the ConIn devices in the spliter.
2856 If the ConIn is password locked then return.
2857 If any events of physical ConIn devices are signaled, signal the ConIn
2858 spliter event. This will cause the calling code to call
2859 ConSplitterTextInReadKeyStroke ().
2862 Event - The Event assoicated with callback.
2863 Context - Context registered when Event was created.
2871 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2874 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2875 if (Private
->PasswordEnabled
) {
2877 // If StdIn Locked return not ready
2883 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2885 if (Private
->InputEventSignalState
) {
2886 gBS
->SignalEvent (Event
);
2890 // if any physical console input device has key input, signal the event.
2892 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2893 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2894 if (!EFI_ERROR (Status
)) {
2895 gBS
->SignalEvent (Event
);
2896 Private
->InputEventSignalState
= TRUE
;
2903 ConSplitterTextOutReset (
2904 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2905 IN BOOLEAN ExtendedVerification
2909 Routine Description:
2910 Reset the text output device hardware and optionaly run diagnostics
2913 This - Protocol instance pointer.
2914 ExtendedVerification - Driver may perform more exhaustive verfication
2915 operation of the device during reset.
2918 EFI_SUCCESS - The text output device was reset.
2919 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2925 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2927 EFI_STATUS ReturnStatus
;
2929 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2932 // return the worst status met
2934 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2936 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2938 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2939 Private
->TextOutList
[Index
].TextOut
,
2940 ExtendedVerification
2942 if (EFI_ERROR (Status
)) {
2943 ReturnStatus
= Status
;
2948 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2950 Status
= DevNullTextOutSetMode (Private
, 0);
2951 if (EFI_ERROR (Status
)) {
2952 ReturnStatus
= Status
;
2955 return ReturnStatus
;
2960 ConSplitterTextOutOutputString (
2961 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2966 Routine Description:
2967 Write a Unicode string to the output device.
2970 This - Protocol instance pointer.
2971 String - The NULL-terminated Unicode string to be displayed on the output
2972 device(s). All output devices must also support the Unicode
2973 drawing defined in this file.
2976 EFI_SUCCESS - The string was output to the device.
2977 EFI_DEVICE_ERROR - The device reported an error while attempting to output
2979 EFI_UNSUPPORTED - The output device's mode is not currently in a
2981 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
2982 characters in the Unicode string could not be
2983 rendered and were skipped.
2988 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2990 UINTN BackSpaceCount
;
2991 EFI_STATUS ReturnStatus
;
2992 CHAR16
*TargetString
;
2994 This
->SetAttribute (This
, This
->Mode
->Attribute
);
2996 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2999 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3000 if (*TargetString
== CHAR_BACKSPACE
) {
3006 if (BackSpaceCount
== 0) {
3007 TargetString
= WString
;
3009 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3010 StrCpy (TargetString
, WString
);
3013 // return the worst status met
3015 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3016 if (EFI_ERROR (Status
)) {
3017 ReturnStatus
= Status
;
3020 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3022 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3023 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3024 Private
->TextOutList
[Index
].TextOut
,
3027 if (EFI_ERROR (Status
)) {
3028 ReturnStatus
= Status
;
3033 if (BackSpaceCount
) {
3034 FreePool (TargetString
);
3037 return ReturnStatus
;
3042 ConSplitterTextOutTestString (
3043 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3048 Routine Description:
3049 Verifies that all characters in a Unicode string can be output to the
3053 This - Protocol instance pointer.
3054 String - The NULL-terminated Unicode string to be examined for the output
3058 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3059 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3060 rendered by one or more of the output devices mapped
3066 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3068 EFI_STATUS ReturnStatus
;
3070 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3073 // return the worst status met
3075 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3076 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3077 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3078 Private
->TextOutList
[Index
].TextOut
,
3081 if (EFI_ERROR (Status
)) {
3082 ReturnStatus
= Status
;
3087 // There is no DevNullTextOutTestString () since a Unicode buffer would
3088 // always return EFI_SUCCESS.
3089 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3091 return ReturnStatus
;
3096 ConSplitterTextOutQueryMode (
3097 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3098 IN UINTN ModeNumber
,
3104 Routine Description:
3105 Returns information for an available text mode that the output device(s)
3109 This - Protocol instance pointer.
3110 ModeNumber - The mode number to return information on.
3111 Columns, Rows - Returns the geometry of the text output device for the
3112 requested ModeNumber.
3115 EFI_SUCCESS - The requested mode information was returned.
3116 EFI_DEVICE_ERROR - The device had an error and could not
3117 complete the request.
3118 EFI_UNSUPPORTED - The mode number was not valid.
3122 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3124 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3127 // Check whether param ModeNumber is valid.
3128 // ModeNumber should be within range 0 ~ MaxMode - 1.
3130 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3131 return EFI_UNSUPPORTED
;
3134 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3135 return EFI_UNSUPPORTED
;
3138 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3139 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3141 if (*Columns
<= 0 && *Rows
<= 0) {
3142 return EFI_UNSUPPORTED
;
3151 ConSplitterTextOutSetMode (
3152 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3157 Routine Description:
3158 Sets the output device(s) to a specified mode.
3161 This - Protocol instance pointer.
3162 ModeNumber - The mode number to set.
3165 EFI_SUCCESS - The requested text mode was set.
3166 EFI_DEVICE_ERROR - The device had an error and
3167 could not complete the request.
3168 EFI_UNSUPPORTED - The mode number was not valid.
3173 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3175 INT32
*TextOutModeMap
;
3176 EFI_STATUS ReturnStatus
;
3178 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3181 // Check whether param ModeNumber is valid.
3182 // ModeNumber should be within range 0 ~ MaxMode - 1.
3184 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3185 return EFI_UNSUPPORTED
;
3188 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3189 return EFI_UNSUPPORTED
;
3192 // If the mode is being set to the curent mode, then just clear the screen and return.
3194 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3195 return ConSplitterTextOutClearScreen (This
);
3198 // return the worst status met
3200 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3201 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3203 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3204 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3205 Private
->TextOutList
[Index
].TextOut
,
3206 TextOutModeMap
[Index
]
3209 // If this console device is based on a UGA device, then sync up the bitmap from
3210 // the UGA splitter and reclear the text portion of the display in the new mode.
3212 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3213 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3216 if (EFI_ERROR (Status
)) {
3217 ReturnStatus
= Status
;
3222 // The DevNull Console will support any possible mode as it allocates memory
3224 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3225 if (EFI_ERROR (Status
)) {
3226 ReturnStatus
= Status
;
3229 return ReturnStatus
;
3234 ConSplitterTextOutSetAttribute (
3235 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3240 Routine Description:
3241 Sets the background and foreground colors for the OutputString () and
3242 ClearScreen () functions.
3245 This - Protocol instance pointer.
3246 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3247 bits 4..6 are the background color. All other bits are undefined
3248 and must be zero. The valid Attributes are defined in this file.
3251 EFI_SUCCESS - The attribute was set.
3252 EFI_DEVICE_ERROR - The device had an error and
3253 could not complete the request.
3254 EFI_UNSUPPORTED - The attribute requested is not defined.
3259 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3261 EFI_STATUS ReturnStatus
;
3263 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3266 // Check whether param Attribute is valid.
3268 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3269 return EFI_UNSUPPORTED
;
3273 // return the worst status met
3275 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3277 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3278 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3279 Private
->TextOutList
[Index
].TextOut
,
3282 if (EFI_ERROR (Status
)) {
3283 ReturnStatus
= Status
;
3288 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3290 return ReturnStatus
;
3295 ConSplitterTextOutClearScreen (
3296 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3300 Routine Description:
3301 Clears the output device(s) display to the currently selected background
3305 This - Protocol instance pointer.
3308 EFI_SUCCESS - The operation completed successfully.
3309 EFI_DEVICE_ERROR - The device had an error and
3310 could not complete the request.
3311 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3316 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3318 EFI_STATUS ReturnStatus
;
3320 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3323 // return the worst status met
3325 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3327 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3328 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3329 if (EFI_ERROR (Status
)) {
3330 ReturnStatus
= Status
;
3335 Status
= DevNullTextOutClearScreen (Private
);
3336 if (EFI_ERROR (Status
)) {
3337 ReturnStatus
= Status
;
3340 return ReturnStatus
;
3345 ConSplitterTextOutSetCursorPosition (
3346 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3352 Routine Description:
3353 Sets the current coordinates of the cursor position
3356 This - Protocol instance pointer.
3357 Column, Row - the position to set the cursor to. Must be greater than or
3358 equal to zero and less than the number of columns and rows
3362 EFI_SUCCESS - The operation completed successfully.
3363 EFI_DEVICE_ERROR - The device had an error and
3364 could not complete the request.
3365 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3366 cursor position is invalid for the current mode.
3371 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3373 EFI_STATUS ReturnStatus
;
3377 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3379 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3380 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3382 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3383 return EFI_UNSUPPORTED
;
3386 // return the worst status met
3388 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3390 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3391 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3392 Private
->TextOutList
[Index
].TextOut
,
3396 if (EFI_ERROR (Status
)) {
3397 ReturnStatus
= Status
;
3402 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3404 return ReturnStatus
;
3409 ConSplitterTextOutEnableCursor (
3410 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3415 Routine Description:
3416 Makes the cursor visible or invisible
3419 This - Protocol instance pointer.
3420 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3421 set to be invisible.
3424 EFI_SUCCESS - The operation completed successfully.
3425 EFI_DEVICE_ERROR - The device had an error and could not complete the
3426 request, or the device does not support changing
3428 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3433 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3435 EFI_STATUS ReturnStatus
;
3437 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3440 // return the worst status met
3442 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3444 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3445 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3446 Private
->TextOutList
[Index
].TextOut
,
3449 if (EFI_ERROR (Status
)) {
3450 ReturnStatus
= Status
;
3455 DevNullTextOutEnableCursor (Private
, Visible
);
3457 return ReturnStatus
;