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
,
47 ConSplitterTextInResetEx
,
48 ConSplitterTextInReadKeyStrokeEx
,
50 ConSplitterTextInSetState
,
51 ConSplitterTextInRegisterKeyNotify
,
52 ConSplitterTextInUnregisterKeyNotify
55 (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
**) NULL
,
58 (struct _LIST_ENTRY
*) NULL
,
59 (struct _LIST_ENTRY
*) NULL
63 ConSplitterSimplePointerReset
,
64 ConSplitterSimplePointerGetState
,
66 (EFI_SIMPLE_POINTER_MODE
*) NULL
76 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
99 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
100 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
103 ConSplitterTextOutReset
,
104 ConSplitterTextOutOutputString
,
105 ConSplitterTextOutTestString
,
106 ConSplitterTextOutQueryMode
,
107 ConSplitterTextOutSetMode
,
108 ConSplitterTextOutSetAttribute
,
109 ConSplitterTextOutClearScreen
,
110 ConSplitterTextOutSetCursorPosition
,
111 ConSplitterTextOutEnableCursor
,
112 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
123 ConSpliterUgaDrawGetMode
,
124 ConSpliterUgaDrawSetMode
,
131 (EFI_UGA_PIXEL
*) NULL
,
133 ConSpliterGraphicsOutputQueryMode
,
134 ConSpliterGraphicsOutputSetMode
,
135 ConSpliterGraphicsOutputBlt
,
138 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
139 (TEXT_OUT_GOP_MODE
*) NULL
,
143 ConSpliterConsoleControlGetMode
,
144 ConSpliterConsoleControlSetMode
,
145 ConSpliterConsoleControlLockStdIn
149 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
151 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
155 EfiConsoleControlScreenText
,
162 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
163 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
166 ConSplitterTextOutReset
,
167 ConSplitterTextOutOutputString
,
168 ConSplitterTextOutTestString
,
169 ConSplitterTextOutQueryMode
,
170 ConSplitterTextOutSetMode
,
171 ConSplitterTextOutSetAttribute
,
172 ConSplitterTextOutClearScreen
,
173 ConSplitterTextOutSetCursorPosition
,
174 ConSplitterTextOutEnableCursor
,
175 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
186 ConSpliterUgaDrawGetMode
,
187 ConSpliterUgaDrawSetMode
,
194 (EFI_UGA_PIXEL
*) NULL
,
196 ConSpliterGraphicsOutputQueryMode
,
197 ConSpliterGraphicsOutputSetMode
,
198 ConSpliterGraphicsOutputBlt
,
201 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
202 (TEXT_OUT_GOP_MODE
*) NULL
,
206 ConSpliterConsoleControlGetMode
,
207 ConSpliterConsoleControlSetMode
,
208 ConSpliterConsoleControlLockStdIn
212 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
214 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
218 EfiConsoleControlScreenText
,
225 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
226 ConSplitterConInDriverBindingSupported
,
227 ConSplitterConInDriverBindingStart
,
228 ConSplitterConInDriverBindingStop
,
234 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
235 ConSplitterSimplePointerDriverBindingSupported
,
236 ConSplitterSimplePointerDriverBindingStart
,
237 ConSplitterSimplePointerDriverBindingStop
,
243 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
244 ConSplitterConOutDriverBindingSupported
,
245 ConSplitterConOutDriverBindingStart
,
246 ConSplitterConOutDriverBindingStop
,
252 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
253 ConSplitterStdErrDriverBindingSupported
,
254 ConSplitterStdErrDriverBindingStart
,
255 ConSplitterStdErrDriverBindingStop
,
262 The user Entry Point for module ConSplitter. The user code starts with this function.
264 @param[in] ImageHandle The firmware allocated handle for the EFI image.
265 @param[in] SystemTable A pointer to the EFI System Table.
267 @retval EFI_SUCCESS The entry point is executed successfully.
268 @retval other Some error occurs when executing this entry point.
273 InitializeConSplitter(
274 IN EFI_HANDLE ImageHandle
,
275 IN EFI_SYSTEM_TABLE
*SystemTable
281 // Install driver model protocol(s).
283 Status
= EfiLibInstallDriverBindingComponentName2 (
286 &gConSplitterConInDriverBinding
,
288 &gConSplitterConInComponentName
,
289 &gConSplitterConInComponentName2
291 ASSERT_EFI_ERROR (Status
);
293 Status
= EfiLibInstallDriverBindingComponentName2 (
296 &gConSplitterSimplePointerDriverBinding
,
298 &gConSplitterSimplePointerComponentName
,
299 &gConSplitterSimplePointerComponentName2
301 ASSERT_EFI_ERROR (Status
);
303 Status
= EfiLibInstallDriverBindingComponentName2 (
306 &gConSplitterConOutDriverBinding
,
308 &gConSplitterConOutComponentName
,
309 &gConSplitterConOutComponentName2
311 ASSERT_EFI_ERROR (Status
);
313 Status
= EfiLibInstallDriverBindingComponentName2 (
316 &gConSplitterStdErrDriverBinding
,
318 &gConSplitterStdErrComponentName
,
319 &gConSplitterStdErrComponentName2
321 ASSERT_EFI_ERROR (Status
);
325 // Call the original Entry Point
327 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
335 ConSplitterDriverEntry (
336 IN EFI_HANDLE ImageHandle
,
337 IN EFI_SYSTEM_TABLE
*SystemTable
342 Intialize a virtual console device to act as an agrigator of physical console
346 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
347 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
355 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
356 FeaturePcdGet (PcdConOutUgaSupport
));
358 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
359 // The virtual handles will always exist even if no console exist in the
360 // system. This is need to support hotplug devices like USB.
363 // Create virtual device handle for StdErr Splitter
365 Status
= ConSplitterTextOutConstructor (&mStdErr
);
366 if (!EFI_ERROR (Status
)) {
367 Status
= gBS
->InstallMultipleProtocolInterfaces (
368 &mStdErr
.VirtualHandle
,
369 &gEfiSimpleTextOutProtocolGuid
,
371 &gEfiPrimaryStandardErrorDeviceGuid
,
377 // Create virtual device handle for ConIn Splitter
379 Status
= ConSplitterTextInConstructor (&mConIn
);
380 if (!EFI_ERROR (Status
)) {
381 Status
= gBS
->InstallMultipleProtocolInterfaces (
382 &mConIn
.VirtualHandle
,
383 &gEfiSimpleTextInProtocolGuid
,
385 &gEfiSimpleTextInputExProtocolGuid
,
387 &gEfiSimplePointerProtocolGuid
,
388 &mConIn
.SimplePointer
,
389 &gEfiPrimaryConsoleInDeviceGuid
,
393 if (!EFI_ERROR (Status
)) {
395 // Update the EFI System Table with new virtual console
397 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
398 gST
->ConIn
= &mConIn
.TextIn
;
402 // Create virtual device handle for ConOut Splitter
404 Status
= ConSplitterTextOutConstructor (&mConOut
);
405 if (!EFI_ERROR (Status
)) {
406 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
408 // In EFI mode, UGA Draw protocol is installed
410 Status
= gBS
->InstallMultipleProtocolInterfaces (
411 &mConOut
.VirtualHandle
,
412 &gEfiSimpleTextOutProtocolGuid
,
414 &gEfiUgaDrawProtocolGuid
,
416 &gEfiConsoleControlProtocolGuid
,
417 &mConOut
.ConsoleControl
,
418 &gEfiPrimaryConsoleOutDeviceGuid
,
422 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
424 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
426 Status
= gBS
->InstallMultipleProtocolInterfaces (
427 &mConOut
.VirtualHandle
,
428 &gEfiSimpleTextOutProtocolGuid
,
430 &gEfiGraphicsOutputProtocolGuid
,
431 &mConOut
.GraphicsOutput
,
432 &gEfiConsoleControlProtocolGuid
,
433 &mConOut
.ConsoleControl
,
434 &gEfiPrimaryConsoleOutDeviceGuid
,
440 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
441 // installed on virtual handle.
443 Status
= gBS
->InstallMultipleProtocolInterfaces (
444 &mConOut
.VirtualHandle
,
445 &gEfiSimpleTextOutProtocolGuid
,
447 &gEfiGraphicsOutputProtocolGuid
,
448 &mConOut
.GraphicsOutput
,
449 &gEfiUgaDrawProtocolGuid
,
451 &gEfiConsoleControlProtocolGuid
,
452 &mConOut
.ConsoleControl
,
453 &gEfiPrimaryConsoleOutDeviceGuid
,
459 if (!EFI_ERROR (Status
)) {
461 // Update the EFI System Table with new virtual console
463 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
464 gST
->ConOut
= &mConOut
.TextOut
;
469 // Update the CRC32 in the EFI System Table header
472 gBS
->CalculateCrc32 (
482 ConSplitterTextInConstructor (
483 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
489 Construct the ConSplitter.
493 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
496 EFI_OUT_OF_RESOURCES - Out of resources.
503 // Initilize console input splitter's private data.
505 Status
= ConSplitterGrowBuffer (
506 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
507 &ConInPrivate
->TextInListCount
,
508 (VOID
**) &ConInPrivate
->TextInList
510 if (EFI_ERROR (Status
)) {
511 return EFI_OUT_OF_RESOURCES
;
514 // Create Event to support locking StdIn Device
516 Status
= gBS
->CreateEvent (
517 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
519 ConSpliterConsoleControlLockStdInEvent
,
521 &ConInPrivate
->LockEvent
523 ASSERT_EFI_ERROR (Status
);
525 Status
= gBS
->CreateEvent (
528 ConSplitterTextInWaitForKey
,
530 &ConInPrivate
->TextIn
.WaitForKey
532 ASSERT_EFI_ERROR (Status
);
535 // Buffer for Simple Text Input Ex Protocol
537 Status
= ConSplitterGrowBuffer (
538 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
539 &ConInPrivate
->TextInExListCount
,
540 (VOID
**) &ConInPrivate
->TextInExList
542 if (EFI_ERROR (Status
)) {
543 return EFI_OUT_OF_RESOURCES
;
546 Status
= gBS
->CreateEvent (
549 ConSplitterTextInWaitForKey
,
551 &ConInPrivate
->TextInEx
.WaitForKeyEx
553 ASSERT_EFI_ERROR (Status
);
555 InitializeListHead (&ConInPrivate
->NotifyList
);
558 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
560 Status
= ConSplitterGrowBuffer (
561 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
562 &ConInPrivate
->PointerListCount
,
563 (VOID
**) &ConInPrivate
->PointerList
565 if (EFI_ERROR (Status
)) {
566 return EFI_OUT_OF_RESOURCES
;
569 Status
= gBS
->CreateEvent (
572 ConSplitterSimplePointerWaitForInput
,
574 &ConInPrivate
->SimplePointer
.WaitForInput
581 ConSplitterTextOutConstructor (
582 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
588 // Initilize console output splitter's private data.
590 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
592 Status
= ConSplitterGrowBuffer (
593 sizeof (TEXT_OUT_AND_GOP_DATA
),
594 &ConOutPrivate
->TextOutListCount
,
595 (VOID
**) &ConOutPrivate
->TextOutList
597 if (EFI_ERROR (Status
)) {
598 return EFI_OUT_OF_RESOURCES
;
601 Status
= ConSplitterGrowBuffer (
602 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
603 &ConOutPrivate
->TextOutQueryDataCount
,
604 (VOID
**) &ConOutPrivate
->TextOutQueryData
606 if (EFI_ERROR (Status
)) {
607 return EFI_OUT_OF_RESOURCES
;
610 // Setup the DevNullTextOut console to 80 x 25
612 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
613 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
614 DevNullTextOutSetMode (ConOutPrivate
, 0);
616 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
618 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
620 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
622 if (FeaturePcdGet (PcdConOutGopSupport
)) {
624 // Setup resource for mode information in Graphics Output Protocol interface
626 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
627 return EFI_OUT_OF_RESOURCES
;
629 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
630 return EFI_OUT_OF_RESOURCES
;
633 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
635 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
636 return EFI_OUT_OF_RESOURCES
;
638 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
639 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
642 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
643 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
644 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
646 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
647 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
648 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
649 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
650 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
652 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
654 // Initial current mode to unknow state, and then set to mode 0
656 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
657 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
665 ConSplitterSupported (
666 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
667 IN EFI_HANDLE ControllerHandle
,
673 Generic Supported Check
676 This - Pointer to protocol.
677 ControllerHandle - Controller Handle.
682 EFI_UNSUPPORTED - unsupported.
683 EFI_SUCCESS - operation is OK.
691 // Make sure the Console Splitter does not attempt to attach to itself
693 if (ControllerHandle
== mConIn
.VirtualHandle
) {
694 return EFI_UNSUPPORTED
;
697 if (ControllerHandle
== mConOut
.VirtualHandle
) {
698 return EFI_UNSUPPORTED
;
701 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
702 return EFI_UNSUPPORTED
;
705 // Check to see whether the handle has the ConsoleInDevice GUID on it
707 Status
= gBS
->OpenProtocol (
711 This
->DriverBindingHandle
,
713 EFI_OPEN_PROTOCOL_BY_DRIVER
716 if (EFI_ERROR (Status
)) {
723 This
->DriverBindingHandle
,
732 ConSplitterConInDriverBindingSupported (
733 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
734 IN EFI_HANDLE ControllerHandle
,
735 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
740 Console In Supported Check
743 This - Pointer to protocol.
744 ControllerHandle - Controller handle.
745 RemainingDevicePath - Remaining device path.
753 return ConSplitterSupported (
756 &gEfiConsoleInDeviceGuid
762 ConSplitterSimplePointerDriverBindingSupported (
763 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
764 IN EFI_HANDLE ControllerHandle
,
765 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
770 Standard Error Supported Check
773 This - Pointer to protocol.
774 ControllerHandle - Controller handle.
775 RemainingDevicePath - Remaining device path.
783 return ConSplitterSupported (
786 &gEfiSimplePointerProtocolGuid
792 ConSplitterConOutDriverBindingSupported (
793 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
794 IN EFI_HANDLE ControllerHandle
,
795 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
800 Console Out Supported Check
803 This - Pointer to protocol.
804 ControllerHandle - Controller handle.
805 RemainingDevicePath - Remaining device path.
813 return ConSplitterSupported (
816 &gEfiConsoleOutDeviceGuid
822 ConSplitterStdErrDriverBindingSupported (
823 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
824 IN EFI_HANDLE ControllerHandle
,
825 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
830 Standard Error Supported Check
833 This - Pointer to protocol.
834 ControllerHandle - Controller handle.
835 RemainingDevicePath - Remaining device path.
843 return ConSplitterSupported (
846 &gEfiStandardErrorDeviceGuid
854 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
855 IN EFI_HANDLE ControllerHandle
,
856 IN EFI_HANDLE ConSplitterVirtualHandle
,
857 IN EFI_GUID
*DeviceGuid
,
858 IN EFI_GUID
*InterfaceGuid
,
864 Start ConSplitter on ControllerHandle, and create the virtual
865 agrogated console device on first call Start for a SimpleTextIn handle.
868 (Standard DriverBinding Protocol Start() function)
871 EFI_ERROR if a SimpleTextIn protocol is not started.
879 // Check to see whether the handle has the ConsoleInDevice GUID on it
881 Status
= gBS
->OpenProtocol (
885 This
->DriverBindingHandle
,
887 EFI_OPEN_PROTOCOL_BY_DRIVER
889 if (EFI_ERROR (Status
)) {
893 Status
= gBS
->OpenProtocol (
897 This
->DriverBindingHandle
,
898 ConSplitterVirtualHandle
,
899 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
901 if (EFI_ERROR (Status
)) {
905 return gBS
->OpenProtocol (
909 This
->DriverBindingHandle
,
910 ConSplitterVirtualHandle
,
911 EFI_OPEN_PROTOCOL_GET_PROTOCOL
917 ConSplitterConInDriverBindingStart (
918 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
919 IN EFI_HANDLE ControllerHandle
,
920 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
925 Start ConSplitter on ControllerHandle, and create the virtual
926 agrogated console device on first call Start for a SimpleTextIn handle.
929 This - Pointer to protocol.
930 ControllerHandle - Controller handle.
931 RemainingDevicePath - Remaining device path.
936 EFI_ERROR if a SimpleTextIn protocol is not started.
941 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
942 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
945 // Start ConSplitter on ControllerHandle, and create the virtual
946 // agrogated console device on first call Start for a SimpleTextIn handle.
948 Status
= ConSplitterStart (
951 mConIn
.VirtualHandle
,
952 &gEfiConsoleInDeviceGuid
,
953 &gEfiSimpleTextInProtocolGuid
,
956 if (EFI_ERROR (Status
)) {
960 Status
= ConSplitterTextInAddDevice (&mConIn
, TextIn
);
961 if (EFI_ERROR (Status
)) {
965 Status
= gBS
->OpenProtocol (
967 &gEfiSimpleTextInputExProtocolGuid
,
969 This
->DriverBindingHandle
,
970 mConIn
.VirtualHandle
,
971 EFI_OPEN_PROTOCOL_GET_PROTOCOL
973 if (EFI_ERROR (Status
)) {
977 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
984 ConSplitterSimplePointerDriverBindingStart (
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.
1002 EFI_ERROR if a SimpleTextIn protocol is not started.
1007 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1009 Status
= ConSplitterStart (
1012 mConIn
.VirtualHandle
,
1013 &gEfiSimplePointerProtocolGuid
,
1014 &gEfiSimplePointerProtocolGuid
,
1015 (VOID
**) &SimplePointer
1017 if (EFI_ERROR (Status
)) {
1021 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1026 ConSplitterConOutDriverBindingStart (
1027 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1028 IN EFI_HANDLE ControllerHandle
,
1029 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1033 Routine Description:
1034 Start ConSplitter on ControllerHandle, and create the virtual
1035 agrogated console device on first call Start for a SimpleTextIn handle.
1038 This - Pointer to protocol.
1039 ControllerHandle - Controller handle.
1040 RemainingDevicePath - Remaining device path.
1043 EFI_ERROR if a SimpleTextIn protocol is not started.
1048 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1049 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1050 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1052 Status
= ConSplitterStart (
1055 mConOut
.VirtualHandle
,
1056 &gEfiConsoleOutDeviceGuid
,
1057 &gEfiSimpleTextOutProtocolGuid
,
1060 if (EFI_ERROR (Status
)) {
1064 // Try to Open Graphics Output protocol
1066 Status
= gBS
->OpenProtocol (
1068 &gEfiGraphicsOutputProtocolGuid
,
1069 (VOID
**) &GraphicsOutput
,
1070 This
->DriverBindingHandle
,
1071 mConOut
.VirtualHandle
,
1072 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1074 if (EFI_ERROR (Status
)) {
1075 GraphicsOutput
= NULL
;
1078 // Open UGA_DRAW protocol
1080 Status
= gBS
->OpenProtocol (
1082 &gEfiUgaDrawProtocolGuid
,
1084 This
->DriverBindingHandle
,
1085 mConOut
.VirtualHandle
,
1086 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1088 if (EFI_ERROR (Status
)) {
1092 // If both ConOut and StdErr incorporate the same Text Out device,
1093 // their MaxMode and QueryData should be the intersection of both.
1095 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1096 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1098 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
1100 // Match the UGA mode data of ConOut with the current mode
1102 if (UgaDraw
!= NULL
) {
1105 &mConOut
.UgaHorizontalResolution
,
1106 &mConOut
.UgaVerticalResolution
,
1107 &mConOut
.UgaColorDepth
,
1108 &mConOut
.UgaRefreshRate
1117 ConSplitterStdErrDriverBindingStart (
1118 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1119 IN EFI_HANDLE ControllerHandle
,
1120 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1124 Routine Description:
1125 Start ConSplitter on ControllerHandle, and create the virtual
1126 agrogated console device on first call Start for a SimpleTextIn handle.
1129 This - Pointer to protocol.
1130 ControllerHandle - Controller handle.
1131 RemainingDevicePath - Remaining device path.
1134 EFI_ERROR if a SimpleTextIn protocol is not started.
1139 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1141 Status
= ConSplitterStart (
1144 mStdErr
.VirtualHandle
,
1145 &gEfiStandardErrorDeviceGuid
,
1146 &gEfiSimpleTextOutProtocolGuid
,
1149 if (EFI_ERROR (Status
)) {
1153 // If both ConOut and StdErr incorporate the same Text Out device,
1154 // their MaxMode and QueryData should be the intersection of both.
1156 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1157 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1158 if (EFI_ERROR (Status
)) {
1162 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1163 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1164 gST
->StdErr
= &mStdErr
.TextOut
;
1166 // Update the CRC32 in the EFI System Table header
1169 gBS
->CalculateCrc32 (
1170 (UINT8
*) &gST
->Hdr
,
1171 gST
->Hdr
.HeaderSize
,
1183 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1184 IN EFI_HANDLE ControllerHandle
,
1185 IN EFI_HANDLE ConSplitterVirtualHandle
,
1186 IN EFI_GUID
*DeviceGuid
,
1187 IN EFI_GUID
*InterfaceGuid
,
1192 Routine Description:
1195 (Standard DriverBinding Protocol Stop() function)
1205 Status
= gBS
->OpenProtocol (
1209 This
->DriverBindingHandle
,
1211 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1213 if (EFI_ERROR (Status
)) {
1217 // close the protocol refered.
1219 gBS
->CloseProtocol (
1222 This
->DriverBindingHandle
,
1223 ConSplitterVirtualHandle
1225 gBS
->CloseProtocol (
1228 This
->DriverBindingHandle
,
1237 ConSplitterConInDriverBindingStop (
1238 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1239 IN EFI_HANDLE ControllerHandle
,
1240 IN UINTN NumberOfChildren
,
1241 IN EFI_HANDLE
*ChildHandleBuffer
1245 Routine Description:
1248 (Standard DriverBinding Protocol Stop() function)
1257 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1259 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1260 if (NumberOfChildren
== 0) {
1264 Status
= gBS
->OpenProtocol (
1266 &gEfiSimpleTextInputExProtocolGuid
,
1267 (VOID
**) &TextInEx
,
1268 This
->DriverBindingHandle
,
1270 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1272 if (EFI_ERROR (Status
)) {
1276 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1277 if (EFI_ERROR (Status
)) {
1282 Status
= ConSplitterStop (
1285 mConIn
.VirtualHandle
,
1286 &gEfiConsoleInDeviceGuid
,
1287 &gEfiSimpleTextInProtocolGuid
,
1290 if (EFI_ERROR (Status
)) {
1294 // Delete this console input device's data structures.
1296 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1301 ConSplitterSimplePointerDriverBindingStop (
1302 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1303 IN EFI_HANDLE ControllerHandle
,
1304 IN UINTN NumberOfChildren
,
1305 IN EFI_HANDLE
*ChildHandleBuffer
1309 Routine Description:
1312 (Standard DriverBinding Protocol Stop() function)
1321 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1323 if (NumberOfChildren
== 0) {
1327 Status
= ConSplitterStop (
1330 mConIn
.VirtualHandle
,
1331 &gEfiSimplePointerProtocolGuid
,
1332 &gEfiSimplePointerProtocolGuid
,
1333 (VOID
**) &SimplePointer
1335 if (EFI_ERROR (Status
)) {
1339 // Delete this console input device's data structures.
1341 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1346 ConSplitterConOutDriverBindingStop (
1347 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1348 IN EFI_HANDLE ControllerHandle
,
1349 IN UINTN NumberOfChildren
,
1350 IN EFI_HANDLE
*ChildHandleBuffer
1354 Routine Description:
1357 (Standard DriverBinding Protocol Stop() function)
1366 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1368 if (NumberOfChildren
== 0) {
1372 Status
= ConSplitterStop (
1375 mConOut
.VirtualHandle
,
1376 &gEfiConsoleOutDeviceGuid
,
1377 &gEfiSimpleTextOutProtocolGuid
,
1380 if (EFI_ERROR (Status
)) {
1385 // Delete this console output device's data structures.
1387 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1392 ConSplitterStdErrDriverBindingStop (
1393 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1394 IN EFI_HANDLE ControllerHandle
,
1395 IN UINTN NumberOfChildren
,
1396 IN EFI_HANDLE
*ChildHandleBuffer
1400 Routine Description:
1403 (Standard DriverBinding Protocol Stop() function)
1407 EFI_SUCCESS - Complete successfully.
1412 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1414 if (NumberOfChildren
== 0) {
1418 Status
= ConSplitterStop (
1421 mStdErr
.VirtualHandle
,
1422 &gEfiStandardErrorDeviceGuid
,
1423 &gEfiSimpleTextOutProtocolGuid
,
1426 if (EFI_ERROR (Status
)) {
1430 // Delete this console error out device's data structures.
1432 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1433 if (EFI_ERROR (Status
)) {
1437 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1438 gST
->StandardErrorHandle
= NULL
;
1441 // Update the CRC32 in the EFI System Table header
1444 gBS
->CalculateCrc32 (
1445 (UINT8
*) &gST
->Hdr
,
1446 gST
->Hdr
.HeaderSize
,
1455 ConSplitterGrowBuffer (
1456 IN UINTN SizeOfCount
,
1458 IN OUT VOID
**Buffer
1462 Routine Description:
1463 Take the passed in Buffer of size SizeOfCount and grow the buffer
1464 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1465 bytes. Copy the current data in Buffer to the new version of Buffer
1466 and free the old version of buffer.
1470 SizeOfCount - Size of element in array
1471 Count - Current number of elements in array
1472 Buffer - Bigger version of passed in Buffer with all the data
1475 EFI_SUCCESS - Buffer size has grown
1476 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1487 // grow the buffer to new buffer size,
1488 // copy the old buffer's content to the new-size buffer,
1489 // then free the old buffer.
1491 OldSize
= *Count
* SizeOfCount
;
1492 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1493 NewSize
= *Count
* SizeOfCount
;
1495 Ptr
= AllocateZeroPool (NewSize
);
1497 return EFI_OUT_OF_RESOURCES
;
1500 CopyMem (Ptr
, *Buffer
, OldSize
);
1502 if (*Buffer
!= NULL
) {
1512 ConSplitterTextInAddDevice (
1513 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1514 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1518 Routine Description:
1525 EFI_OUT_OF_RESOURCES
1532 // If the Text In List is full, enlarge it by calling growbuffer().
1534 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1535 Status
= ConSplitterGrowBuffer (
1536 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1537 &Private
->TextInListCount
,
1538 (VOID
**) &Private
->TextInList
1540 if (EFI_ERROR (Status
)) {
1541 return EFI_OUT_OF_RESOURCES
;
1545 // Add the new text-in device data structure into the Text In List.
1547 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1548 Private
->CurrentNumberOfConsoles
++;
1551 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1553 gBS
->CheckEvent (TextIn
->WaitForKey
);
1559 ConSplitterTextInDeleteDevice (
1560 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1561 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1565 Routine Description:
1578 // Remove the specified text-in device data structure from the Text In List,
1579 // and rearrange the remaining data structures in the Text In List.
1581 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1582 if (Private
->TextInList
[Index
] == TextIn
) {
1583 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1584 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1587 Private
->CurrentNumberOfConsoles
--;
1592 return EFI_NOT_FOUND
;
1596 ConSplitterTextInExAddDevice (
1597 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1598 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1604 // If the TextInEx List is full, enlarge it by calling growbuffer().
1606 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1607 Status
= ConSplitterGrowBuffer (
1608 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1609 &Private
->TextInExListCount
,
1610 (VOID
**) &Private
->TextInExList
1612 if (EFI_ERROR (Status
)) {
1613 return EFI_OUT_OF_RESOURCES
;
1617 // Add the new text-in device data structure into the Text In List.
1619 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
1620 Private
->CurrentNumberOfExConsoles
++;
1623 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1625 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
1631 ConSplitterTextInExDeleteDevice (
1632 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1633 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1638 // Remove the specified text-in device data structure from the Text In List,
1639 // and rearrange the remaining data structures in the Text In List.
1641 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
1642 if (Private
->TextInExList
[Index
] == TextInEx
) {
1643 for (Index
= Index
; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
1644 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
1647 Private
->CurrentNumberOfExConsoles
--;
1652 return EFI_NOT_FOUND
;
1656 ConSplitterSimplePointerAddDevice (
1657 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1658 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1662 Routine Description:
1668 EFI_OUT_OF_RESOURCES
1676 // If the Text In List is full, enlarge it by calling growbuffer().
1678 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1679 Status
= ConSplitterGrowBuffer (
1680 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1681 &Private
->PointerListCount
,
1682 (VOID
**) &Private
->PointerList
1684 if (EFI_ERROR (Status
)) {
1685 return EFI_OUT_OF_RESOURCES
;
1689 // Add the new text-in device data structure into the Text In List.
1691 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1692 Private
->CurrentNumberOfPointers
++;
1697 ConSplitterSimplePointerDeleteDevice (
1698 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1699 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1703 Routine Description:
1715 // Remove the specified text-in device data structure from the Text In List,
1716 // and rearrange the remaining data structures in the Text In List.
1718 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1719 if (Private
->PointerList
[Index
] == SimplePointer
) {
1720 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1721 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1724 Private
->CurrentNumberOfPointers
--;
1729 return EFI_NOT_FOUND
;
1734 ConSplitterGrowMapTable (
1735 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1739 Routine Description:
1752 INT32
*TextOutModeMap
;
1753 INT32
*OldTextOutModeMap
;
1757 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1758 OldTextOutModeMap
= Private
->TextOutModeMap
;
1759 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1761 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1762 if (TextOutModeMap
== NULL
) {
1763 return EFI_OUT_OF_RESOURCES
;
1766 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1767 Private
->TextOutModeMap
= TextOutModeMap
;
1770 // If TextOutList has been enlarged, need to realloc the mode map table
1771 // The mode map table is regarded as a two dimension array.
1774 // 0 ---------> TextOutListCount ----> TextOutListCount
1775 // | -------------------------------------------
1782 // -------------------------------------------
1785 if (OldTextOutModeMap
!= NULL
) {
1787 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1789 SrcAddress
= OldTextOutModeMap
;
1792 // Copy the old data to the new one
1794 while (Index
< Private
->TextOutMode
.MaxMode
) {
1795 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1796 TextOutModeMap
+= NewSize
;
1801 // Free the old buffer
1803 FreePool (OldTextOutModeMap
);
1811 ConSplitterAddOutputMode (
1812 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1813 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1817 Routine Description:
1832 MaxMode
= TextOut
->Mode
->MaxMode
;
1833 Private
->TextOutMode
.MaxMode
= MaxMode
;
1836 // Grow the buffer if query data buffer is not large enough to
1837 // hold all the mode supported by the first console.
1839 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1840 Status
= ConSplitterGrowBuffer (
1841 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1842 &Private
->TextOutQueryDataCount
,
1843 (VOID
**) &Private
->TextOutQueryData
1845 if (EFI_ERROR (Status
)) {
1846 return EFI_OUT_OF_RESOURCES
;
1850 // Allocate buffer for the output mode map
1852 Status
= ConSplitterGrowMapTable (Private
);
1853 if (EFI_ERROR (Status
)) {
1854 return EFI_OUT_OF_RESOURCES
;
1857 // As the first textout device, directly add the mode in to QueryData
1858 // and at the same time record the mapping between QueryData and TextOut.
1862 while (Mode
< MaxMode
) {
1863 TextOut
->QueryMode (
1866 &Private
->TextOutQueryData
[Mode
].Columns
,
1867 &Private
->TextOutQueryData
[Mode
].Rows
1869 Private
->TextOutModeMap
[Index
] = Mode
;
1871 Index
+= Private
->TextOutListCount
;
1879 ConSplitterGetIntersection (
1880 IN INT32
*TextOutModeMap
,
1881 IN INT32
*NewlyAddedMap
,
1882 IN UINTN MapStepSize
,
1883 IN UINTN NewMapStepSize
,
1885 OUT INT32
*CurrentMode
1889 INT32
*CurrentMapEntry
;
1890 INT32
*NextMapEntry
;
1891 INT32 CurrentMaxMode
;
1895 CurrentMapEntry
= TextOutModeMap
;
1896 NextMapEntry
= TextOutModeMap
;
1897 CurrentMaxMode
= *MaxMode
;
1898 Mode
= *CurrentMode
;
1900 while (Index
< CurrentMaxMode
) {
1901 if (*NewlyAddedMap
== -1) {
1903 // This mode is not supported any more. Remove it. Special care
1904 // must be taken as this remove will also affect current mode;
1906 if (Index
== *CurrentMode
) {
1908 } else if (Index
< *CurrentMode
) {
1913 if (CurrentMapEntry
!= NextMapEntry
) {
1914 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1917 NextMapEntry
+= MapStepSize
;
1920 CurrentMapEntry
+= MapStepSize
;
1921 NewlyAddedMap
+= NewMapStepSize
;
1925 *CurrentMode
= Mode
;
1932 ConSplitterSyncOutputMode (
1933 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1934 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1938 Routine Description:
1941 Private - Private data structure.
1942 TextOut - Text Out Protocol.
1949 INT32 CurrentMaxMode
;
1952 INT32
*TextOutModeMap
;
1954 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1960 // Must make sure that current mode won't change even if mode number changes
1962 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1963 TextOutModeMap
= Private
->TextOutModeMap
;
1964 StepSize
= Private
->TextOutListCount
;
1965 TextOutQueryData
= Private
->TextOutQueryData
;
1968 // Query all the mode that the newly added TextOut supports
1971 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1972 while (Mode
< TextOut
->Mode
->MaxMode
) {
1973 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1976 // Search the QueryData database to see if they intersects
1979 while (Index
< CurrentMaxMode
) {
1980 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1981 MapTable
[Index
* StepSize
] = Mode
;
1991 // Now search the TextOutModeMap table to find the intersection of supported
1992 // mode between ConSplitter and the newly added device.
1994 ConSplitterGetIntersection (
1999 &Private
->TextOutMode
.MaxMode
,
2000 &Private
->TextOutMode
.Mode
2008 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2013 Routine Description:
2020 EFI_OUT_OF_RESOURCES
2024 UINTN ConOutNumOfConsoles
;
2025 UINTN StdErrNumOfConsoles
;
2026 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2027 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2032 INT32 ConOutMaxMode
;
2033 INT32 StdErrMaxMode
;
2036 INT32
*ConOutModeMap
;
2037 INT32
*StdErrModeMap
;
2038 INT32
*ConOutMapTable
;
2039 INT32
*StdErrMapTable
;
2040 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2041 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2042 BOOLEAN FoundTheSameTextOut
;
2043 UINTN ConOutMapTableSize
;
2044 UINTN StdErrMapTableSize
;
2046 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2047 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2048 ConOutTextOutList
= mConOut
.TextOutList
;
2049 StdErrTextOutList
= mStdErr
.TextOutList
;
2052 FoundTheSameTextOut
= FALSE
;
2053 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2055 while (Indexj
< StdErrNumOfConsoles
) {
2056 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2057 FoundTheSameTextOut
= TRUE
;
2062 StdErrTextOutList
++;
2066 ConOutTextOutList
++;
2069 if (!FoundTheSameTextOut
) {
2073 // Must make sure that current mode won't change even if mode number changes
2075 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2076 ConOutModeMap
= mConOut
.TextOutModeMap
;
2077 ConOutQueryData
= mConOut
.TextOutQueryData
;
2079 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2080 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2081 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2084 // Allocate the map table and set the map table's index to -1.
2086 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2087 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2088 if (ConOutMapTable
== NULL
) {
2089 return EFI_OUT_OF_RESOURCES
;
2092 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2094 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2095 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2096 if (StdErrMapTable
== NULL
) {
2097 return EFI_OUT_OF_RESOURCES
;
2100 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2103 // Find the intersection of the two set of modes. If they actually intersect, the
2104 // correponding entry in the map table is set to 1.
2107 while (Mode
< ConOutMaxMode
) {
2109 // Search the other's QueryData database to see if they intersect
2112 Rows
= ConOutQueryData
[Mode
].Rows
;
2113 Columns
= ConOutQueryData
[Mode
].Columns
;
2114 while (Index
< StdErrMaxMode
) {
2115 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
2116 ConOutMapTable
[Mode
] = 1;
2117 StdErrMapTable
[Index
] = 1;
2127 // Now search the TextOutModeMap table to find the intersection of supported
2128 // mode between ConSplitter and the newly added device.
2130 ConSplitterGetIntersection (
2133 mConOut
.TextOutListCount
,
2135 &(mConOut
.TextOutMode
.MaxMode
),
2136 &(mConOut
.TextOutMode
.Mode
)
2138 if (mConOut
.TextOutMode
.Mode
< 0) {
2139 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2142 ConSplitterGetIntersection (
2145 mStdErr
.TextOutListCount
,
2147 &(mStdErr
.TextOutMode
.MaxMode
),
2148 &(mStdErr
.TextOutMode
.Mode
)
2150 if (mStdErr
.TextOutMode
.Mode
< 0) {
2151 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2154 FreePool (ConOutMapTable
);
2155 FreePool (StdErrMapTable
);
2162 ConSplitterAddGraphicsOutputMode (
2163 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2164 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2165 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2169 Routine Description:
2181 TEXT_OUT_GOP_MODE
*Mode
;
2183 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2184 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2185 TEXT_OUT_GOP_MODE
*ModeBuffer
;
2186 TEXT_OUT_GOP_MODE
*MatchedMode
;
2190 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2191 return EFI_UNSUPPORTED
;
2194 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2196 if (GraphicsOutput
!= NULL
) {
2197 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2199 // This is the first Graphics Output device added
2201 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2202 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2203 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2204 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2205 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2206 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2209 // Allocate resource for the private mode buffer
2211 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
2212 if (ModeBuffer
== NULL
) {
2213 return EFI_OUT_OF_RESOURCES
;
2215 FreePool (Private
->GraphicsOutputModeBuffer
);
2216 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2219 // Store all supported display modes to the private mode buffer
2222 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2223 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2224 if (EFI_ERROR (Status
)) {
2227 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2228 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2234 // Check intersection of display mode
2236 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2237 if (ModeBuffer
== NULL
) {
2238 return EFI_OUT_OF_RESOURCES
;
2241 MatchedMode
= ModeBuffer
;
2242 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2243 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2246 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2247 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2248 if (EFI_ERROR (Status
)) {
2251 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2252 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2261 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2269 // Drop the old mode buffer, assign it to a new one
2271 FreePool (Private
->GraphicsOutputModeBuffer
);
2272 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2275 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2277 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2278 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2279 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2280 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2281 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2282 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2286 // Select a prefered Display mode 800x600
2288 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2289 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2290 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2295 // Prefered mode is not found, set to mode 0
2297 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2302 // Current mode number may need update now, so set it to an invalide mode number
2304 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2307 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2308 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2310 CurrentGraphicsOutputMode
->MaxMode
= 1;
2311 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2312 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2313 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2314 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2315 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2316 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2317 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2318 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2321 // Update the private mode buffer
2323 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2324 ModeBuffer
->HorizontalResolution
= 800;
2325 ModeBuffer
->VerticalResolution
= 600;
2328 // Current mode is unknow now, set it to an invalid mode number 0xffff
2330 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2335 // Force GraphicsOutput mode to be set,
2336 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2338 Private
->HardwareNeedsStarting
= TRUE
;
2339 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2341 Private
->CurrentNumberOfGraphicsOutput
++;
2347 ConSplitterTextOutAddDevice (
2348 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2349 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2350 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2351 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2355 Routine Description:
2366 UINTN CurrentNumOfConsoles
;
2369 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2371 Status
= EFI_SUCCESS
;
2372 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2375 // If the Text Out List is full, enlarge it by calling growbuffer().
2377 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2378 Status
= ConSplitterGrowBuffer (
2379 sizeof (TEXT_OUT_AND_GOP_DATA
),
2380 &Private
->TextOutListCount
,
2381 (VOID
**) &Private
->TextOutList
2383 if (EFI_ERROR (Status
)) {
2384 return EFI_OUT_OF_RESOURCES
;
2387 // Also need to reallocate the TextOutModeMap table
2389 Status
= ConSplitterGrowMapTable (Private
);
2390 if (EFI_ERROR (Status
)) {
2391 return EFI_OUT_OF_RESOURCES
;
2395 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2397 TextAndGop
->TextOut
= TextOut
;
2398 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2399 TextAndGop
->UgaDraw
= UgaDraw
;
2401 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2403 // If No UGA device then use the ConOut device
2405 TextAndGop
->TextOutEnabled
= TRUE
;
2408 // If UGA device use ConOut device only used if UGA screen is in Text mode
2410 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2413 if (CurrentNumOfConsoles
== 0) {
2415 // Add the first device's output mode to console splitter's mode list
2417 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2419 ConSplitterSyncOutputMode (Private
, TextOut
);
2422 Private
->CurrentNumberOfConsoles
++;
2425 // Scan both TextOutList, for the intersection TextOut device
2426 // maybe both ConOut and StdErr incorporate the same Text Out
2427 // device in them, thus the output of both should be synced.
2429 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2431 CurrentMode
= Private
->TextOutMode
.Mode
;
2432 MaxMode
= Private
->TextOutMode
.MaxMode
;
2433 ASSERT (MaxMode
>= 1);
2435 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2436 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2437 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2441 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2443 // We just added a new UGA device in graphics mode
2445 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2446 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2447 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2448 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2450 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2452 // The new console supports the same mode of the current console so sync up
2454 DevNullSyncGopStdOut (Private
);
2457 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2459 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2466 ConSplitterTextOutDeleteDevice (
2467 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2468 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2472 Routine Description:
2483 UINTN CurrentNumOfConsoles
;
2484 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2488 // Remove the specified text-out device data structure from the Text out List,
2489 // and rearrange the remaining data structures in the Text out List.
2491 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2492 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2493 TextOutList
= Private
->TextOutList
;
2494 while (Index
>= 0) {
2495 if (TextOutList
->TextOut
== TextOut
) {
2496 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2497 CurrentNumOfConsoles
--;
2505 // The specified TextOut is not managed by the ConSplitter driver
2508 return EFI_NOT_FOUND
;
2511 if (CurrentNumOfConsoles
== 0) {
2513 // If the number of consoles is zero clear the Dev NULL device
2515 Private
->CurrentNumberOfConsoles
= 0;
2516 Private
->TextOutMode
.MaxMode
= 1;
2517 Private
->TextOutQueryData
[0].Columns
= 80;
2518 Private
->TextOutQueryData
[0].Rows
= 25;
2519 DevNullTextOutSetMode (Private
, 0);
2524 // Max Mode is realy an intersection of the QueryMode command to all
2525 // devices. So we must copy the QueryMode of the first device to
2529 Private
->TextOutQueryData
,
2530 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2533 FreePool (Private
->TextOutModeMap
);
2534 Private
->TextOutModeMap
= NULL
;
2535 TextOutList
= Private
->TextOutList
;
2538 // Add the first TextOut to the QueryData array and ModeMap table
2540 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2543 // Now add one by one
2546 Private
->CurrentNumberOfConsoles
= 1;
2548 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2549 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2551 Private
->CurrentNumberOfConsoles
++;
2555 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2560 // ConSplitter TextIn member functions
2564 ConSplitterTextInReset (
2565 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2566 IN BOOLEAN ExtendedVerification
2570 Routine Description:
2571 Reset the input device and optionaly run diagnostics
2574 This - Protocol instance pointer.
2575 ExtendedVerification - Driver may perform diagnostics on reset.
2578 EFI_SUCCESS - The device was reset.
2579 EFI_DEVICE_ERROR - The device is not functioning properly and could
2585 EFI_STATUS ReturnStatus
;
2586 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2589 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2591 Private
->KeyEventSignalState
= FALSE
;
2594 // return the worst status met
2596 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2597 Status
= Private
->TextInList
[Index
]->Reset (
2598 Private
->TextInList
[Index
],
2599 ExtendedVerification
2601 if (EFI_ERROR (Status
)) {
2602 ReturnStatus
= Status
;
2606 return ReturnStatus
;
2611 ConSplitterTextInPrivateReadKeyStroke (
2612 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2613 OUT EFI_INPUT_KEY
*Key
2617 Routine Description:
2618 Reads the next keystroke from the input device. The WaitForKey Event can
2619 be used to test for existance of a keystroke via WaitForEvent () call.
2622 This - Protocol instance pointer.
2623 Key - Driver may perform diagnostics on reset.
2626 EFI_SUCCESS - The keystroke information was returned.
2627 EFI_NOT_READY - There was no keystroke data availiable.
2628 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2635 EFI_INPUT_KEY CurrentKey
;
2637 Key
->UnicodeChar
= 0;
2638 Key
->ScanCode
= SCAN_NULL
;
2641 // if no physical console input device exists, return EFI_NOT_READY;
2642 // if any physical console input device has key input,
2643 // return the key and EFI_SUCCESS.
2645 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2646 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2647 Private
->TextInList
[Index
],
2650 if (!EFI_ERROR (Status
)) {
2656 return EFI_NOT_READY
;
2660 ConSpliterConssoleControlStdInLocked (
2665 Routine Description:
2666 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2667 the only device locked.
2674 FALSE - StdIn working normally
2678 return mConIn
.PasswordEnabled
;
2683 ConSpliterConsoleControlLockStdInEvent (
2689 Routine Description:
2690 This timer event will fire when StdIn is locked. It will check the key
2691 sequence on StdIn to see if it matches the password. Any error in the
2692 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2693 TRUE the StdIn splitter will not report any input.
2696 (Standard EFI_EVENT_NOTIFY)
2705 CHAR16 BackSpaceString
[2];
2706 CHAR16 SpaceString
[2];
2709 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2710 if (!EFI_ERROR (Status
)) {
2712 // if it's an ENTER, match password
2714 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2715 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2716 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2718 // Password not match
2720 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2721 mConIn
.PwdIndex
= 0;
2724 // Key matches password sequence
2726 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2727 mConIn
.PasswordEnabled
= FALSE
;
2728 Status
= EFI_NOT_READY
;
2730 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2734 if (mConIn
.PwdIndex
> 0) {
2735 BackSpaceString
[0] = CHAR_BACKSPACE
;
2736 BackSpaceString
[1] = 0;
2738 SpaceString
[0] = ' ';
2741 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2742 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2743 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2747 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2749 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2751 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2752 if (mConIn
.PwdIndex
== 0) {
2753 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2756 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2757 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2762 } while (!EFI_ERROR (Status
));
2767 ConSpliterConsoleControlLockStdIn (
2768 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2773 Routine Description:
2774 If Password is NULL unlock the password state variable and set the event
2775 timer. If the Password is too big return an error. If the Password is valid
2776 Copy the Password and enable state variable and then arm the periodic timer
2781 EFI_SUCCESS - Lock the StdIn device
2782 EFI_INVALID_PARAMETER - Password is NULL
2783 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2787 if (Password
== NULL
) {
2788 return EFI_INVALID_PARAMETER
;
2791 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2793 // Currently have a max password size
2795 return EFI_OUT_OF_RESOURCES
;
2798 // Save the password, initialize state variables and arm event timer
2800 StrCpy (mConIn
.Password
, Password
);
2801 mConIn
.PasswordEnabled
= TRUE
;
2802 mConIn
.PwdIndex
= 0;
2803 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2810 ConSplitterTextInReadKeyStroke (
2811 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2812 OUT EFI_INPUT_KEY
*Key
2816 Routine Description:
2817 Reads the next keystroke from the input device. The WaitForKey Event can
2818 be used to test for existance of a keystroke via WaitForEvent () call.
2819 If the ConIn is password locked make it look like no keystroke is availible
2822 This - Protocol instance pointer.
2823 Key - Driver may perform diagnostics on reset.
2826 EFI_SUCCESS - The keystroke information was returned.
2827 EFI_NOT_READY - There was no keystroke data availiable.
2828 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2833 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2835 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2836 if (Private
->PasswordEnabled
) {
2838 // If StdIn Locked return not ready
2840 return EFI_NOT_READY
;
2843 Private
->KeyEventSignalState
= FALSE
;
2845 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2850 ConSplitterTextInWaitForKey (
2856 Routine Description:
2857 This event agregates all the events of the ConIn devices in the spliter.
2858 If the ConIn is password locked then return.
2859 If any events of physical ConIn devices are signaled, signal the ConIn
2860 spliter event. This will cause the calling code to call
2861 ConSplitterTextInReadKeyStroke ().
2864 Event - The Event assoicated with callback.
2865 Context - Context registered when Event was created.
2873 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2876 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2877 if (Private
->PasswordEnabled
) {
2879 // If StdIn Locked return not ready
2885 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2887 if (Private
->KeyEventSignalState
) {
2888 gBS
->SignalEvent (Event
);
2892 // if any physical console input device has key input, signal the event.
2894 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2895 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2896 if (!EFI_ERROR (Status
)) {
2897 gBS
->SignalEvent (Event
);
2898 Private
->KeyEventSignalState
= TRUE
;
2907 IN EFI_KEY_DATA
*RegsiteredData
,
2908 IN EFI_KEY_DATA
*InputData
2912 Routine Description:
2916 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
2917 state data for the key that was registered.
2918 InputData - A pointer to a buffer that is filled in with the keystroke
2919 state data for the key that was pressed.
2922 TRUE - Key be pressed matches a registered key.
2923 FLASE - Match failed.
2927 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
2929 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
2930 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
2935 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
2937 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
2938 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
2941 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
2942 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
2951 // Simple Text Input Ex protocol functions
2956 ConSplitterTextInResetEx (
2957 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2958 IN BOOLEAN ExtendedVerification
2962 Routine Description:
2963 Reset the input device and optionaly run diagnostics
2966 This - Protocol instance pointer.
2967 ExtendedVerification - Driver may perform diagnostics on reset.
2970 EFI_SUCCESS - The device was reset.
2971 EFI_DEVICE_ERROR - The device is not functioning properly and could
2977 EFI_STATUS ReturnStatus
;
2978 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2981 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2983 Private
->KeyEventSignalState
= FALSE
;
2986 // return the worst status met
2988 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
2989 Status
= Private
->TextInExList
[Index
]->Reset (
2990 Private
->TextInExList
[Index
],
2991 ExtendedVerification
2993 if (EFI_ERROR (Status
)) {
2994 ReturnStatus
= Status
;
2998 return ReturnStatus
;
3004 ConSplitterTextInReadKeyStrokeEx (
3005 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3006 OUT EFI_KEY_DATA
*KeyData
3010 Routine Description:
3011 Reads the next keystroke from the input device. The WaitForKey Event can
3012 be used to test for existance of a keystroke via WaitForEvent () call.
3015 This - Protocol instance pointer.
3016 KeyData - A pointer to a buffer that is filled in with the keystroke
3017 state data for the key that was pressed.
3020 EFI_SUCCESS - The keystroke information was returned.
3021 EFI_NOT_READY - There was no keystroke data availiable.
3022 EFI_DEVICE_ERROR - The keystroke information was not returned due to
3024 EFI_INVALID_PARAMETER - KeyData is NULL.
3028 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3031 EFI_KEY_DATA CurrentKeyData
;
3034 if (KeyData
== NULL
) {
3035 return EFI_INVALID_PARAMETER
;
3038 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3039 if (Private
->PasswordEnabled
) {
3041 // If StdIn Locked return not ready
3043 return EFI_NOT_READY
;
3046 Private
->KeyEventSignalState
= FALSE
;
3048 KeyData
->Key
.UnicodeChar
= 0;
3049 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3052 // if no physical console input device exists, return EFI_NOT_READY;
3053 // if any physical console input device has key input,
3054 // return the key and EFI_SUCCESS.
3056 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3057 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3058 Private
->TextInExList
[Index
],
3061 if (!EFI_ERROR (Status
)) {
3062 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3067 return EFI_NOT_READY
;
3072 ConSplitterTextInSetState (
3073 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3074 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3078 Routine Description:
3079 Set certain state for the input device.
3082 This - Protocol instance pointer.
3083 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
3084 state for the input device.
3087 EFI_SUCCESS - The device state was set successfully.
3088 EFI_DEVICE_ERROR - The device is not functioning correctly and could
3089 not have the setting adjusted.
3090 EFI_UNSUPPORTED - The device does not have the ability to set its state.
3091 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
3095 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3099 if (KeyToggleState
== NULL
) {
3100 return EFI_INVALID_PARAMETER
;
3103 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3106 // if no physical console input device exists, return EFI_SUCCESS;
3107 // otherwise return the status of setting state of physical console input device
3109 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3110 Status
= Private
->TextInExList
[Index
]->SetState (
3111 Private
->TextInExList
[Index
],
3114 if (EFI_ERROR (Status
)) {
3125 ConSplitterTextInRegisterKeyNotify (
3126 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3127 IN EFI_KEY_DATA
*KeyData
,
3128 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3129 OUT EFI_HANDLE
*NotifyHandle
3133 Routine Description:
3134 Register a notification function for a particular keystroke for the input device.
3137 This - Protocol instance pointer.
3138 KeyData - A pointer to a buffer that is filled in with the keystroke
3139 information data for the key that was pressed.
3140 KeyNotificationFunction - Points to the function to be called when the key
3141 sequence is typed specified by KeyData.
3142 NotifyHandle - Points to the unique handle assigned to the registered notification.
3145 EFI_SUCCESS - The notification function was registered successfully.
3146 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
3147 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
3151 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3154 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3156 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3159 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3160 return EFI_INVALID_PARAMETER
;
3163 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3166 // if no physical console input device exists,
3167 // return EFI_SUCCESS directly.
3169 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3174 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3176 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3177 CurrentNotify
= CR (
3179 TEXT_IN_EX_SPLITTER_NOTIFY
,
3181 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
3183 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3184 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3185 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
3192 // Allocate resource to save the notification function
3194 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3195 if (NewNotify
== NULL
) {
3196 return EFI_OUT_OF_RESOURCES
;
3198 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->CurrentNumberOfExConsoles
);
3199 if (NewNotify
->NotifyHandleList
== NULL
) {
3200 gBS
->FreePool (NewNotify
);
3201 return EFI_OUT_OF_RESOURCES
;
3203 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3204 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3205 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
3208 // Return the wrong status of registering key notify of
3209 // physical console input device if meet problems
3211 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3212 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3213 Private
->TextInExList
[Index
],
3215 KeyNotificationFunction
,
3216 &NewNotify
->NotifyHandleList
[Index
]
3218 if (EFI_ERROR (Status
)) {
3219 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3220 gBS
->FreePool (NewNotify
);
3226 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
3228 Status
= gBS
->InstallMultipleProtocolInterfaces (
3229 &NewNotify
->NotifyHandle
,
3230 &gSimpleTextInExNotifyGuid
,
3234 ASSERT_EFI_ERROR (Status
);
3236 InsertTailList (&mConIn
.NotifyList
, &NewNotify
->NotifyEntry
);
3238 *NotifyHandle
= NewNotify
->NotifyHandle
;
3246 ConSplitterTextInUnregisterKeyNotify (
3247 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3248 IN EFI_HANDLE NotificationHandle
3252 Routine Description:
3253 Remove a registered notification function from a particular keystroke.
3256 This - Protocol instance pointer.
3257 NotificationHandle - The handle of the notification function being unregistered.
3260 EFI_SUCCESS - The notification function was unregistered successfully.
3261 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
3262 EFI_NOT_FOUND - Can not find the matching entry in database.
3266 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3269 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3272 if (NotificationHandle
== NULL
) {
3273 return EFI_INVALID_PARAMETER
;
3276 Status
= gBS
->OpenProtocol (
3278 &gSimpleTextInExNotifyGuid
,
3282 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
3284 if (EFI_ERROR (Status
)) {
3285 return EFI_INVALID_PARAMETER
;
3288 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3291 // if no physical console input device exists,
3292 // return EFI_SUCCESS directly.
3294 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3298 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3299 CurrentNotify
= CR (Link
, TEXT_IN_EX_SPLITTER_NOTIFY
, NotifyEntry
, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
);
3300 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
3301 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3302 Status
= Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3303 Private
->TextInExList
[Index
],
3304 CurrentNotify
->NotifyHandleList
[Index
]
3306 if (EFI_ERROR (Status
)) {
3310 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3311 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3312 CurrentNotify
->NotifyHandle
,
3313 &gSimpleTextInExNotifyGuid
,
3317 ASSERT_EFI_ERROR (Status
);
3318 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3319 gBS
->FreePool (CurrentNotify
);
3324 return EFI_NOT_FOUND
;
3332 ConSplitterSimplePointerReset (
3333 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3334 IN BOOLEAN ExtendedVerification
3338 Routine Description:
3339 Reset the input device and optionaly run diagnostics
3342 This - Protocol instance pointer.
3343 ExtendedVerification - Driver may perform diagnostics on reset.
3346 EFI_SUCCESS - The device was reset.
3347 EFI_DEVICE_ERROR - The device is not functioning properly and could
3353 EFI_STATUS ReturnStatus
;
3354 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3357 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3359 Private
->InputEventSignalState
= FALSE
;
3361 if (Private
->CurrentNumberOfPointers
== 0) {
3365 // return the worst status met
3367 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3368 Status
= Private
->PointerList
[Index
]->Reset (
3369 Private
->PointerList
[Index
],
3370 ExtendedVerification
3372 if (EFI_ERROR (Status
)) {
3373 ReturnStatus
= Status
;
3377 return ReturnStatus
;
3383 ConSplitterSimplePointerPrivateGetState (
3384 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3385 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3389 Routine Description:
3390 Reads the next keystroke from the input device. The WaitForKey Event can
3391 be used to test for existance of a keystroke via WaitForEvent () call.
3394 This - Protocol instance pointer.
3398 EFI_SUCCESS - The keystroke information was returned.
3399 EFI_NOT_READY - There was no keystroke data availiable.
3400 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3406 EFI_STATUS ReturnStatus
;
3408 EFI_SIMPLE_POINTER_STATE CurrentState
;
3410 State
->RelativeMovementX
= 0;
3411 State
->RelativeMovementY
= 0;
3412 State
->RelativeMovementZ
= 0;
3413 State
->LeftButton
= FALSE
;
3414 State
->RightButton
= FALSE
;
3417 // if no physical console input device exists, return EFI_NOT_READY;
3418 // if any physical console input device has key input,
3419 // return the key and EFI_SUCCESS.
3421 ReturnStatus
= EFI_NOT_READY
;
3422 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3424 Status
= Private
->PointerList
[Index
]->GetState (
3425 Private
->PointerList
[Index
],
3428 if (!EFI_ERROR (Status
)) {
3429 if (ReturnStatus
== EFI_NOT_READY
) {
3430 ReturnStatus
= EFI_SUCCESS
;
3433 if (CurrentState
.LeftButton
) {
3434 State
->LeftButton
= TRUE
;
3437 if (CurrentState
.RightButton
) {
3438 State
->RightButton
= TRUE
;
3441 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
3442 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
3445 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
3446 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
3449 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
3450 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
3452 } else if (Status
== EFI_DEVICE_ERROR
) {
3453 ReturnStatus
= EFI_DEVICE_ERROR
;
3457 return ReturnStatus
;
3462 ConSplitterSimplePointerGetState (
3463 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3464 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3468 Routine Description:
3469 Reads the next keystroke from the input device. The WaitForKey Event can
3470 be used to test for existance of a keystroke via WaitForEvent () call.
3471 If the ConIn is password locked make it look like no keystroke is availible
3474 This - Protocol instance pointer.
3478 EFI_SUCCESS - The keystroke information was returned.
3479 EFI_NOT_READY - There was no keystroke data availiable.
3480 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
3485 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3487 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3488 if (Private
->PasswordEnabled
) {
3490 // If StdIn Locked return not ready
3492 return EFI_NOT_READY
;
3495 Private
->InputEventSignalState
= FALSE
;
3497 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
3502 ConSplitterSimplePointerWaitForInput (
3508 Routine Description:
3509 This event agregates all the events of the ConIn devices in the spliter.
3510 If the ConIn is password locked then return.
3511 If any events of physical ConIn devices are signaled, signal the ConIn
3512 spliter event. This will cause the calling code to call
3513 ConSplitterTextInReadKeyStroke ().
3516 Event - The Event assoicated with callback.
3517 Context - Context registered when Event was created.
3525 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3528 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3529 if (Private
->PasswordEnabled
) {
3531 // If StdIn Locked return not ready
3537 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3539 if (Private
->InputEventSignalState
) {
3540 gBS
->SignalEvent (Event
);
3544 // if any physical console input device has key input, signal the event.
3546 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3547 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
3548 if (!EFI_ERROR (Status
)) {
3549 gBS
->SignalEvent (Event
);
3550 Private
->InputEventSignalState
= TRUE
;
3557 ConSplitterTextOutReset (
3558 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3559 IN BOOLEAN ExtendedVerification
3563 Routine Description:
3564 Reset the text output device hardware and optionaly run diagnostics
3567 This - Protocol instance pointer.
3568 ExtendedVerification - Driver may perform more exhaustive verfication
3569 operation of the device during reset.
3572 EFI_SUCCESS - The text output device was reset.
3573 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
3579 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3581 EFI_STATUS ReturnStatus
;
3583 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3586 // return the worst status met
3588 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3590 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3592 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
3593 Private
->TextOutList
[Index
].TextOut
,
3594 ExtendedVerification
3596 if (EFI_ERROR (Status
)) {
3597 ReturnStatus
= Status
;
3602 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
3604 Status
= DevNullTextOutSetMode (Private
, 0);
3605 if (EFI_ERROR (Status
)) {
3606 ReturnStatus
= Status
;
3609 return ReturnStatus
;
3614 ConSplitterTextOutOutputString (
3615 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3620 Routine Description:
3621 Write a Unicode string to the output device.
3624 This - Protocol instance pointer.
3625 String - The NULL-terminated Unicode string to be displayed on the output
3626 device(s). All output devices must also support the Unicode
3627 drawing defined in this file.
3630 EFI_SUCCESS - The string was output to the device.
3631 EFI_DEVICE_ERROR - The device reported an error while attempting to output
3633 EFI_UNSUPPORTED - The output device's mode is not currently in a
3635 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
3636 characters in the Unicode string could not be
3637 rendered and were skipped.
3642 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3644 UINTN BackSpaceCount
;
3645 EFI_STATUS ReturnStatus
;
3646 CHAR16
*TargetString
;
3648 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3650 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3653 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3654 if (*TargetString
== CHAR_BACKSPACE
) {
3660 if (BackSpaceCount
== 0) {
3661 TargetString
= WString
;
3663 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3664 StrCpy (TargetString
, WString
);
3667 // return the worst status met
3669 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3670 if (EFI_ERROR (Status
)) {
3671 ReturnStatus
= Status
;
3674 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3676 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3677 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3678 Private
->TextOutList
[Index
].TextOut
,
3681 if (EFI_ERROR (Status
)) {
3682 ReturnStatus
= Status
;
3687 if (BackSpaceCount
) {
3688 FreePool (TargetString
);
3691 return ReturnStatus
;
3696 ConSplitterTextOutTestString (
3697 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3702 Routine Description:
3703 Verifies that all characters in a Unicode string can be output to the
3707 This - Protocol instance pointer.
3708 String - The NULL-terminated Unicode string to be examined for the output
3712 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3713 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3714 rendered by one or more of the output devices mapped
3720 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3722 EFI_STATUS ReturnStatus
;
3724 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3727 // return the worst status met
3729 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3730 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3731 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3732 Private
->TextOutList
[Index
].TextOut
,
3735 if (EFI_ERROR (Status
)) {
3736 ReturnStatus
= Status
;
3741 // There is no DevNullTextOutTestString () since a Unicode buffer would
3742 // always return EFI_SUCCESS.
3743 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3745 return ReturnStatus
;
3750 ConSplitterTextOutQueryMode (
3751 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3752 IN UINTN ModeNumber
,
3758 Routine Description:
3759 Returns information for an available text mode that the output device(s)
3763 This - Protocol instance pointer.
3764 ModeNumber - The mode number to return information on.
3765 Columns, Rows - Returns the geometry of the text output device for the
3766 requested ModeNumber.
3769 EFI_SUCCESS - The requested mode information was returned.
3770 EFI_DEVICE_ERROR - The device had an error and could not
3771 complete the request.
3772 EFI_UNSUPPORTED - The mode number was not valid.
3776 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3778 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3781 // Check whether param ModeNumber is valid.
3782 // ModeNumber should be within range 0 ~ MaxMode - 1.
3784 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3785 return EFI_UNSUPPORTED
;
3788 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3789 return EFI_UNSUPPORTED
;
3792 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3793 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3795 if (*Columns
<= 0 && *Rows
<= 0) {
3796 return EFI_UNSUPPORTED
;
3805 ConSplitterTextOutSetMode (
3806 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3811 Routine Description:
3812 Sets the output device(s) to a specified mode.
3815 This - Protocol instance pointer.
3816 ModeNumber - The mode number to set.
3819 EFI_SUCCESS - The requested text mode was set.
3820 EFI_DEVICE_ERROR - The device had an error and
3821 could not complete the request.
3822 EFI_UNSUPPORTED - The mode number was not valid.
3827 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3829 INT32
*TextOutModeMap
;
3830 EFI_STATUS ReturnStatus
;
3832 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3835 // Check whether param ModeNumber is valid.
3836 // ModeNumber should be within range 0 ~ MaxMode - 1.
3838 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3839 return EFI_UNSUPPORTED
;
3842 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3843 return EFI_UNSUPPORTED
;
3846 // If the mode is being set to the curent mode, then just clear the screen and return.
3848 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3849 return ConSplitterTextOutClearScreen (This
);
3852 // return the worst status met
3854 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3855 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3857 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3858 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3859 Private
->TextOutList
[Index
].TextOut
,
3860 TextOutModeMap
[Index
]
3863 // If this console device is based on a UGA device, then sync up the bitmap from
3864 // the UGA splitter and reclear the text portion of the display in the new mode.
3866 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3867 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3870 if (EFI_ERROR (Status
)) {
3871 ReturnStatus
= Status
;
3876 // The DevNull Console will support any possible mode as it allocates memory
3878 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3879 if (EFI_ERROR (Status
)) {
3880 ReturnStatus
= Status
;
3883 return ReturnStatus
;
3888 ConSplitterTextOutSetAttribute (
3889 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3894 Routine Description:
3895 Sets the background and foreground colors for the OutputString () and
3896 ClearScreen () functions.
3899 This - Protocol instance pointer.
3900 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3901 bits 4..6 are the background color. All other bits are undefined
3902 and must be zero. The valid Attributes are defined in this file.
3905 EFI_SUCCESS - The attribute was set.
3906 EFI_DEVICE_ERROR - The device had an error and
3907 could not complete the request.
3908 EFI_UNSUPPORTED - The attribute requested is not defined.
3913 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3915 EFI_STATUS ReturnStatus
;
3917 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3920 // Check whether param Attribute is valid.
3922 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3923 return EFI_UNSUPPORTED
;
3927 // return the worst status met
3929 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3931 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3932 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3933 Private
->TextOutList
[Index
].TextOut
,
3936 if (EFI_ERROR (Status
)) {
3937 ReturnStatus
= Status
;
3942 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3944 return ReturnStatus
;
3949 ConSplitterTextOutClearScreen (
3950 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3954 Routine Description:
3955 Clears the output device(s) display to the currently selected background
3959 This - Protocol instance pointer.
3962 EFI_SUCCESS - The operation completed successfully.
3963 EFI_DEVICE_ERROR - The device had an error and
3964 could not complete the request.
3965 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3970 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3972 EFI_STATUS ReturnStatus
;
3974 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3977 // return the worst status met
3979 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3981 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3982 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3983 if (EFI_ERROR (Status
)) {
3984 ReturnStatus
= Status
;
3989 Status
= DevNullTextOutClearScreen (Private
);
3990 if (EFI_ERROR (Status
)) {
3991 ReturnStatus
= Status
;
3994 return ReturnStatus
;
3999 ConSplitterTextOutSetCursorPosition (
4000 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4006 Routine Description:
4007 Sets the current coordinates of the cursor position
4010 This - Protocol instance pointer.
4011 Column, Row - the position to set the cursor to. Must be greater than or
4012 equal to zero and less than the number of columns and rows
4016 EFI_SUCCESS - The operation completed successfully.
4017 EFI_DEVICE_ERROR - The device had an error and
4018 could not complete the request.
4019 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
4020 cursor position is invalid for the current mode.
4025 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4027 EFI_STATUS ReturnStatus
;
4030 INT32
*TextOutModeMap
;
4034 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4035 TextOutModeMap
= NULL
;
4036 ModeNumber
= Private
->TextOutMode
.Mode
;
4039 // Get current MaxColumn and MaxRow from intersection map
4041 if (Private
->TextOutModeMap
!= NULL
) {
4042 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4043 CurrentMode
= *TextOutModeMap
;
4045 CurrentMode
= ModeNumber
;
4048 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4049 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4051 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4052 return EFI_UNSUPPORTED
;
4055 // return the worst status met
4057 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4059 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4060 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4061 Private
->TextOutList
[Index
].TextOut
,
4065 if (EFI_ERROR (Status
)) {
4066 ReturnStatus
= Status
;
4071 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
4073 return ReturnStatus
;
4078 ConSplitterTextOutEnableCursor (
4079 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4084 Routine Description:
4085 Makes the cursor visible or invisible
4088 This - Protocol instance pointer.
4089 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
4090 set to be invisible.
4093 EFI_SUCCESS - The operation completed successfully.
4094 EFI_DEVICE_ERROR - The device had an error and could not complete the
4095 request, or the device does not support changing
4097 EFI_UNSUPPORTED - The output device is not in a valid text mode.
4102 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4104 EFI_STATUS ReturnStatus
;
4106 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4109 // return the worst status met
4111 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4113 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4114 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
4115 Private
->TextOutList
[Index
].TextOut
,
4118 if (EFI_ERROR (Status
)) {
4119 ReturnStatus
= Status
;
4124 DevNullTextOutEnableCursor (Private
, Visible
);
4126 return ReturnStatus
;