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.
31 // Include common header file for this module.
33 #include "CommonHeader.h"
35 #include "ConSplitter.h"
40 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
41 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
44 ConSplitterTextInReset
,
45 ConSplitterTextInReadKeyStroke
,
49 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
53 ConSplitterSimplePointerReset
,
54 ConSplitterSimplePointerGetState
,
56 (EFI_SIMPLE_POINTER_MODE
*) NULL
66 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 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
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
89 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
90 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
93 ConSplitterTextOutReset
,
94 ConSplitterTextOutOutputString
,
95 ConSplitterTextOutTestString
,
96 ConSplitterTextOutQueryMode
,
97 ConSplitterTextOutSetMode
,
98 ConSplitterTextOutSetAttribute
,
99 ConSplitterTextOutClearScreen
,
100 ConSplitterTextOutSetCursorPosition
,
101 ConSplitterTextOutEnableCursor
,
102 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
113 ConSpliterGraphicsOutputQueryMode
,
114 ConSpliterGraphicsOutputSetMode
,
115 ConSpliterGraphicsOutputBlt
,
118 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
119 (TEXT_OUT_GOP_MODE
*) NULL
,
123 ConSpliterConsoleControlGetMode
,
124 ConSpliterConsoleControlSetMode
,
125 ConSpliterConsoleControlLockStdIn
129 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
131 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
135 EfiConsoleControlScreenText
,
142 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
143 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
146 ConSplitterTextOutReset
,
147 ConSplitterTextOutOutputString
,
148 ConSplitterTextOutTestString
,
149 ConSplitterTextOutQueryMode
,
150 ConSplitterTextOutSetMode
,
151 ConSplitterTextOutSetAttribute
,
152 ConSplitterTextOutClearScreen
,
153 ConSplitterTextOutSetCursorPosition
,
154 ConSplitterTextOutEnableCursor
,
155 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
166 ConSpliterGraphicsOutputQueryMode
,
167 ConSpliterGraphicsOutputSetMode
,
168 ConSpliterGraphicsOutputBlt
,
171 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
172 (TEXT_OUT_GOP_MODE
*) NULL
,
176 ConSpliterConsoleControlGetMode
,
177 ConSpliterConsoleControlSetMode
,
178 ConSpliterConsoleControlLockStdIn
182 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
184 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
188 EfiConsoleControlScreenText
,
195 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
196 ConSplitterConInDriverBindingSupported
,
197 ConSplitterConInDriverBindingStart
,
198 ConSplitterConInDriverBindingStop
,
204 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
205 ConSplitterSimplePointerDriverBindingSupported
,
206 ConSplitterSimplePointerDriverBindingStart
,
207 ConSplitterSimplePointerDriverBindingStop
,
213 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
214 ConSplitterConOutDriverBindingSupported
,
215 ConSplitterConOutDriverBindingStart
,
216 ConSplitterConOutDriverBindingStop
,
222 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
223 ConSplitterStdErrDriverBindingSupported
,
224 ConSplitterStdErrDriverBindingStart
,
225 ConSplitterStdErrDriverBindingStop
,
232 The user Entry Point for module ConSplitter. The user code starts with this function.
234 @param[in] ImageHandle The firmware allocated handle for the EFI image.
235 @param[in] SystemTable A pointer to the EFI System Table.
237 @retval EFI_SUCCESS The entry point is executed successfully.
238 @retval other Some error occurs when executing this entry point.
243 InitializeConSplitter(
244 IN EFI_HANDLE ImageHandle
,
245 IN EFI_SYSTEM_TABLE
*SystemTable
251 // Install driver model protocol(s).
253 Status
= EfiLibInstallAllDriverProtocols (
256 &gConSplitterConInDriverBinding
,
258 &gConSplitterConInComponentName
,
262 ASSERT_EFI_ERROR (Status
);
264 Status
= EfiLibInstallAllDriverProtocols (
267 &gConSplitterSimplePointerDriverBinding
,
269 &gConSplitterSimplePointerComponentName
,
273 ASSERT_EFI_ERROR (Status
);
275 Status
= EfiLibInstallAllDriverProtocols (
278 &gConSplitterConOutDriverBinding
,
280 &gConSplitterConOutComponentName
,
284 ASSERT_EFI_ERROR (Status
);
286 Status
= EfiLibInstallAllDriverProtocols (
289 &gConSplitterStdErrDriverBinding
,
291 &gConSplitterStdErrComponentName
,
295 ASSERT_EFI_ERROR (Status
);
299 // Call the original Entry Point
301 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
309 ConSplitterDriverEntry (
310 IN EFI_HANDLE ImageHandle
,
311 IN EFI_SYSTEM_TABLE
*SystemTable
316 Intialize a virtual console device to act as an agrigator of physical console
320 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
321 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
330 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
331 // The virtual handles will always exist even if no console exist in the
332 // system. This is need to support hotplug devices like USB.
335 // Create virtual device handle for StdErr Splitter
337 Status
= ConSplitterTextOutConstructor (&mStdErr
);
338 if (!EFI_ERROR (Status
)) {
339 Status
= gBS
->InstallMultipleProtocolInterfaces (
340 &mStdErr
.VirtualHandle
,
341 &gEfiSimpleTextOutProtocolGuid
,
343 &gEfiPrimaryStandardErrorDeviceGuid
,
349 // Create virtual device handle for ConIn Splitter
351 Status
= ConSplitterTextInConstructor (&mConIn
);
352 if (!EFI_ERROR (Status
)) {
353 Status
= gBS
->InstallMultipleProtocolInterfaces (
354 &mConIn
.VirtualHandle
,
355 &gEfiSimpleTextInProtocolGuid
,
357 &gEfiSimplePointerProtocolGuid
,
358 &mConIn
.SimplePointer
,
359 &gEfiPrimaryConsoleInDeviceGuid
,
363 if (!EFI_ERROR (Status
)) {
365 // Update the EFI System Table with new virtual console
367 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
368 gST
->ConIn
= &mConIn
.TextIn
;
372 // Create virtual device handle for ConOut Splitter
374 Status
= ConSplitterTextOutConstructor (&mConOut
);
375 if (!EFI_ERROR (Status
)) {
377 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
379 Status
= gBS
->InstallMultipleProtocolInterfaces (
380 &mConOut
.VirtualHandle
,
381 &gEfiSimpleTextOutProtocolGuid
,
383 &gEfiGraphicsOutputProtocolGuid
,
384 &mConOut
.GraphicsOutput
,
385 &gEfiConsoleControlProtocolGuid
,
386 &mConOut
.ConsoleControl
,
387 &gEfiPrimaryConsoleOutDeviceGuid
,
392 if (!EFI_ERROR (Status
)) {
394 // Update the EFI System Table with new virtual console
396 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
397 gST
->ConOut
= &mConOut
.TextOut
;
402 // Update the CRC32 in the EFI System Table header
405 gBS
->CalculateCrc32 (
415 ConSplitterTextInConstructor (
416 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
422 Construct the ConSplitter.
426 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
429 EFI_OUT_OF_RESOURCES - Out of resources.
436 // Initilize console input splitter's private data.
438 Status
= ConSplitterGrowBuffer (
439 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
440 &ConInPrivate
->TextInListCount
,
441 (VOID
**) &ConInPrivate
->TextInList
443 if (EFI_ERROR (Status
)) {
444 return EFI_OUT_OF_RESOURCES
;
447 // Create Event to support locking StdIn Device
449 Status
= gBS
->CreateEvent (
450 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
452 ConSpliterConsoleControlLockStdInEvent
,
454 &ConInPrivate
->LockEvent
456 ASSERT_EFI_ERROR (Status
);
458 Status
= gBS
->CreateEvent (
461 ConSplitterTextInWaitForKey
,
463 &ConInPrivate
->TextIn
.WaitForKey
465 ASSERT_EFI_ERROR (Status
);
467 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
469 Status
= ConSplitterGrowBuffer (
470 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
471 &ConInPrivate
->PointerListCount
,
472 (VOID
**) &ConInPrivate
->PointerList
474 if (EFI_ERROR (Status
)) {
475 return EFI_OUT_OF_RESOURCES
;
478 Status
= gBS
->CreateEvent (
481 ConSplitterSimplePointerWaitForInput
,
483 &ConInPrivate
->SimplePointer
.WaitForInput
490 ConSplitterTextOutConstructor (
491 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
497 // Initilize console output splitter's private data.
499 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
501 Status
= ConSplitterGrowBuffer (
502 sizeof (TEXT_OUT_AND_GOP_DATA
),
503 &ConOutPrivate
->TextOutListCount
,
504 (VOID
**) &ConOutPrivate
->TextOutList
506 if (EFI_ERROR (Status
)) {
507 return EFI_OUT_OF_RESOURCES
;
510 Status
= ConSplitterGrowBuffer (
511 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
512 &ConOutPrivate
->TextOutQueryDataCount
,
513 (VOID
**) &ConOutPrivate
->TextOutQueryData
515 if (EFI_ERROR (Status
)) {
516 return EFI_OUT_OF_RESOURCES
;
519 // Setup the DevNullTextOut console to 80 x 25
521 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
522 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
523 DevNullTextOutSetMode (ConOutPrivate
, 0);
526 // Setup resource for mode information in Graphics Output Protocol interface
528 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
529 return EFI_OUT_OF_RESOURCES
;
531 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
532 return EFI_OUT_OF_RESOURCES
;
535 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
537 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
538 return EFI_OUT_OF_RESOURCES
;
540 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
541 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
544 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
545 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
546 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
548 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
549 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
550 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
551 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
552 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
554 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
556 // Initial current mode to unknow state, and then set to mode 0
558 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
559 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
566 ConSplitterSupported (
567 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
568 IN EFI_HANDLE ControllerHandle
,
574 Generic Supported Check
577 This - Pointer to protocol.
578 ControllerHandle - Controller Handle.
583 EFI_UNSUPPORTED - unsupported.
584 EFI_SUCCESS - operation is OK.
592 // Make sure the Console Splitter does not attempt to attach to itself
594 if (ControllerHandle
== mConIn
.VirtualHandle
) {
595 return EFI_UNSUPPORTED
;
598 if (ControllerHandle
== mConOut
.VirtualHandle
) {
599 return EFI_UNSUPPORTED
;
602 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
603 return EFI_UNSUPPORTED
;
606 // Check to see whether the handle has the ConsoleInDevice GUID on it
608 Status
= gBS
->OpenProtocol (
612 This
->DriverBindingHandle
,
614 EFI_OPEN_PROTOCOL_BY_DRIVER
617 if (EFI_ERROR (Status
)) {
624 This
->DriverBindingHandle
,
633 ConSplitterConInDriverBindingSupported (
634 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
635 IN EFI_HANDLE ControllerHandle
,
636 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
641 Console In Supported Check
644 This - Pointer to protocol.
645 ControllerHandle - Controller handle.
646 RemainingDevicePath - Remaining device path.
654 return ConSplitterSupported (
657 &gEfiConsoleInDeviceGuid
663 ConSplitterSimplePointerDriverBindingSupported (
664 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
665 IN EFI_HANDLE ControllerHandle
,
666 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
671 Standard Error Supported Check
674 This - Pointer to protocol.
675 ControllerHandle - Controller handle.
676 RemainingDevicePath - Remaining device path.
684 return ConSplitterSupported (
687 &gEfiSimplePointerProtocolGuid
693 ConSplitterConOutDriverBindingSupported (
694 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
695 IN EFI_HANDLE ControllerHandle
,
696 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
701 Console Out Supported Check
704 This - Pointer to protocol.
705 ControllerHandle - Controller handle.
706 RemainingDevicePath - Remaining device path.
714 return ConSplitterSupported (
717 &gEfiConsoleOutDeviceGuid
723 ConSplitterStdErrDriverBindingSupported (
724 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
725 IN EFI_HANDLE ControllerHandle
,
726 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
731 Standard Error Supported Check
734 This - Pointer to protocol.
735 ControllerHandle - Controller handle.
736 RemainingDevicePath - Remaining device path.
744 return ConSplitterSupported (
747 &gEfiStandardErrorDeviceGuid
755 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
756 IN EFI_HANDLE ControllerHandle
,
757 IN EFI_HANDLE ConSplitterVirtualHandle
,
758 IN EFI_GUID
*DeviceGuid
,
759 IN EFI_GUID
*InterfaceGuid
,
765 Start ConSplitter on ControllerHandle, and create the virtual
766 agrogated console device on first call Start for a SimpleTextIn handle.
769 (Standard DriverBinding Protocol Start() function)
772 EFI_ERROR if a SimpleTextIn protocol is not started.
780 // Check to see whether the handle has the ConsoleInDevice GUID on it
782 Status
= gBS
->OpenProtocol (
786 This
->DriverBindingHandle
,
788 EFI_OPEN_PROTOCOL_BY_DRIVER
790 if (EFI_ERROR (Status
)) {
794 Status
= gBS
->OpenProtocol (
798 This
->DriverBindingHandle
,
799 ConSplitterVirtualHandle
,
800 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
802 if (EFI_ERROR (Status
)) {
806 return gBS
->OpenProtocol (
810 This
->DriverBindingHandle
,
811 ConSplitterVirtualHandle
,
812 EFI_OPEN_PROTOCOL_GET_PROTOCOL
818 ConSplitterConInDriverBindingStart (
819 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
820 IN EFI_HANDLE ControllerHandle
,
821 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
826 Start ConSplitter on ControllerHandle, and create the virtual
827 agrogated console device on first call Start for a SimpleTextIn handle.
830 This - Pointer to protocol.
831 ControllerHandle - Controller handle.
832 RemainingDevicePath - Remaining device path.
837 EFI_ERROR if a SimpleTextIn protocol is not started.
842 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
845 // Start ConSplitter on ControllerHandle, and create the virtual
846 // agrogated console device on first call Start for a SimpleTextIn handle.
848 Status
= ConSplitterStart (
851 mConIn
.VirtualHandle
,
852 &gEfiConsoleInDeviceGuid
,
853 &gEfiSimpleTextInProtocolGuid
,
856 if (EFI_ERROR (Status
)) {
860 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
865 ConSplitterSimplePointerDriverBindingStart (
866 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
867 IN EFI_HANDLE ControllerHandle
,
868 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
873 Start ConSplitter on ControllerHandle, and create the virtual
874 agrogated console device on first call Start for a SimpleTextIn handle.
877 This - Pointer to protocol.
878 ControllerHandle - Controller handle.
879 RemainingDevicePath - Remaining device path.
883 EFI_ERROR if a SimpleTextIn protocol is not started.
888 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
890 Status
= ConSplitterStart (
893 mConIn
.VirtualHandle
,
894 &gEfiSimplePointerProtocolGuid
,
895 &gEfiSimplePointerProtocolGuid
,
896 (VOID
**) &SimplePointer
898 if (EFI_ERROR (Status
)) {
902 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
907 ConSplitterConOutDriverBindingStart (
908 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
909 IN EFI_HANDLE ControllerHandle
,
910 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
915 Start ConSplitter on ControllerHandle, and create the virtual
916 agrogated console device on first call Start for a SimpleTextIn handle.
919 This - Pointer to protocol.
920 ControllerHandle - Controller handle.
921 RemainingDevicePath - Remaining device path.
924 EFI_ERROR if a SimpleTextIn protocol is not started.
929 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
930 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
931 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
933 Status
= ConSplitterStart (
936 mConOut
.VirtualHandle
,
937 &gEfiConsoleOutDeviceGuid
,
938 &gEfiSimpleTextOutProtocolGuid
,
941 if (EFI_ERROR (Status
)) {
945 // Try to Open Graphics Output protocol
947 Status
= gBS
->OpenProtocol (
949 &gEfiGraphicsOutputProtocolGuid
,
950 (VOID
**) &GraphicsOutput
,
951 This
->DriverBindingHandle
,
952 mConOut
.VirtualHandle
,
953 EFI_OPEN_PROTOCOL_GET_PROTOCOL
955 if (EFI_ERROR (Status
)) {
956 GraphicsOutput
= NULL
;
959 // Open UGA_DRAW protocol
961 Status
= gBS
->OpenProtocol (
963 &gEfiUgaDrawProtocolGuid
,
965 This
->DriverBindingHandle
,
966 mConOut
.VirtualHandle
,
967 EFI_OPEN_PROTOCOL_GET_PROTOCOL
969 if (EFI_ERROR (Status
)) {
973 // If both ConOut and StdErr incorporate the same Text Out device,
974 // their MaxMode and QueryData should be the intersection of both.
976 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
977 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
984 ConSplitterStdErrDriverBindingStart (
985 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
986 IN EFI_HANDLE ControllerHandle
,
987 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
992 Start ConSplitter on ControllerHandle, and create the virtual
993 agrogated console device on first call Start for a SimpleTextIn handle.
996 This - Pointer to protocol.
997 ControllerHandle - Controller handle.
998 RemainingDevicePath - Remaining device path.
1001 EFI_ERROR if a SimpleTextIn protocol is not started.
1006 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1008 Status
= ConSplitterStart (
1011 mStdErr
.VirtualHandle
,
1012 &gEfiStandardErrorDeviceGuid
,
1013 &gEfiSimpleTextOutProtocolGuid
,
1016 if (EFI_ERROR (Status
)) {
1020 // If both ConOut and StdErr incorporate the same Text Out device,
1021 // their MaxMode and QueryData should be the intersection of both.
1023 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1024 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1025 if (EFI_ERROR (Status
)) {
1029 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1030 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1031 gST
->StdErr
= &mStdErr
.TextOut
;
1033 // Update the CRC32 in the EFI System Table header
1036 gBS
->CalculateCrc32 (
1037 (UINT8
*) &gST
->Hdr
,
1038 gST
->Hdr
.HeaderSize
,
1050 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1051 IN EFI_HANDLE ControllerHandle
,
1052 IN EFI_HANDLE ConSplitterVirtualHandle
,
1053 IN EFI_GUID
*DeviceGuid
,
1054 IN EFI_GUID
*InterfaceGuid
,
1059 Routine Description:
1062 (Standard DriverBinding Protocol Stop() function)
1072 Status
= gBS
->OpenProtocol (
1076 This
->DriverBindingHandle
,
1078 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1080 if (EFI_ERROR (Status
)) {
1084 // close the protocol refered.
1086 gBS
->CloseProtocol (
1089 This
->DriverBindingHandle
,
1090 ConSplitterVirtualHandle
1092 gBS
->CloseProtocol (
1095 This
->DriverBindingHandle
,
1104 ConSplitterConInDriverBindingStop (
1105 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1106 IN EFI_HANDLE ControllerHandle
,
1107 IN UINTN NumberOfChildren
,
1108 IN EFI_HANDLE
*ChildHandleBuffer
1112 Routine Description:
1115 (Standard DriverBinding Protocol Stop() function)
1124 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1126 if (NumberOfChildren
== 0) {
1130 Status
= ConSplitterStop (
1133 mConIn
.VirtualHandle
,
1134 &gEfiConsoleInDeviceGuid
,
1135 &gEfiSimpleTextInProtocolGuid
,
1138 if (EFI_ERROR (Status
)) {
1142 // Delete this console input device's data structures.
1144 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1149 ConSplitterSimplePointerDriverBindingStop (
1150 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1151 IN EFI_HANDLE ControllerHandle
,
1152 IN UINTN NumberOfChildren
,
1153 IN EFI_HANDLE
*ChildHandleBuffer
1157 Routine Description:
1160 (Standard DriverBinding Protocol Stop() function)
1169 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1171 if (NumberOfChildren
== 0) {
1175 Status
= ConSplitterStop (
1178 mConIn
.VirtualHandle
,
1179 &gEfiSimplePointerProtocolGuid
,
1180 &gEfiSimplePointerProtocolGuid
,
1181 (VOID
**) &SimplePointer
1183 if (EFI_ERROR (Status
)) {
1187 // Delete this console input device's data structures.
1189 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1194 ConSplitterConOutDriverBindingStop (
1195 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1196 IN EFI_HANDLE ControllerHandle
,
1197 IN UINTN NumberOfChildren
,
1198 IN EFI_HANDLE
*ChildHandleBuffer
1202 Routine Description:
1205 (Standard DriverBinding Protocol Stop() function)
1214 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1216 if (NumberOfChildren
== 0) {
1220 Status
= ConSplitterStop (
1223 mConOut
.VirtualHandle
,
1224 &gEfiConsoleOutDeviceGuid
,
1225 &gEfiSimpleTextOutProtocolGuid
,
1228 if (EFI_ERROR (Status
)) {
1233 // Delete this console output device's data structures.
1235 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1240 ConSplitterStdErrDriverBindingStop (
1241 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1242 IN EFI_HANDLE ControllerHandle
,
1243 IN UINTN NumberOfChildren
,
1244 IN EFI_HANDLE
*ChildHandleBuffer
1248 Routine Description:
1251 (Standard DriverBinding Protocol Stop() function)
1255 EFI_SUCCESS - Complete successfully.
1260 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1262 if (NumberOfChildren
== 0) {
1266 Status
= ConSplitterStop (
1269 mStdErr
.VirtualHandle
,
1270 &gEfiStandardErrorDeviceGuid
,
1271 &gEfiSimpleTextOutProtocolGuid
,
1274 if (EFI_ERROR (Status
)) {
1278 // Delete this console error out device's data structures.
1280 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1281 if (EFI_ERROR (Status
)) {
1285 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1286 gST
->StandardErrorHandle
= NULL
;
1289 // Update the CRC32 in the EFI System Table header
1292 gBS
->CalculateCrc32 (
1293 (UINT8
*) &gST
->Hdr
,
1294 gST
->Hdr
.HeaderSize
,
1303 ConSplitterGrowBuffer (
1304 IN UINTN SizeOfCount
,
1306 IN OUT VOID
**Buffer
1310 Routine Description:
1311 Take the passed in Buffer of size SizeOfCount and grow the buffer
1312 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1313 bytes. Copy the current data in Buffer to the new version of Buffer
1314 and free the old version of buffer.
1318 SizeOfCount - Size of element in array
1319 Count - Current number of elements in array
1320 Buffer - Bigger version of passed in Buffer with all the data
1323 EFI_SUCCESS - Buffer size has grown
1324 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1335 // grow the buffer to new buffer size,
1336 // copy the old buffer's content to the new-size buffer,
1337 // then free the old buffer.
1339 OldSize
= *Count
* SizeOfCount
;
1340 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1341 NewSize
= *Count
* SizeOfCount
;
1343 Ptr
= AllocateZeroPool (NewSize
);
1345 return EFI_OUT_OF_RESOURCES
;
1348 CopyMem (Ptr
, *Buffer
, OldSize
);
1350 if (*Buffer
!= NULL
) {
1360 ConSplitterTextInAddDevice (
1361 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1362 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1366 Routine Description:
1373 EFI_OUT_OF_RESOURCES
1380 // If the Text In List is full, enlarge it by calling growbuffer().
1382 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1383 Status
= ConSplitterGrowBuffer (
1384 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1385 &Private
->TextInListCount
,
1386 (VOID
**) &Private
->TextInList
1388 if (EFI_ERROR (Status
)) {
1389 return EFI_OUT_OF_RESOURCES
;
1393 // Add the new text-in device data structure into the Text In List.
1395 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1396 Private
->CurrentNumberOfConsoles
++;
1399 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1401 gBS
->CheckEvent (TextIn
->WaitForKey
);
1407 ConSplitterTextInDeleteDevice (
1408 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1409 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1413 Routine Description:
1426 // Remove the specified text-in device data structure from the Text In List,
1427 // and rearrange the remaining data structures in the Text In List.
1429 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1430 if (Private
->TextInList
[Index
] == TextIn
) {
1431 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1432 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1435 Private
->CurrentNumberOfConsoles
--;
1440 return EFI_NOT_FOUND
;
1444 ConSplitterSimplePointerAddDevice (
1445 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1446 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1450 Routine Description:
1456 EFI_OUT_OF_RESOURCES
1464 // If the Text In List is full, enlarge it by calling growbuffer().
1466 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1467 Status
= ConSplitterGrowBuffer (
1468 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1469 &Private
->PointerListCount
,
1470 (VOID
**) &Private
->PointerList
1472 if (EFI_ERROR (Status
)) {
1473 return EFI_OUT_OF_RESOURCES
;
1477 // Add the new text-in device data structure into the Text In List.
1479 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1480 Private
->CurrentNumberOfPointers
++;
1485 ConSplitterSimplePointerDeleteDevice (
1486 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1487 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1491 Routine Description:
1503 // Remove the specified text-in device data structure from the Text In List,
1504 // and rearrange the remaining data structures in the Text In List.
1506 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1507 if (Private
->PointerList
[Index
] == SimplePointer
) {
1508 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1509 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1512 Private
->CurrentNumberOfPointers
--;
1517 return EFI_NOT_FOUND
;
1522 ConSplitterGrowMapTable (
1523 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1527 Routine Description:
1540 INT32
*TextOutModeMap
;
1541 INT32
*OldTextOutModeMap
;
1545 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1546 OldTextOutModeMap
= Private
->TextOutModeMap
;
1547 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1549 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1550 if (TextOutModeMap
== NULL
) {
1551 return EFI_OUT_OF_RESOURCES
;
1554 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1555 Private
->TextOutModeMap
= TextOutModeMap
;
1558 // If TextOutList has been enlarged, need to realloc the mode map table
1559 // The mode map table is regarded as a two dimension array.
1562 // 0 ---------> TextOutListCount ----> TextOutListCount
1563 // | -------------------------------------------
1570 // -------------------------------------------
1573 if (OldTextOutModeMap
!= NULL
) {
1575 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1577 SrcAddress
= OldTextOutModeMap
;
1580 // Copy the old data to the new one
1582 while (Index
< Private
->TextOutMode
.MaxMode
) {
1583 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1584 TextOutModeMap
+= NewSize
;
1589 // Free the old buffer
1591 FreePool (OldTextOutModeMap
);
1599 ConSplitterAddOutputMode (
1600 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1601 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1605 Routine Description:
1620 MaxMode
= TextOut
->Mode
->MaxMode
;
1621 Private
->TextOutMode
.MaxMode
= MaxMode
;
1624 // Grow the buffer if query data buffer is not large enough to
1625 // hold all the mode supported by the first console.
1627 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1628 Status
= ConSplitterGrowBuffer (
1629 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1630 &Private
->TextOutQueryDataCount
,
1631 (VOID
**) &Private
->TextOutQueryData
1633 if (EFI_ERROR (Status
)) {
1634 return EFI_OUT_OF_RESOURCES
;
1638 // Allocate buffer for the output mode map
1640 Status
= ConSplitterGrowMapTable (Private
);
1641 if (EFI_ERROR (Status
)) {
1642 return EFI_OUT_OF_RESOURCES
;
1645 // As the first textout device, directly add the mode in to QueryData
1646 // and at the same time record the mapping between QueryData and TextOut.
1650 while (Mode
< MaxMode
) {
1651 TextOut
->QueryMode (
1654 &Private
->TextOutQueryData
[Mode
].Columns
,
1655 &Private
->TextOutQueryData
[Mode
].Rows
1657 Private
->TextOutModeMap
[Index
] = Mode
;
1659 Index
+= Private
->TextOutListCount
;
1667 ConSplitterGetIntersection (
1668 IN INT32
*TextOutModeMap
,
1669 IN INT32
*NewlyAddedMap
,
1670 IN UINTN MapStepSize
,
1671 IN UINTN NewMapStepSize
,
1673 OUT INT32
*CurrentMode
1677 INT32
*CurrentMapEntry
;
1678 INT32
*NextMapEntry
;
1679 INT32 CurrentMaxMode
;
1683 CurrentMapEntry
= TextOutModeMap
;
1684 NextMapEntry
= TextOutModeMap
;
1685 CurrentMaxMode
= *MaxMode
;
1686 Mode
= *CurrentMode
;
1688 while (Index
< CurrentMaxMode
) {
1689 if (*NewlyAddedMap
== -1) {
1691 // This mode is not supported any more. Remove it. Special care
1692 // must be taken as this remove will also affect current mode;
1694 if (Index
== *CurrentMode
) {
1696 } else if (Index
< *CurrentMode
) {
1701 if (CurrentMapEntry
!= NextMapEntry
) {
1702 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1705 NextMapEntry
+= MapStepSize
;
1708 CurrentMapEntry
+= MapStepSize
;
1709 NewlyAddedMap
+= NewMapStepSize
;
1713 *CurrentMode
= Mode
;
1720 ConSplitterSyncOutputMode (
1721 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1722 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1726 Routine Description:
1729 Private - Private data structure.
1730 TextOut - Text Out Protocol.
1737 INT32 CurrentMaxMode
;
1740 INT32
*TextOutModeMap
;
1742 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1748 // Must make sure that current mode won't change even if mode number changes
1750 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1751 TextOutModeMap
= Private
->TextOutModeMap
;
1752 StepSize
= Private
->TextOutListCount
;
1753 TextOutQueryData
= Private
->TextOutQueryData
;
1756 // Query all the mode that the newly added TextOut supports
1759 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1760 while (Mode
< TextOut
->Mode
->MaxMode
) {
1761 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1764 // Search the QueryData database to see if they intersects
1767 while (Index
< CurrentMaxMode
) {
1768 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1769 MapTable
[Index
* StepSize
] = Mode
;
1779 // Now search the TextOutModeMap table to find the intersection of supported
1780 // mode between ConSplitter and the newly added device.
1782 ConSplitterGetIntersection (
1787 &Private
->TextOutMode
.MaxMode
,
1788 &Private
->TextOutMode
.Mode
1796 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1801 Routine Description:
1808 EFI_OUT_OF_RESOURCES
1812 UINTN ConOutNumOfConsoles
;
1813 UINTN StdErrNumOfConsoles
;
1814 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1815 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1820 INT32 ConOutMaxMode
;
1821 INT32 StdErrMaxMode
;
1824 INT32
*ConOutModeMap
;
1825 INT32
*StdErrModeMap
;
1826 INT32
*ConOutMapTable
;
1827 INT32
*StdErrMapTable
;
1828 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1829 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1830 BOOLEAN FoundTheSameTextOut
;
1831 UINTN ConOutMapTableSize
;
1832 UINTN StdErrMapTableSize
;
1834 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1835 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1836 ConOutTextOutList
= mConOut
.TextOutList
;
1837 StdErrTextOutList
= mStdErr
.TextOutList
;
1840 FoundTheSameTextOut
= FALSE
;
1841 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1843 while (Indexj
< StdErrNumOfConsoles
) {
1844 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1845 FoundTheSameTextOut
= TRUE
;
1850 StdErrTextOutList
++;
1854 ConOutTextOutList
++;
1857 if (!FoundTheSameTextOut
) {
1861 // Must make sure that current mode won't change even if mode number changes
1863 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1864 ConOutModeMap
= mConOut
.TextOutModeMap
;
1865 ConOutQueryData
= mConOut
.TextOutQueryData
;
1867 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1868 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1869 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1872 // Allocate the map table and set the map table's index to -1.
1874 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1875 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1876 if (ConOutMapTable
== NULL
) {
1877 return EFI_OUT_OF_RESOURCES
;
1880 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1882 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1883 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1884 if (StdErrMapTable
== NULL
) {
1885 return EFI_OUT_OF_RESOURCES
;
1888 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
1891 // Find the intersection of the two set of modes. If they actually intersect, the
1892 // correponding entry in the map table is set to 1.
1895 while (Mode
< ConOutMaxMode
) {
1897 // Search the other's QueryData database to see if they intersect
1900 Rows
= ConOutQueryData
[Mode
].Rows
;
1901 Columns
= ConOutQueryData
[Mode
].Columns
;
1902 while (Index
< StdErrMaxMode
) {
1903 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
1904 ConOutMapTable
[Mode
] = 1;
1905 StdErrMapTable
[Index
] = 1;
1915 // Now search the TextOutModeMap table to find the intersection of supported
1916 // mode between ConSplitter and the newly added device.
1918 ConSplitterGetIntersection (
1921 mConOut
.TextOutListCount
,
1923 &(mConOut
.TextOutMode
.MaxMode
),
1924 &(mConOut
.TextOutMode
.Mode
)
1926 if (mConOut
.TextOutMode
.Mode
< 0) {
1927 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
1930 ConSplitterGetIntersection (
1933 mStdErr
.TextOutListCount
,
1935 &(mStdErr
.TextOutMode
.MaxMode
),
1936 &(mStdErr
.TextOutMode
.Mode
)
1938 if (mStdErr
.TextOutMode
.Mode
< 0) {
1939 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
1942 FreePool (ConOutMapTable
);
1943 FreePool (StdErrMapTable
);
1950 ConSplitterAddGraphicsOutputMode (
1951 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1952 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1953 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1957 Routine Description:
1969 TEXT_OUT_GOP_MODE
*Mode
;
1971 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1972 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
1973 TEXT_OUT_GOP_MODE
*ModeBuffer
;
1974 TEXT_OUT_GOP_MODE
*MatchedMode
;
1978 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
1979 return EFI_UNSUPPORTED
;
1982 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
1984 if (GraphicsOutput
!= NULL
) {
1985 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
1987 // This is the first Graphics Output device added
1989 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
1990 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
1991 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
1992 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
1993 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
1994 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
1997 // Allocate resource for the private mode buffer
1999 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
2000 if (ModeBuffer
== NULL
) {
2001 return EFI_OUT_OF_RESOURCES
;
2003 FreePool (Private
->GraphicsOutputModeBuffer
);
2004 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2007 // Store all supported display modes to the private mode buffer
2010 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2011 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2012 if (EFI_ERROR (Status
)) {
2015 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2016 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2022 // Check intersection of display mode
2024 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2025 if (ModeBuffer
== NULL
) {
2026 return EFI_OUT_OF_RESOURCES
;
2029 MatchedMode
= ModeBuffer
;
2030 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2031 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2034 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2035 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2036 if (EFI_ERROR (Status
)) {
2039 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2040 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2049 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2057 // Drop the old mode buffer, assign it to a new one
2059 FreePool (Private
->GraphicsOutputModeBuffer
);
2060 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2063 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2065 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2066 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2067 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2068 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2069 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2070 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2074 // Select a prefered Display mode 800x600
2076 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2077 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2078 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2083 // Prefered mode is not found, set to mode 0
2085 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2090 // Current mode number may need update now, so set it to an invalide mode number
2092 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2095 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2096 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2098 CurrentGraphicsOutputMode
->MaxMode
= 1;
2099 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2100 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2101 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2102 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2103 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2104 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2105 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2106 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2109 // Update the private mode buffer
2111 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2112 ModeBuffer
->HorizontalResolution
= 800;
2113 ModeBuffer
->VerticalResolution
= 600;
2116 // Current mode is unknow now, set it to an invalid mode number 0xffff
2118 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2123 // Force GraphicsOutput mode to be set,
2124 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2126 Private
->HardwareNeedsStarting
= TRUE
;
2127 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2129 Private
->CurrentNumberOfGraphicsOutput
++;
2135 ConSplitterTextOutAddDevice (
2136 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2137 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2138 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2139 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2143 Routine Description:
2154 UINTN CurrentNumOfConsoles
;
2157 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2159 Status
= EFI_SUCCESS
;
2160 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2163 // If the Text Out List is full, enlarge it by calling growbuffer().
2165 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2166 Status
= ConSplitterGrowBuffer (
2167 sizeof (TEXT_OUT_AND_GOP_DATA
),
2168 &Private
->TextOutListCount
,
2169 (VOID
**) &Private
->TextOutList
2171 if (EFI_ERROR (Status
)) {
2172 return EFI_OUT_OF_RESOURCES
;
2175 // Also need to reallocate the TextOutModeMap table
2177 Status
= ConSplitterGrowMapTable (Private
);
2178 if (EFI_ERROR (Status
)) {
2179 return EFI_OUT_OF_RESOURCES
;
2183 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2185 TextAndGop
->TextOut
= TextOut
;
2186 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2187 TextAndGop
->UgaDraw
= UgaDraw
;
2189 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2191 // If No UGA device then use the ConOut device
2193 TextAndGop
->TextOutEnabled
= TRUE
;
2196 // If UGA device use ConOut device only used if UGA screen is in Text mode
2198 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2201 if (CurrentNumOfConsoles
== 0) {
2203 // Add the first device's output mode to console splitter's mode list
2205 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2207 ConSplitterSyncOutputMode (Private
, TextOut
);
2210 Private
->CurrentNumberOfConsoles
++;
2213 // Scan both TextOutList, for the intersection TextOut device
2214 // maybe both ConOut and StdErr incorporate the same Text Out
2215 // device in them, thus the output of both should be synced.
2217 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2219 CurrentMode
= Private
->TextOutMode
.Mode
;
2220 MaxMode
= Private
->TextOutMode
.MaxMode
;
2221 ASSERT (MaxMode
>= 1);
2223 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2224 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2227 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2229 // We just added a new UGA device in graphics mode
2231 DevNullGopSync (Private
, GraphicsOutput
, UgaDraw
);
2232 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2234 // The new console supports the same mode of the current console so sync up
2236 DevNullSyncGopStdOut (Private
);
2239 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2241 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2248 ConSplitterTextOutDeleteDevice (
2249 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2250 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2254 Routine Description:
2265 UINTN CurrentNumOfConsoles
;
2266 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2270 // Remove the specified text-out device data structure from the Text out List,
2271 // and rearrange the remaining data structures in the Text out List.
2273 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2274 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2275 TextOutList
= Private
->TextOutList
;
2276 while (Index
>= 0) {
2277 if (TextOutList
->TextOut
== TextOut
) {
2278 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2279 CurrentNumOfConsoles
--;
2287 // The specified TextOut is not managed by the ConSplitter driver
2290 return EFI_NOT_FOUND
;
2293 if (CurrentNumOfConsoles
== 0) {
2295 // If the number of consoles is zero clear the Dev NULL device
2297 Private
->CurrentNumberOfConsoles
= 0;
2298 Private
->TextOutMode
.MaxMode
= 1;
2299 Private
->TextOutQueryData
[0].Columns
= 80;
2300 Private
->TextOutQueryData
[0].Rows
= 25;
2301 DevNullTextOutSetMode (Private
, 0);
2306 // Max Mode is realy an intersection of the QueryMode command to all
2307 // devices. So we must copy the QueryMode of the first device to
2311 Private
->TextOutQueryData
,
2312 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2315 FreePool (Private
->TextOutModeMap
);
2316 Private
->TextOutModeMap
= NULL
;
2317 TextOutList
= Private
->TextOutList
;
2320 // Add the first TextOut to the QueryData array and ModeMap table
2322 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2325 // Now add one by one
2328 Private
->CurrentNumberOfConsoles
= 1;
2330 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2331 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2333 Private
->CurrentNumberOfConsoles
++;
2337 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2342 // ConSplitter TextIn member functions
2346 ConSplitterTextInReset (
2347 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2348 IN BOOLEAN ExtendedVerification
2352 Routine Description:
2353 Reset the input device and optionaly run diagnostics
2356 This - Protocol instance pointer.
2357 ExtendedVerification - Driver may perform diagnostics on reset.
2360 EFI_SUCCESS - The device was reset.
2361 EFI_DEVICE_ERROR - The device is not functioning properly and could
2367 EFI_STATUS ReturnStatus
;
2368 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2371 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2373 Private
->KeyEventSignalState
= FALSE
;
2376 // return the worst status met
2378 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2379 Status
= Private
->TextInList
[Index
]->Reset (
2380 Private
->TextInList
[Index
],
2381 ExtendedVerification
2383 if (EFI_ERROR (Status
)) {
2384 ReturnStatus
= Status
;
2388 return ReturnStatus
;
2393 ConSplitterTextInPrivateReadKeyStroke (
2394 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2395 OUT EFI_INPUT_KEY
*Key
2399 Routine Description:
2400 Reads the next keystroke from the input device. The WaitForKey Event can
2401 be used to test for existance of a keystroke via WaitForEvent () call.
2404 This - Protocol instance pointer.
2405 Key - Driver may perform diagnostics on reset.
2408 EFI_SUCCESS - The keystroke information was returned.
2409 EFI_NOT_READY - There was no keystroke data availiable.
2410 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2417 EFI_INPUT_KEY CurrentKey
;
2419 Key
->UnicodeChar
= 0;
2420 Key
->ScanCode
= SCAN_NULL
;
2423 // if no physical console input device exists, return EFI_NOT_READY;
2424 // if any physical console input device has key input,
2425 // return the key and EFI_SUCCESS.
2427 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2428 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2429 Private
->TextInList
[Index
],
2432 if (!EFI_ERROR (Status
)) {
2438 return EFI_NOT_READY
;
2442 ConSpliterConssoleControlStdInLocked (
2447 Routine Description:
2448 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2449 the only device locked.
2456 FALSE - StdIn working normally
2460 return mConIn
.PasswordEnabled
;
2465 ConSpliterConsoleControlLockStdInEvent (
2471 Routine Description:
2472 This timer event will fire when StdIn is locked. It will check the key
2473 sequence on StdIn to see if it matches the password. Any error in the
2474 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2475 TRUE the StdIn splitter will not report any input.
2478 (Standard EFI_EVENT_NOTIFY)
2487 CHAR16 BackSpaceString
[2];
2488 CHAR16 SpaceString
[2];
2491 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2492 if (!EFI_ERROR (Status
)) {
2494 // if it's an ENTER, match password
2496 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2497 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2498 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2500 // Password not match
2502 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2503 mConIn
.PwdIndex
= 0;
2506 // Key matches password sequence
2508 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2509 mConIn
.PasswordEnabled
= FALSE
;
2510 Status
= EFI_NOT_READY
;
2512 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2516 if (mConIn
.PwdIndex
> 0) {
2517 BackSpaceString
[0] = CHAR_BACKSPACE
;
2518 BackSpaceString
[1] = 0;
2520 SpaceString
[0] = ' ';
2523 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2524 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2525 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2529 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2531 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2533 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2534 if (mConIn
.PwdIndex
== 0) {
2535 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2538 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2539 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2544 } while (!EFI_ERROR (Status
));
2549 ConSpliterConsoleControlLockStdIn (
2550 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2555 Routine Description:
2556 If Password is NULL unlock the password state variable and set the event
2557 timer. If the Password is too big return an error. If the Password is valid
2558 Copy the Password and enable state variable and then arm the periodic timer
2563 EFI_SUCCESS - Lock the StdIn device
2564 EFI_INVALID_PARAMETER - Password is NULL
2565 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2569 if (Password
== NULL
) {
2570 return EFI_INVALID_PARAMETER
;
2573 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2575 // Currently have a max password size
2577 return EFI_OUT_OF_RESOURCES
;
2580 // Save the password, initialize state variables and arm event timer
2582 StrCpy (mConIn
.Password
, Password
);
2583 mConIn
.PasswordEnabled
= TRUE
;
2584 mConIn
.PwdIndex
= 0;
2585 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2592 ConSplitterTextInReadKeyStroke (
2593 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2594 OUT EFI_INPUT_KEY
*Key
2598 Routine Description:
2599 Reads the next keystroke from the input device. The WaitForKey Event can
2600 be used to test for existance of a keystroke via WaitForEvent () call.
2601 If the ConIn is password locked make it look like no keystroke is availible
2604 This - Protocol instance pointer.
2605 Key - Driver may perform diagnostics on reset.
2608 EFI_SUCCESS - The keystroke information was returned.
2609 EFI_NOT_READY - There was no keystroke data availiable.
2610 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2615 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2617 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2618 if (Private
->PasswordEnabled
) {
2620 // If StdIn Locked return not ready
2622 return EFI_NOT_READY
;
2625 Private
->KeyEventSignalState
= FALSE
;
2627 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2632 ConSplitterTextInWaitForKey (
2638 Routine Description:
2639 This event agregates all the events of the ConIn devices in the spliter.
2640 If the ConIn is password locked then return.
2641 If any events of physical ConIn devices are signaled, signal the ConIn
2642 spliter event. This will cause the calling code to call
2643 ConSplitterTextInReadKeyStroke ().
2646 Event - The Event assoicated with callback.
2647 Context - Context registered when Event was created.
2655 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2658 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2659 if (Private
->PasswordEnabled
) {
2661 // If StdIn Locked return not ready
2667 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2669 if (Private
->KeyEventSignalState
) {
2670 gBS
->SignalEvent (Event
);
2674 // if any physical console input device has key input, signal the event.
2676 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2677 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2678 if (!EFI_ERROR (Status
)) {
2679 gBS
->SignalEvent (Event
);
2680 Private
->KeyEventSignalState
= TRUE
;
2687 ConSplitterSimplePointerReset (
2688 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2689 IN BOOLEAN ExtendedVerification
2693 Routine Description:
2694 Reset the input device and optionaly run diagnostics
2697 This - Protocol instance pointer.
2698 ExtendedVerification - Driver may perform diagnostics on reset.
2701 EFI_SUCCESS - The device was reset.
2702 EFI_DEVICE_ERROR - The device is not functioning properly and could
2708 EFI_STATUS ReturnStatus
;
2709 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2712 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2714 Private
->InputEventSignalState
= FALSE
;
2716 if (Private
->CurrentNumberOfPointers
== 0) {
2720 // return the worst status met
2722 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2723 Status
= Private
->PointerList
[Index
]->Reset (
2724 Private
->PointerList
[Index
],
2725 ExtendedVerification
2727 if (EFI_ERROR (Status
)) {
2728 ReturnStatus
= Status
;
2732 return ReturnStatus
;
2738 ConSplitterSimplePointerPrivateGetState (
2739 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2740 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2744 Routine Description:
2745 Reads the next keystroke from the input device. The WaitForKey Event can
2746 be used to test for existance of a keystroke via WaitForEvent () call.
2749 This - Protocol instance pointer.
2753 EFI_SUCCESS - The keystroke information was returned.
2754 EFI_NOT_READY - There was no keystroke data availiable.
2755 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2761 EFI_STATUS ReturnStatus
;
2763 EFI_SIMPLE_POINTER_STATE CurrentState
;
2765 State
->RelativeMovementX
= 0;
2766 State
->RelativeMovementY
= 0;
2767 State
->RelativeMovementZ
= 0;
2768 State
->LeftButton
= FALSE
;
2769 State
->RightButton
= FALSE
;
2772 // if no physical console input device exists, return EFI_NOT_READY;
2773 // if any physical console input device has key input,
2774 // return the key and EFI_SUCCESS.
2776 ReturnStatus
= EFI_NOT_READY
;
2777 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2779 Status
= Private
->PointerList
[Index
]->GetState (
2780 Private
->PointerList
[Index
],
2783 if (!EFI_ERROR (Status
)) {
2784 if (ReturnStatus
== EFI_NOT_READY
) {
2785 ReturnStatus
= EFI_SUCCESS
;
2788 if (CurrentState
.LeftButton
) {
2789 State
->LeftButton
= TRUE
;
2792 if (CurrentState
.RightButton
) {
2793 State
->RightButton
= TRUE
;
2796 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2797 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2800 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2801 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2804 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2805 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2807 } else if (Status
== EFI_DEVICE_ERROR
) {
2808 ReturnStatus
= EFI_DEVICE_ERROR
;
2812 return ReturnStatus
;
2817 ConSplitterSimplePointerGetState (
2818 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2819 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2823 Routine Description:
2824 Reads the next keystroke from the input device. The WaitForKey Event can
2825 be used to test for existance of a keystroke via WaitForEvent () call.
2826 If the ConIn is password locked make it look like no keystroke is availible
2829 This - Protocol instance pointer.
2833 EFI_SUCCESS - The keystroke information was returned.
2834 EFI_NOT_READY - There was no keystroke data availiable.
2835 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2840 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2842 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2843 if (Private
->PasswordEnabled
) {
2845 // If StdIn Locked return not ready
2847 return EFI_NOT_READY
;
2850 Private
->InputEventSignalState
= FALSE
;
2852 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2857 ConSplitterSimplePointerWaitForInput (
2863 Routine Description:
2864 This event agregates all the events of the ConIn devices in the spliter.
2865 If the ConIn is password locked then return.
2866 If any events of physical ConIn devices are signaled, signal the ConIn
2867 spliter event. This will cause the calling code to call
2868 ConSplitterTextInReadKeyStroke ().
2871 Event - The Event assoicated with callback.
2872 Context - Context registered when Event was created.
2880 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2883 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2884 if (Private
->PasswordEnabled
) {
2886 // If StdIn Locked return not ready
2892 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2894 if (Private
->InputEventSignalState
) {
2895 gBS
->SignalEvent (Event
);
2899 // if any physical console input device has key input, signal the event.
2901 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2902 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2903 if (!EFI_ERROR (Status
)) {
2904 gBS
->SignalEvent (Event
);
2905 Private
->InputEventSignalState
= TRUE
;
2912 ConSplitterTextOutReset (
2913 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2914 IN BOOLEAN ExtendedVerification
2918 Routine Description:
2919 Reset the text output device hardware and optionaly run diagnostics
2922 This - Protocol instance pointer.
2923 ExtendedVerification - Driver may perform more exhaustive verfication
2924 operation of the device during reset.
2927 EFI_SUCCESS - The text output device was reset.
2928 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2934 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2936 EFI_STATUS ReturnStatus
;
2938 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2941 // return the worst status met
2943 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2945 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2947 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2948 Private
->TextOutList
[Index
].TextOut
,
2949 ExtendedVerification
2951 if (EFI_ERROR (Status
)) {
2952 ReturnStatus
= Status
;
2957 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2959 Status
= DevNullTextOutSetMode (Private
, 0);
2960 if (EFI_ERROR (Status
)) {
2961 ReturnStatus
= Status
;
2964 return ReturnStatus
;
2969 ConSplitterTextOutOutputString (
2970 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2975 Routine Description:
2976 Write a Unicode string to the output device.
2979 This - Protocol instance pointer.
2980 String - The NULL-terminated Unicode string to be displayed on the output
2981 device(s). All output devices must also support the Unicode
2982 drawing defined in this file.
2985 EFI_SUCCESS - The string was output to the device.
2986 EFI_DEVICE_ERROR - The device reported an error while attempting to output
2988 EFI_UNSUPPORTED - The output device's mode is not currently in a
2990 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
2991 characters in the Unicode string could not be
2992 rendered and were skipped.
2997 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2999 UINTN BackSpaceCount
;
3000 EFI_STATUS ReturnStatus
;
3001 CHAR16
*TargetString
;
3003 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3005 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3008 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3009 if (*TargetString
== CHAR_BACKSPACE
) {
3015 if (BackSpaceCount
== 0) {
3016 TargetString
= WString
;
3018 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3019 StrCpy (TargetString
, WString
);
3022 // return the worst status met
3024 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3025 if (EFI_ERROR (Status
)) {
3026 ReturnStatus
= Status
;
3029 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3031 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3032 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3033 Private
->TextOutList
[Index
].TextOut
,
3036 if (EFI_ERROR (Status
)) {
3037 ReturnStatus
= Status
;
3042 if (BackSpaceCount
) {
3043 FreePool (TargetString
);
3046 return ReturnStatus
;
3051 ConSplitterTextOutTestString (
3052 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3057 Routine Description:
3058 Verifies that all characters in a Unicode string can be output to the
3062 This - Protocol instance pointer.
3063 String - The NULL-terminated Unicode string to be examined for the output
3067 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3068 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3069 rendered by one or more of the output devices mapped
3075 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3077 EFI_STATUS ReturnStatus
;
3079 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3082 // return the worst status met
3084 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3085 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3086 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3087 Private
->TextOutList
[Index
].TextOut
,
3090 if (EFI_ERROR (Status
)) {
3091 ReturnStatus
= Status
;
3096 // There is no DevNullTextOutTestString () since a Unicode buffer would
3097 // always return EFI_SUCCESS.
3098 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3100 return ReturnStatus
;
3105 ConSplitterTextOutQueryMode (
3106 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3107 IN UINTN ModeNumber
,
3113 Routine Description:
3114 Returns information for an available text mode that the output device(s)
3118 This - Protocol instance pointer.
3119 ModeNumber - The mode number to return information on.
3120 Columns, Rows - Returns the geometry of the text output device for the
3121 requested ModeNumber.
3124 EFI_SUCCESS - The requested mode information was returned.
3125 EFI_DEVICE_ERROR - The device had an error and could not
3126 complete the request.
3127 EFI_UNSUPPORTED - The mode number was not valid.
3131 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3133 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3136 // Check whether param ModeNumber is valid.
3137 // ModeNumber should be within range 0 ~ MaxMode - 1.
3139 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3140 return EFI_UNSUPPORTED
;
3143 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3144 return EFI_UNSUPPORTED
;
3147 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3148 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3150 if (*Columns
<= 0 && *Rows
<= 0) {
3151 return EFI_UNSUPPORTED
;
3160 ConSplitterTextOutSetMode (
3161 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3166 Routine Description:
3167 Sets the output device(s) to a specified mode.
3170 This - Protocol instance pointer.
3171 ModeNumber - The mode number to set.
3174 EFI_SUCCESS - The requested text mode was set.
3175 EFI_DEVICE_ERROR - The device had an error and
3176 could not complete the request.
3177 EFI_UNSUPPORTED - The mode number was not valid.
3182 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3184 INT32
*TextOutModeMap
;
3185 EFI_STATUS ReturnStatus
;
3187 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3190 // Check whether param ModeNumber is valid.
3191 // ModeNumber should be within range 0 ~ MaxMode - 1.
3193 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3194 return EFI_UNSUPPORTED
;
3197 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3198 return EFI_UNSUPPORTED
;
3201 // If the mode is being set to the curent mode, then just clear the screen and return.
3203 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3204 return ConSplitterTextOutClearScreen (This
);
3207 // return the worst status met
3209 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3210 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3212 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3213 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3214 Private
->TextOutList
[Index
].TextOut
,
3215 TextOutModeMap
[Index
]
3218 // If this console device is based on a UGA device, then sync up the bitmap from
3219 // the UGA splitter and reclear the text portion of the display in the new mode.
3221 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3222 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3225 if (EFI_ERROR (Status
)) {
3226 ReturnStatus
= Status
;
3231 // The DevNull Console will support any possible mode as it allocates memory
3233 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3234 if (EFI_ERROR (Status
)) {
3235 ReturnStatus
= Status
;
3238 return ReturnStatus
;
3243 ConSplitterTextOutSetAttribute (
3244 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3249 Routine Description:
3250 Sets the background and foreground colors for the OutputString () and
3251 ClearScreen () functions.
3254 This - Protocol instance pointer.
3255 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3256 bits 4..6 are the background color. All other bits are undefined
3257 and must be zero. The valid Attributes are defined in this file.
3260 EFI_SUCCESS - The attribute was set.
3261 EFI_DEVICE_ERROR - The device had an error and
3262 could not complete the request.
3263 EFI_UNSUPPORTED - The attribute requested is not defined.
3268 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3270 EFI_STATUS ReturnStatus
;
3272 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3275 // Check whether param Attribute is valid.
3277 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3278 return EFI_UNSUPPORTED
;
3282 // return the worst status met
3284 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3286 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3287 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3288 Private
->TextOutList
[Index
].TextOut
,
3291 if (EFI_ERROR (Status
)) {
3292 ReturnStatus
= Status
;
3297 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3299 return ReturnStatus
;
3304 ConSplitterTextOutClearScreen (
3305 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3309 Routine Description:
3310 Clears the output device(s) display to the currently selected background
3314 This - Protocol instance pointer.
3317 EFI_SUCCESS - The operation completed successfully.
3318 EFI_DEVICE_ERROR - The device had an error and
3319 could not complete the request.
3320 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3325 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3327 EFI_STATUS ReturnStatus
;
3329 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3332 // return the worst status met
3334 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3336 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3337 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3338 if (EFI_ERROR (Status
)) {
3339 ReturnStatus
= Status
;
3344 Status
= DevNullTextOutClearScreen (Private
);
3345 if (EFI_ERROR (Status
)) {
3346 ReturnStatus
= Status
;
3349 return ReturnStatus
;
3354 ConSplitterTextOutSetCursorPosition (
3355 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3361 Routine Description:
3362 Sets the current coordinates of the cursor position
3365 This - Protocol instance pointer.
3366 Column, Row - the position to set the cursor to. Must be greater than or
3367 equal to zero and less than the number of columns and rows
3371 EFI_SUCCESS - The operation completed successfully.
3372 EFI_DEVICE_ERROR - The device had an error and
3373 could not complete the request.
3374 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3375 cursor position is invalid for the current mode.
3380 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3382 EFI_STATUS ReturnStatus
;
3386 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3388 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3389 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3391 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3392 return EFI_UNSUPPORTED
;
3395 // return the worst status met
3397 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3399 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3400 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3401 Private
->TextOutList
[Index
].TextOut
,
3405 if (EFI_ERROR (Status
)) {
3406 ReturnStatus
= Status
;
3411 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3413 return ReturnStatus
;
3418 ConSplitterTextOutEnableCursor (
3419 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3424 Routine Description:
3425 Makes the cursor visible or invisible
3428 This - Protocol instance pointer.
3429 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3430 set to be invisible.
3433 EFI_SUCCESS - The operation completed successfully.
3434 EFI_DEVICE_ERROR - The device had an error and could not complete the
3435 request, or the device does not support changing
3437 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3442 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3444 EFI_STATUS ReturnStatus
;
3446 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3449 // return the worst status met
3451 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3453 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3454 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3455 Private
->TextOutList
[Index
].TextOut
,
3458 if (EFI_ERROR (Status
)) {
3459 ReturnStatus
= Status
;
3464 DevNullTextOutEnableCursor (Private
, Visible
);
3466 return ReturnStatus
;