3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Console Splitter Driver. Any Handle that attatched
19 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
21 So far it works like any other driver by opening a SimpleTextIn and/or
22 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
23 difference is this driver does not layer a protocol on the passed in
24 handle, or construct a child handle like a standard device or bus driver.
25 This driver produces three virtual handles as children, one for console input
26 splitter, one for console output splitter and one for error output splitter.
27 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
28 identify the splitter type.
30 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
31 and Console I/O protocol, will be produced in the driver entry point.
32 The virtual handle are added on driver entry and never removed.
33 Such design ensures sytem function well during none console device situation.
37 #include "ConSplitter.h"
42 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
43 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
46 ConSplitterTextInReset
,
47 ConSplitterTextInReadKeyStroke
,
51 (EFI_SIMPLE_TEXT_IN_PROTOCOL
**) NULL
,
55 ConSplitterSimplePointerReset
,
56 ConSplitterSimplePointerGetState
,
58 (EFI_SIMPLE_POINTER_MODE
*) NULL
68 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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,
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
91 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
92 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
95 ConSplitterTextOutReset
,
96 ConSplitterTextOutOutputString
,
97 ConSplitterTextOutTestString
,
98 ConSplitterTextOutQueryMode
,
99 ConSplitterTextOutSetMode
,
100 ConSplitterTextOutSetAttribute
,
101 ConSplitterTextOutClearScreen
,
102 ConSplitterTextOutSetCursorPosition
,
103 ConSplitterTextOutEnableCursor
,
104 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
114 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
116 ConSpliterUgaDrawGetMode
,
117 ConSpliterUgaDrawSetMode
,
124 (EFI_UGA_PIXEL
*) NULL
,
127 ConSpliterGraphicsOutputQueryMode
,
128 ConSpliterGraphicsOutputSetMode
,
129 ConSpliterGraphicsOutputBlt
,
132 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
133 (TEXT_OUT_GOP_MODE
*) NULL
,
138 ConSpliterConsoleControlGetMode
,
139 ConSpliterConsoleControlSetMode
,
140 ConSpliterConsoleControlLockStdIn
144 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
146 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
150 EfiConsoleControlScreenText
,
157 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
158 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
161 ConSplitterTextOutReset
,
162 ConSplitterTextOutOutputString
,
163 ConSplitterTextOutTestString
,
164 ConSplitterTextOutQueryMode
,
165 ConSplitterTextOutSetMode
,
166 ConSplitterTextOutSetAttribute
,
167 ConSplitterTextOutClearScreen
,
168 ConSplitterTextOutSetCursorPosition
,
169 ConSplitterTextOutEnableCursor
,
170 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
180 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
182 ConSpliterUgaDrawGetMode
,
183 ConSpliterUgaDrawSetMode
,
190 (EFI_UGA_PIXEL
*) NULL
,
193 ConSpliterGraphicsOutputQueryMode
,
194 ConSpliterGraphicsOutputSetMode
,
195 ConSpliterGraphicsOutputBlt
,
198 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
199 (TEXT_OUT_GOP_MODE
*) NULL
,
204 ConSpliterConsoleControlGetMode
,
205 ConSpliterConsoleControlSetMode
,
206 ConSpliterConsoleControlLockStdIn
210 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
212 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
216 EfiConsoleControlScreenText
,
223 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
224 ConSplitterConInDriverBindingSupported
,
225 ConSplitterConInDriverBindingStart
,
226 ConSplitterConInDriverBindingStop
,
232 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
233 ConSplitterSimplePointerDriverBindingSupported
,
234 ConSplitterSimplePointerDriverBindingStart
,
235 ConSplitterSimplePointerDriverBindingStop
,
241 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
242 ConSplitterConOutDriverBindingSupported
,
243 ConSplitterConOutDriverBindingStart
,
244 ConSplitterConOutDriverBindingStop
,
250 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
251 ConSplitterStdErrDriverBindingSupported
,
252 ConSplitterStdErrDriverBindingStart
,
253 ConSplitterStdErrDriverBindingStop
,
261 ConSplitterDriverEntry (
262 IN EFI_HANDLE ImageHandle
,
263 IN EFI_SYSTEM_TABLE
*SystemTable
268 Intialize a virtual console device to act as an agrigator of physical console
272 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
273 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
282 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
283 // The virtual handles will always exist even if no console exist in the
284 // system. This is need to support hotplug devices like USB.
287 // Create virtual device handle for StdErr Splitter
289 Status
= ConSplitterTextOutConstructor (&mStdErr
);
290 if (!EFI_ERROR (Status
)) {
291 Status
= gBS
->InstallMultipleProtocolInterfaces (
292 &mStdErr
.VirtualHandle
,
293 &gEfiSimpleTextOutProtocolGuid
,
295 &gEfiPrimaryStandardErrorDeviceGuid
,
301 // Create virtual device handle for ConIn Splitter
303 Status
= ConSplitterTextInConstructor (&mConIn
);
304 if (!EFI_ERROR (Status
)) {
305 Status
= gBS
->InstallMultipleProtocolInterfaces (
306 &mConIn
.VirtualHandle
,
307 &gEfiSimpleTextInProtocolGuid
,
309 &gEfiSimplePointerProtocolGuid
,
310 &mConIn
.SimplePointer
,
311 &gEfiPrimaryConsoleInDeviceGuid
,
315 if (!EFI_ERROR (Status
)) {
317 // Update the EFI System Table with new virtual console
319 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
320 gST
->ConIn
= &mConIn
.TextIn
;
324 // Create virtual device handle for ConOut Splitter
326 Status
= ConSplitterTextOutConstructor (&mConOut
);
327 if (!EFI_ERROR (Status
)) {
328 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
330 // In EFI mode, UGA Draw protocol is installed
332 Status
= gBS
->InstallMultipleProtocolInterfaces (
333 &mConOut
.VirtualHandle
,
334 &gEfiSimpleTextOutProtocolGuid
,
336 &gEfiUgaDrawProtocolGuid
,
338 &gEfiConsoleControlProtocolGuid
,
339 &mConOut
.ConsoleControl
,
340 &gEfiPrimaryConsoleOutDeviceGuid
,
346 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
348 Status
= gBS
->InstallMultipleProtocolInterfaces (
349 &mConOut
.VirtualHandle
,
350 &gEfiSimpleTextOutProtocolGuid
,
352 &gEfiGraphicsOutputProtocolGuid
,
353 &mConOut
.GraphicsOutput
,
354 &gEfiConsoleControlProtocolGuid
,
355 &mConOut
.ConsoleControl
,
356 &gEfiPrimaryConsoleOutDeviceGuid
,
362 if (!EFI_ERROR (Status
)) {
364 // Update the EFI System Table with new virtual console
366 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
367 gST
->ConOut
= &mConOut
.TextOut
;
372 // Update the CRC32 in the EFI System Table header
375 gBS
->CalculateCrc32 (
386 ConSplitterTextInConstructor (
387 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
393 Construct the ConSplitter.
397 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
400 EFI_OUT_OF_RESOURCES - Out of resources.
407 // Initilize console input splitter's private data.
409 Status
= ConSplitterGrowBuffer (
410 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
411 &ConInPrivate
->TextInListCount
,
412 (VOID
**) &ConInPrivate
->TextInList
414 if (EFI_ERROR (Status
)) {
415 return EFI_OUT_OF_RESOURCES
;
418 // Create Event to support locking StdIn Device
420 Status
= gBS
->CreateEvent (
421 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
423 ConSpliterConsoleControlLockStdInEvent
,
425 &ConInPrivate
->LockEvent
427 ASSERT_EFI_ERROR (Status
);
429 Status
= gBS
->CreateEvent (
430 EFI_EVENT_NOTIFY_WAIT
,
432 ConSplitterTextInWaitForKey
,
434 &ConInPrivate
->TextIn
.WaitForKey
436 ASSERT_EFI_ERROR (Status
);
438 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
440 Status
= ConSplitterGrowBuffer (
441 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
442 &ConInPrivate
->PointerListCount
,
443 (VOID
**) &ConInPrivate
->PointerList
445 if (EFI_ERROR (Status
)) {
446 return EFI_OUT_OF_RESOURCES
;
449 Status
= gBS
->CreateEvent (
450 EFI_EVENT_NOTIFY_WAIT
,
452 ConSplitterSimplePointerWaitForInput
,
454 &ConInPrivate
->SimplePointer
.WaitForInput
462 ConSplitterTextOutConstructor (
463 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
469 // Initilize console output splitter's private data.
471 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
473 Status
= ConSplitterGrowBuffer (
474 sizeof (TEXT_OUT_AND_GOP_DATA
),
475 &ConOutPrivate
->TextOutListCount
,
476 (VOID
**) &ConOutPrivate
->TextOutList
478 if (EFI_ERROR (Status
)) {
479 return EFI_OUT_OF_RESOURCES
;
482 Status
= ConSplitterGrowBuffer (
483 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
484 &ConOutPrivate
->TextOutQueryDataCount
,
485 (VOID
**) &ConOutPrivate
->TextOutQueryData
487 if (EFI_ERROR (Status
)) {
488 return EFI_OUT_OF_RESOURCES
;
491 // Setup the DevNullTextOut console to 80 x 25
493 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
494 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
495 DevNullTextOutSetMode (ConOutPrivate
, 0);
497 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
499 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
501 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
504 // Setup resource for mode information in Graphics Output Protocol interface
506 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
507 return EFI_OUT_OF_RESOURCES
;
509 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
510 return EFI_OUT_OF_RESOURCES
;
513 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
515 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
516 return EFI_OUT_OF_RESOURCES
;
518 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
519 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
522 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
523 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
524 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
526 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
527 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
528 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
529 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
530 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
532 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
534 // Initial current mode to unknow state, and then set to mode 0
536 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
537 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
545 ConSplitterSupported (
546 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
547 IN EFI_HANDLE ControllerHandle
,
553 Generic Supported Check
556 This - Pointer to protocol.
557 ControllerHandle - Controller Handle.
562 EFI_UNSUPPORTED - unsupported.
563 EFI_SUCCESS - operation is OK.
571 // Make sure the Console Splitter does not attempt to attach to itself
573 if (ControllerHandle
== mConIn
.VirtualHandle
) {
574 return EFI_UNSUPPORTED
;
577 if (ControllerHandle
== mConOut
.VirtualHandle
) {
578 return EFI_UNSUPPORTED
;
581 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
582 return EFI_UNSUPPORTED
;
585 // Check to see whether the handle has the ConsoleInDevice GUID on it
587 Status
= gBS
->OpenProtocol (
591 This
->DriverBindingHandle
,
593 EFI_OPEN_PROTOCOL_BY_DRIVER
596 if (EFI_ERROR (Status
)) {
603 This
->DriverBindingHandle
,
613 ConSplitterConInDriverBindingSupported (
614 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
615 IN EFI_HANDLE ControllerHandle
,
616 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
621 Console In Supported Check
624 This - Pointer to protocol.
625 ControllerHandle - Controller handle.
626 RemainingDevicePath - Remaining device path.
634 return ConSplitterSupported (
637 &gEfiConsoleInDeviceGuid
644 ConSplitterSimplePointerDriverBindingSupported (
645 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
646 IN EFI_HANDLE ControllerHandle
,
647 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
652 Standard Error Supported Check
655 This - Pointer to protocol.
656 ControllerHandle - Controller handle.
657 RemainingDevicePath - Remaining device path.
665 return ConSplitterSupported (
668 &gEfiSimplePointerProtocolGuid
675 ConSplitterConOutDriverBindingSupported (
676 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
677 IN EFI_HANDLE ControllerHandle
,
678 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
683 Console Out Supported Check
686 This - Pointer to protocol.
687 ControllerHandle - Controller handle.
688 RemainingDevicePath - Remaining device path.
696 return ConSplitterSupported (
699 &gEfiConsoleOutDeviceGuid
706 ConSplitterStdErrDriverBindingSupported (
707 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
708 IN EFI_HANDLE ControllerHandle
,
709 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
714 Standard Error Supported Check
717 This - Pointer to protocol.
718 ControllerHandle - Controller handle.
719 RemainingDevicePath - Remaining device path.
727 return ConSplitterSupported (
730 &gEfiStandardErrorDeviceGuid
738 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
739 IN EFI_HANDLE ControllerHandle
,
740 IN EFI_HANDLE ConSplitterVirtualHandle
,
741 IN EFI_GUID
*DeviceGuid
,
742 IN EFI_GUID
*InterfaceGuid
,
748 Start ConSplitter on ControllerHandle, and create the virtual
749 agrogated console device on first call Start for a SimpleTextIn handle.
752 (Standard DriverBinding Protocol Start() function)
755 EFI_ERROR if a SimpleTextIn protocol is not started.
763 // Check to see whether the handle has the ConsoleInDevice GUID on it
765 Status
= gBS
->OpenProtocol (
769 This
->DriverBindingHandle
,
771 EFI_OPEN_PROTOCOL_BY_DRIVER
773 if (EFI_ERROR (Status
)) {
777 Status
= gBS
->OpenProtocol (
781 This
->DriverBindingHandle
,
782 ConSplitterVirtualHandle
,
783 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
785 if (EFI_ERROR (Status
)) {
789 return gBS
->OpenProtocol (
793 This
->DriverBindingHandle
,
794 ConSplitterVirtualHandle
,
795 EFI_OPEN_PROTOCOL_GET_PROTOCOL
802 ConSplitterConInDriverBindingStart (
803 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
804 IN EFI_HANDLE ControllerHandle
,
805 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
810 Start ConSplitter on ControllerHandle, and create the virtual
811 agrogated console device on first call Start for a SimpleTextIn handle.
814 This - Pointer to protocol.
815 ControllerHandle - Controller handle.
816 RemainingDevicePath - Remaining device path.
821 EFI_ERROR if a SimpleTextIn protocol is not started.
826 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
829 // Start ConSplitter on ControllerHandle, and create the virtual
830 // agrogated console device on first call Start for a SimpleTextIn handle.
832 Status
= ConSplitterStart (
835 mConIn
.VirtualHandle
,
836 &gEfiConsoleInDeviceGuid
,
837 &gEfiSimpleTextInProtocolGuid
,
840 if (EFI_ERROR (Status
)) {
844 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
850 ConSplitterSimplePointerDriverBindingStart (
851 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
852 IN EFI_HANDLE ControllerHandle
,
853 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
858 Start ConSplitter on ControllerHandle, and create the virtual
859 agrogated console device on first call Start for a SimpleTextIn handle.
862 This - Pointer to protocol.
863 ControllerHandle - Controller handle.
864 RemainingDevicePath - Remaining device path.
868 EFI_ERROR if a SimpleTextIn protocol is not started.
873 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
875 Status
= ConSplitterStart (
878 mConIn
.VirtualHandle
,
879 &gEfiSimplePointerProtocolGuid
,
880 &gEfiSimplePointerProtocolGuid
,
881 (VOID
**) &SimplePointer
883 if (EFI_ERROR (Status
)) {
887 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
893 ConSplitterConOutDriverBindingStart (
894 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
895 IN EFI_HANDLE ControllerHandle
,
896 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
901 Start ConSplitter on ControllerHandle, and create the virtual
902 agrogated console device on first call Start for a SimpleTextIn handle.
905 This - Pointer to protocol.
906 ControllerHandle - Controller handle.
907 RemainingDevicePath - Remaining device path.
910 EFI_ERROR if a SimpleTextIn protocol is not started.
915 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
916 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
917 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
919 Status
= ConSplitterStart (
922 mConOut
.VirtualHandle
,
923 &gEfiConsoleOutDeviceGuid
,
924 &gEfiSimpleTextOutProtocolGuid
,
927 if (EFI_ERROR (Status
)) {
931 // Try to Open Graphics Output protocol
933 Status
= gBS
->OpenProtocol (
935 &gEfiGraphicsOutputProtocolGuid
,
937 This
->DriverBindingHandle
,
938 mConOut
.VirtualHandle
,
939 EFI_OPEN_PROTOCOL_GET_PROTOCOL
941 if (EFI_ERROR (Status
)) {
942 GraphicsOutput
= NULL
;
945 // Open UGA_DRAW protocol
947 Status
= gBS
->OpenProtocol (
949 &gEfiUgaDrawProtocolGuid
,
951 This
->DriverBindingHandle
,
952 mConOut
.VirtualHandle
,
953 EFI_OPEN_PROTOCOL_GET_PROTOCOL
955 if (EFI_ERROR (Status
)) {
959 // If both ConOut and StdErr incorporate the same Text Out device,
960 // their MaxMode and QueryData should be the intersection of both.
962 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
963 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
965 #if (EFI_SPECIFICATION_VERSION < 0x00020000)
967 // Match the UGA mode data of ConOut with the current mode
969 if (UgaDraw
!= NULL
) {
972 &mConOut
.UgaHorizontalResolution
,
973 &mConOut
.UgaVerticalResolution
,
974 &mConOut
.UgaColorDepth
,
975 &mConOut
.UgaRefreshRate
986 ConSplitterStdErrDriverBindingStart (
987 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
988 IN EFI_HANDLE ControllerHandle
,
989 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
994 Start ConSplitter on ControllerHandle, and create the virtual
995 agrogated console device on first call Start for a SimpleTextIn handle.
998 This - Pointer to protocol.
999 ControllerHandle - Controller handle.
1000 RemainingDevicePath - Remaining device path.
1003 EFI_ERROR if a SimpleTextIn protocol is not started.
1008 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1010 Status
= ConSplitterStart (
1013 mStdErr
.VirtualHandle
,
1014 &gEfiStandardErrorDeviceGuid
,
1015 &gEfiSimpleTextOutProtocolGuid
,
1018 if (EFI_ERROR (Status
)) {
1022 // If both ConOut and StdErr incorporate the same Text Out device,
1023 // their MaxMode and QueryData should be the intersection of both.
1025 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1026 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1027 if (EFI_ERROR (Status
)) {
1031 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1032 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1033 gST
->StdErr
= &mStdErr
.TextOut
;
1035 // Update the CRC32 in the EFI System Table header
1038 gBS
->CalculateCrc32 (
1039 (UINT8
*) &gST
->Hdr
,
1040 gST
->Hdr
.HeaderSize
,
1052 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1053 IN EFI_HANDLE ControllerHandle
,
1054 IN EFI_HANDLE ConSplitterVirtualHandle
,
1055 IN EFI_GUID
*DeviceGuid
,
1056 IN EFI_GUID
*InterfaceGuid
,
1061 Routine Description:
1064 (Standard DriverBinding Protocol Stop() function)
1074 Status
= gBS
->OpenProtocol (
1078 This
->DriverBindingHandle
,
1080 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1082 if (EFI_ERROR (Status
)) {
1086 // close the protocol refered.
1088 gBS
->CloseProtocol (
1091 This
->DriverBindingHandle
,
1092 ConSplitterVirtualHandle
1094 gBS
->CloseProtocol (
1097 This
->DriverBindingHandle
,
1107 ConSplitterConInDriverBindingStop (
1108 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1109 IN EFI_HANDLE ControllerHandle
,
1110 IN UINTN NumberOfChildren
,
1111 IN EFI_HANDLE
*ChildHandleBuffer
1115 Routine Description:
1118 (Standard DriverBinding Protocol Stop() function)
1127 EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
;
1129 if (NumberOfChildren
== 0) {
1133 Status
= ConSplitterStop (
1136 mConIn
.VirtualHandle
,
1137 &gEfiConsoleInDeviceGuid
,
1138 &gEfiSimpleTextInProtocolGuid
,
1141 if (EFI_ERROR (Status
)) {
1145 // Delete this console input device's data structures.
1147 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1153 ConSplitterSimplePointerDriverBindingStop (
1154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1155 IN EFI_HANDLE ControllerHandle
,
1156 IN UINTN NumberOfChildren
,
1157 IN EFI_HANDLE
*ChildHandleBuffer
1161 Routine Description:
1164 (Standard DriverBinding Protocol Stop() function)
1173 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1175 if (NumberOfChildren
== 0) {
1179 Status
= ConSplitterStop (
1182 mConIn
.VirtualHandle
,
1183 &gEfiSimplePointerProtocolGuid
,
1184 &gEfiSimplePointerProtocolGuid
,
1185 (VOID
**) &SimplePointer
1187 if (EFI_ERROR (Status
)) {
1191 // Delete this console input device's data structures.
1193 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1199 ConSplitterConOutDriverBindingStop (
1200 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1201 IN EFI_HANDLE ControllerHandle
,
1202 IN UINTN NumberOfChildren
,
1203 IN EFI_HANDLE
*ChildHandleBuffer
1207 Routine Description:
1210 (Standard DriverBinding Protocol Stop() function)
1219 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1221 if (NumberOfChildren
== 0) {
1225 Status
= ConSplitterStop (
1228 mConOut
.VirtualHandle
,
1229 &gEfiConsoleOutDeviceGuid
,
1230 &gEfiSimpleTextOutProtocolGuid
,
1233 if (EFI_ERROR (Status
)) {
1238 // Delete this console output device's data structures.
1240 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1246 ConSplitterStdErrDriverBindingStop (
1247 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1248 IN EFI_HANDLE ControllerHandle
,
1249 IN UINTN NumberOfChildren
,
1250 IN EFI_HANDLE
*ChildHandleBuffer
1254 Routine Description:
1257 (Standard DriverBinding Protocol Stop() function)
1261 EFI_SUCCESS - Complete successfully.
1266 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
;
1268 if (NumberOfChildren
== 0) {
1272 Status
= ConSplitterStop (
1275 mStdErr
.VirtualHandle
,
1276 &gEfiStandardErrorDeviceGuid
,
1277 &gEfiSimpleTextOutProtocolGuid
,
1280 if (EFI_ERROR (Status
)) {
1284 // Delete this console error out device's data structures.
1286 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1287 if (EFI_ERROR (Status
)) {
1291 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1292 gST
->StandardErrorHandle
= NULL
;
1295 // Update the CRC32 in the EFI System Table header
1298 gBS
->CalculateCrc32 (
1299 (UINT8
*) &gST
->Hdr
,
1300 gST
->Hdr
.HeaderSize
,
1309 ConSplitterGrowBuffer (
1310 IN UINTN SizeOfCount
,
1312 IN OUT VOID
**Buffer
1316 Routine Description:
1317 Take the passed in Buffer of size SizeOfCount and grow the buffer
1318 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1319 bytes. Copy the current data in Buffer to the new version of Buffer
1320 and free the old version of buffer.
1324 SizeOfCount - Size of element in array
1325 Count - Current number of elements in array
1326 Buffer - Bigger version of passed in Buffer with all the data
1329 EFI_SUCCESS - Buffer size has grown
1330 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1341 // grow the buffer to new buffer size,
1342 // copy the old buffer's content to the new-size buffer,
1343 // then free the old buffer.
1345 OldSize
= *Count
* SizeOfCount
;
1346 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1347 NewSize
= *Count
* SizeOfCount
;
1349 Ptr
= AllocateZeroPool (NewSize
);
1351 return EFI_OUT_OF_RESOURCES
;
1354 CopyMem (Ptr
, *Buffer
, OldSize
);
1356 if (*Buffer
!= NULL
) {
1357 gBS
->FreePool (*Buffer
);
1366 ConSplitterTextInAddDevice (
1367 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1368 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1372 Routine Description:
1379 EFI_OUT_OF_RESOURCES
1386 // If the Text In List is full, enlarge it by calling growbuffer().
1388 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1389 Status
= ConSplitterGrowBuffer (
1390 sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL
*),
1391 &Private
->TextInListCount
,
1392 (VOID
**) &Private
->TextInList
1394 if (EFI_ERROR (Status
)) {
1395 return EFI_OUT_OF_RESOURCES
;
1399 // Add the new text-in device data structure into the Text In List.
1401 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1402 Private
->CurrentNumberOfConsoles
++;
1405 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1407 gBS
->CheckEvent (TextIn
->WaitForKey
);
1413 ConSplitterTextInDeleteDevice (
1414 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1415 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*TextIn
1419 Routine Description:
1432 // Remove the specified text-in device data structure from the Text In List,
1433 // and rearrange the remaining data structures in the Text In List.
1435 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1436 if (Private
->TextInList
[Index
] == TextIn
) {
1437 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1438 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1441 Private
->CurrentNumberOfConsoles
--;
1446 return EFI_NOT_FOUND
;
1450 ConSplitterSimplePointerAddDevice (
1451 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1452 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1456 Routine Description:
1462 EFI_OUT_OF_RESOURCES
1470 // If the Text In List is full, enlarge it by calling growbuffer().
1472 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1473 Status
= ConSplitterGrowBuffer (
1474 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1475 &Private
->PointerListCount
,
1476 (VOID
**) &Private
->PointerList
1478 if (EFI_ERROR (Status
)) {
1479 return EFI_OUT_OF_RESOURCES
;
1483 // Add the new text-in device data structure into the Text In List.
1485 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1486 Private
->CurrentNumberOfPointers
++;
1491 ConSplitterSimplePointerDeleteDevice (
1492 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1493 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1497 Routine Description:
1509 // Remove the specified text-in device data structure from the Text In List,
1510 // and rearrange the remaining data structures in the Text In List.
1512 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1513 if (Private
->PointerList
[Index
] == SimplePointer
) {
1514 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1515 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1518 Private
->CurrentNumberOfPointers
--;
1523 return EFI_NOT_FOUND
;
1527 ConSplitterGrowMapTable (
1528 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1532 Routine Description:
1545 INT32
*TextOutModeMap
;
1546 INT32
*OldTextOutModeMap
;
1550 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1551 OldTextOutModeMap
= Private
->TextOutModeMap
;
1552 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1554 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1555 if (TextOutModeMap
== NULL
) {
1556 return EFI_OUT_OF_RESOURCES
;
1559 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1560 Private
->TextOutModeMap
= TextOutModeMap
;
1563 // If TextOutList has been enlarged, need to realloc the mode map table
1564 // The mode map table is regarded as a two dimension array.
1567 // 0 ---------> TextOutListCount ----> TextOutListCount
1568 // | -------------------------------------------
1575 // -------------------------------------------
1578 if (OldTextOutModeMap
!= NULL
) {
1580 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1582 SrcAddress
= OldTextOutModeMap
;
1585 // Copy the old data to the new one
1587 while (Index
< Private
->TextOutMode
.MaxMode
) {
1588 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1589 TextOutModeMap
+= NewSize
;
1594 // Free the old buffer
1596 gBS
->FreePool (OldTextOutModeMap
);
1603 ConSplitterAddOutputMode (
1604 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1605 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1609 Routine Description:
1624 MaxMode
= TextOut
->Mode
->MaxMode
;
1625 Private
->TextOutMode
.MaxMode
= MaxMode
;
1628 // Grow the buffer if query data buffer is not large enough to
1629 // hold all the mode supported by the first console.
1631 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1632 Status
= ConSplitterGrowBuffer (
1633 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1634 &Private
->TextOutQueryDataCount
,
1635 (VOID
**) &Private
->TextOutQueryData
1637 if (EFI_ERROR (Status
)) {
1638 return EFI_OUT_OF_RESOURCES
;
1642 // Allocate buffer for the output mode map
1644 Status
= ConSplitterGrowMapTable (Private
);
1645 if (EFI_ERROR (Status
)) {
1646 return EFI_OUT_OF_RESOURCES
;
1649 // As the first textout device, directly add the mode in to QueryData
1650 // and at the same time record the mapping between QueryData and TextOut.
1654 while (Mode
< MaxMode
) {
1655 TextOut
->QueryMode (
1658 &Private
->TextOutQueryData
[Mode
].Columns
,
1659 &Private
->TextOutQueryData
[Mode
].Rows
1661 Private
->TextOutModeMap
[Index
] = Mode
;
1663 Index
+= Private
->TextOutListCount
;
1670 ConSplitterGetIntersection (
1671 IN INT32
*TextOutModeMap
,
1672 IN INT32
*NewlyAddedMap
,
1673 IN UINTN MapStepSize
,
1674 IN UINTN NewMapStepSize
,
1676 OUT INT32
*CurrentMode
1680 INT32
*CurrentMapEntry
;
1681 INT32
*NextMapEntry
;
1682 INT32 CurrentMaxMode
;
1686 CurrentMapEntry
= TextOutModeMap
;
1687 NextMapEntry
= TextOutModeMap
;
1688 CurrentMaxMode
= *MaxMode
;
1689 Mode
= *CurrentMode
;
1691 while (Index
< CurrentMaxMode
) {
1692 if (*NewlyAddedMap
== -1) {
1694 // This mode is not supported any more. Remove it. Special care
1695 // must be taken as this remove will also affect current mode;
1697 if (Index
== *CurrentMode
) {
1699 } else if (Index
< *CurrentMode
) {
1704 if (CurrentMapEntry
!= NextMapEntry
) {
1705 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1708 NextMapEntry
+= MapStepSize
;
1711 CurrentMapEntry
+= MapStepSize
;
1712 NewlyAddedMap
+= NewMapStepSize
;
1716 *CurrentMode
= Mode
;
1722 ConSplitterSyncOutputMode (
1723 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1724 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
1728 Routine Description:
1731 Private - Private data structure.
1732 TextOut - Text Out Protocol.
1740 INT32 CurrentMaxMode
;
1743 INT32
*TextOutModeMap
;
1745 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1751 // Must make sure that current mode won't change even if mode number changes
1753 CurrentMode
= Private
->TextOutMode
.Mode
;
1754 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1755 TextOutModeMap
= Private
->TextOutModeMap
;
1756 StepSize
= Private
->TextOutListCount
;
1757 TextOutQueryData
= Private
->TextOutQueryData
;
1760 // Query all the mode that the newly added TextOut supports
1763 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1764 while (Mode
< TextOut
->Mode
->MaxMode
) {
1765 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1768 // Search the QueryData database to see if they intersects
1771 while (Index
< CurrentMaxMode
) {
1772 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1773 MapTable
[Index
* StepSize
] = Mode
;
1783 // Now search the TextOutModeMap table to find the intersection of supported
1784 // mode between ConSplitter and the newly added device.
1786 ConSplitterGetIntersection (
1791 &Private
->TextOutMode
.MaxMode
,
1792 &Private
->TextOutMode
.Mode
1799 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1804 Routine Description:
1811 EFI_OUT_OF_RESOURCES
1815 UINTN ConOutNumOfConsoles
;
1816 UINTN StdErrNumOfConsoles
;
1817 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1818 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1823 INT32 ConOutCurrentMode
;
1824 INT32 StdErrCurrentMode
;
1825 INT32 ConOutMaxMode
;
1826 INT32 StdErrMaxMode
;
1829 INT32
*ConOutModeMap
;
1830 INT32
*StdErrModeMap
;
1831 INT32
*ConOutMapTable
;
1832 INT32
*StdErrMapTable
;
1833 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1834 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1835 UINTN ConOutStepSize
;
1836 UINTN StdErrStepSize
;
1837 BOOLEAN FoundTheSameTextOut
;
1838 UINTN ConOutMapTableSize
;
1839 UINTN StdErrMapTableSize
;
1841 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1842 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1843 ConOutTextOutList
= mConOut
.TextOutList
;
1844 StdErrTextOutList
= mStdErr
.TextOutList
;
1847 FoundTheSameTextOut
= FALSE
;
1848 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1850 while (Indexj
< StdErrNumOfConsoles
) {
1851 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1852 FoundTheSameTextOut
= TRUE
;
1857 StdErrTextOutList
++;
1861 ConOutTextOutList
++;
1864 if (!FoundTheSameTextOut
) {
1868 // Must make sure that current mode won't change even if mode number changes
1870 ConOutCurrentMode
= mConOut
.TextOutMode
.Mode
;
1871 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1872 ConOutModeMap
= mConOut
.TextOutModeMap
;
1873 ConOutStepSize
= mConOut
.TextOutListCount
;
1874 ConOutQueryData
= mConOut
.TextOutQueryData
;
1876 StdErrCurrentMode
= mStdErr
.TextOutMode
.Mode
;
1877 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1878 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1879 StdErrStepSize
= mStdErr
.TextOutListCount
;
1880 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1883 // Allocate the map table and set the map table's index to -1.
1885 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1886 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1887 if (ConOutMapTable
== NULL
) {
1888 return EFI_OUT_OF_RESOURCES
;
1891 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1893 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1894 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1895 if (StdErrMapTable
== NULL
) {
1896 return EFI_OUT_OF_RESOURCES
;
1899 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
1902 // Find the intersection of the two set of modes. If they actually intersect, the
1903 // correponding entry in the map table is set to 1.
1906 while (Mode
< ConOutMaxMode
) {
1908 // Search the other's QueryData database to see if they intersect
1911 Rows
= ConOutQueryData
[Mode
].Rows
;
1912 Columns
= ConOutQueryData
[Mode
].Columns
;
1913 while (Index
< StdErrMaxMode
) {
1914 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
1915 ConOutMapTable
[Mode
] = 1;
1916 StdErrMapTable
[Index
] = 1;
1926 // Now search the TextOutModeMap table to find the intersection of supported
1927 // mode between ConSplitter and the newly added device.
1929 ConSplitterGetIntersection (
1932 mConOut
.TextOutListCount
,
1934 &(mConOut
.TextOutMode
.MaxMode
),
1935 &(mConOut
.TextOutMode
.Mode
)
1937 if (mConOut
.TextOutMode
.Mode
< 0) {
1938 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
1941 ConSplitterGetIntersection (
1944 mStdErr
.TextOutListCount
,
1946 &(mStdErr
.TextOutMode
.MaxMode
),
1947 &(mStdErr
.TextOutMode
.Mode
)
1949 if (mStdErr
.TextOutMode
.Mode
< 0) {
1950 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
1953 gBS
->FreePool (ConOutMapTable
);
1954 gBS
->FreePool (StdErrMapTable
);
1959 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
1961 ConSplitterAddGraphicsOutputMode (
1962 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1963 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1964 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1968 Routine Description:
1980 TEXT_OUT_GOP_MODE
*Mode
;
1982 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1983 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
1984 TEXT_OUT_GOP_MODE
*ModeBuffer
;
1985 TEXT_OUT_GOP_MODE
*MatchedMode
;
1989 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
1990 return EFI_UNSUPPORTED
;
1993 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
1995 if (GraphicsOutput
!= NULL
) {
1996 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
1998 // This is the first Graphics Output device added
2000 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2001 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2002 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2003 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2004 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2005 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2008 // Allocate resource for the private mode buffer
2010 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
2011 if (ModeBuffer
== NULL
) {
2012 return EFI_OUT_OF_RESOURCES
;
2014 gBS
->FreePool (Private
->GraphicsOutputModeBuffer
);
2015 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2018 // Store all supported display modes to the private mode buffer
2021 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2022 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2023 if (EFI_ERROR (Status
)) {
2026 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2027 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2029 gBS
->FreePool (Info
);
2033 // Check intersection of display mode
2035 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2036 if (ModeBuffer
== NULL
) {
2037 return EFI_OUT_OF_RESOURCES
;
2040 MatchedMode
= ModeBuffer
;
2041 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2042 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2045 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2046 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2047 if (EFI_ERROR (Status
)) {
2050 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2051 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2053 gBS
->FreePool (Info
);
2056 gBS
->FreePool (Info
);
2060 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2068 // Drop the old mode buffer, assign it to a new one
2070 gBS
->FreePool (Private
->GraphicsOutputModeBuffer
);
2071 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2074 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2076 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2077 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2078 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2079 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2080 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2081 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2085 // Select a prefered Display mode 800x600
2087 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2088 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2089 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2094 // Prefered mode is not found, set to mode 0
2096 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2101 // Current mode number may need update now, so set it to an invalide mode number
2103 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2106 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2107 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2109 CurrentGraphicsOutputMode
->MaxMode
= 1;
2110 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2111 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2112 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2113 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2114 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2115 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2116 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2117 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2120 // Update the private mode buffer
2122 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2123 ModeBuffer
->HorizontalResolution
= 800;
2124 ModeBuffer
->VerticalResolution
= 600;
2127 // Current mode is unknow now, set it to an invalid mode number 0xffff
2129 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2134 // Force GraphicsOutput mode to be set,
2135 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2137 Private
->HardwareNeedsStarting
= TRUE
;
2138 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2140 Private
->CurrentNumberOfGraphicsOutput
++;
2147 ConSplitterTextOutAddDevice (
2148 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2149 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
,
2150 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2151 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2155 Routine Description:
2166 UINTN CurrentNumOfConsoles
;
2169 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2171 Status
= EFI_SUCCESS
;
2172 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2175 // If the Text Out List is full, enlarge it by calling growbuffer().
2177 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2178 Status
= ConSplitterGrowBuffer (
2179 sizeof (TEXT_OUT_AND_GOP_DATA
),
2180 &Private
->TextOutListCount
,
2181 (VOID
**) &Private
->TextOutList
2183 if (EFI_ERROR (Status
)) {
2184 return EFI_OUT_OF_RESOURCES
;
2187 // Also need to reallocate the TextOutModeMap table
2189 Status
= ConSplitterGrowMapTable (Private
);
2190 if (EFI_ERROR (Status
)) {
2191 return EFI_OUT_OF_RESOURCES
;
2195 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2197 TextAndGop
->TextOut
= TextOut
;
2198 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2199 TextAndGop
->UgaDraw
= UgaDraw
;
2201 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2203 // If No UGA device then use the ConOut device
2205 TextAndGop
->TextOutEnabled
= TRUE
;
2208 // If UGA device use ConOut device only used if UGA screen is in Text mode
2210 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2213 if (CurrentNumOfConsoles
== 0) {
2215 // Add the first device's output mode to console splitter's mode list
2217 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2219 ConSplitterSyncOutputMode (Private
, TextOut
);
2222 Private
->CurrentNumberOfConsoles
++;
2225 // Scan both TextOutList, for the intersection TextOut device
2226 // maybe both ConOut and StdErr incorporate the same Text Out
2227 // device in them, thus the output of both should be synced.
2229 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2231 CurrentMode
= Private
->TextOutMode
.Mode
;
2232 MaxMode
= Private
->TextOutMode
.MaxMode
;
2233 ASSERT (MaxMode
>= 1);
2235 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
2236 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2237 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2241 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2243 // We just added a new UGA device in graphics mode
2245 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
2246 DevNullGopSync (Private
, GraphicsOutput
, UgaDraw
);
2248 DevNullUgaSync (Private
, UgaDraw
);
2250 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2252 // The new console supports the same mode of the current console so sync up
2254 DevNullSyncGopStdOut (Private
);
2257 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2259 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2266 ConSplitterTextOutDeleteDevice (
2267 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2268 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*TextOut
2272 Routine Description:
2283 UINTN CurrentNumOfConsoles
;
2284 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2288 // Remove the specified text-out device data structure from the Text out List,
2289 // and rearrange the remaining data structures in the Text out List.
2291 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2292 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2293 TextOutList
= Private
->TextOutList
;
2294 while (Index
>= 0) {
2295 if (TextOutList
->TextOut
== TextOut
) {
2296 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2297 CurrentNumOfConsoles
--;
2305 // The specified TextOut is not managed by the ConSplitter driver
2308 return EFI_NOT_FOUND
;
2311 if (CurrentNumOfConsoles
== 0) {
2313 // If the number of consoles is zero clear the Dev NULL device
2315 Private
->CurrentNumberOfConsoles
= 0;
2316 Private
->TextOutMode
.MaxMode
= 1;
2317 Private
->TextOutQueryData
[0].Columns
= 80;
2318 Private
->TextOutQueryData
[0].Rows
= 25;
2319 DevNullTextOutSetMode (Private
, 0);
2324 // Max Mode is realy an intersection of the QueryMode command to all
2325 // devices. So we must copy the QueryMode of the first device to
2329 Private
->TextOutQueryData
,
2330 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2333 gBS
->FreePool (Private
->TextOutModeMap
);
2334 Private
->TextOutModeMap
= NULL
;
2335 TextOutList
= Private
->TextOutList
;
2338 // Add the first TextOut to the QueryData array and ModeMap table
2340 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2343 // Now add one by one
2346 Private
->CurrentNumberOfConsoles
= 1;
2348 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2349 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2351 Private
->CurrentNumberOfConsoles
++;
2355 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2360 // ConSplitter TextIn member functions
2364 ConSplitterTextInReset (
2365 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2366 IN BOOLEAN ExtendedVerification
2370 Routine Description:
2371 Reset the input device and optionaly run diagnostics
2374 This - Protocol instance pointer.
2375 ExtendedVerification - Driver may perform diagnostics on reset.
2378 EFI_SUCCESS - The device was reset.
2379 EFI_DEVICE_ERROR - The device is not functioning properly and could
2385 EFI_STATUS ReturnStatus
;
2386 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2389 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2391 Private
->KeyEventSignalState
= FALSE
;
2394 // return the worst status met
2396 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2397 Status
= Private
->TextInList
[Index
]->Reset (
2398 Private
->TextInList
[Index
],
2399 ExtendedVerification
2401 if (EFI_ERROR (Status
)) {
2402 ReturnStatus
= Status
;
2406 return ReturnStatus
;
2411 ConSplitterTextInPrivateReadKeyStroke (
2412 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2413 OUT EFI_INPUT_KEY
*Key
2417 Routine Description:
2418 Reads the next keystroke from the input device. The WaitForKey Event can
2419 be used to test for existance of a keystroke via WaitForEvent () call.
2422 This - Protocol instance pointer.
2423 Key - Driver may perform diagnostics on reset.
2426 EFI_SUCCESS - The keystroke information was returned.
2427 EFI_NOT_READY - There was no keystroke data availiable.
2428 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2435 EFI_INPUT_KEY CurrentKey
;
2437 Key
->UnicodeChar
= 0;
2438 Key
->ScanCode
= SCAN_NULL
;
2441 // if no physical console input device exists, return EFI_NOT_READY;
2442 // if any physical console input device has key input,
2443 // return the key and EFI_SUCCESS.
2445 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2446 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2447 Private
->TextInList
[Index
],
2450 if (!EFI_ERROR (Status
)) {
2456 return EFI_NOT_READY
;
2460 ConSpliterConssoleControlStdInLocked (
2465 Routine Description:
2466 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2467 the only device locked.
2474 FALSE - StdIn working normally
2478 return mConIn
.PasswordEnabled
;
2483 ConSpliterConsoleControlLockStdInEvent (
2489 Routine Description:
2490 This timer event will fire when StdIn is locked. It will check the key
2491 sequence on StdIn to see if it matches the password. Any error in the
2492 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2493 TRUE the StdIn splitter will not report any input.
2496 (Standard EFI_EVENT_NOTIFY)
2505 CHAR16 BackSpaceString
[2];
2506 CHAR16 SpaceString
[2];
2509 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2510 if (!EFI_ERROR (Status
)) {
2512 // if it's an ENTER, match password
2514 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2515 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2516 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2518 // Password not match
2520 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2521 mConIn
.PwdIndex
= 0;
2524 // Key matches password sequence
2526 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2527 mConIn
.PasswordEnabled
= FALSE
;
2528 Status
= EFI_NOT_READY
;
2530 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2534 if (mConIn
.PwdIndex
> 0) {
2535 BackSpaceString
[0] = CHAR_BACKSPACE
;
2536 BackSpaceString
[1] = 0;
2538 SpaceString
[0] = ' ';
2541 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2542 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2543 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2547 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2549 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2551 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2552 if (mConIn
.PwdIndex
== 0) {
2553 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2556 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2557 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2562 } while (!EFI_ERROR (Status
));
2567 ConSpliterConsoleControlLockStdIn (
2568 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2573 Routine Description:
2574 If Password is NULL unlock the password state variable and set the event
2575 timer. If the Password is too big return an error. If the Password is valid
2576 Copy the Password and enable state variable and then arm the periodic timer
2581 EFI_SUCCESS - Lock the StdIn device
2582 EFI_INVALID_PARAMETER - Password is NULL
2583 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2587 if (Password
== NULL
) {
2588 return EFI_INVALID_PARAMETER
;
2591 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2593 // Currently have a max password size
2595 return EFI_OUT_OF_RESOURCES
;
2598 // Save the password, initialize state variables and arm event timer
2600 StrCpy (mConIn
.Password
, Password
);
2601 mConIn
.PasswordEnabled
= TRUE
;
2602 mConIn
.PwdIndex
= 0;
2603 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2610 ConSplitterTextInReadKeyStroke (
2611 IN EFI_SIMPLE_TEXT_IN_PROTOCOL
*This
,
2612 OUT EFI_INPUT_KEY
*Key
2616 Routine Description:
2617 Reads the next keystroke from the input device. The WaitForKey Event can
2618 be used to test for existance of a keystroke via WaitForEvent () call.
2619 If the ConIn is password locked make it look like no keystroke is availible
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
2633 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2635 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2636 if (Private
->PasswordEnabled
) {
2638 // If StdIn Locked return not ready
2640 return EFI_NOT_READY
;
2643 Private
->KeyEventSignalState
= FALSE
;
2645 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2650 ConSplitterTextInWaitForKey (
2656 Routine Description:
2657 This event agregates all the events of the ConIn devices in the spliter.
2658 If the ConIn is password locked then return.
2659 If any events of physical ConIn devices are signaled, signal the ConIn
2660 spliter event. This will cause the calling code to call
2661 ConSplitterTextInReadKeyStroke ().
2664 Event - The Event assoicated with callback.
2665 Context - Context registered when Event was created.
2673 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2676 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2677 if (Private
->PasswordEnabled
) {
2679 // If StdIn Locked return not ready
2685 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2687 if (Private
->KeyEventSignalState
) {
2688 gBS
->SignalEvent (Event
);
2692 // if any physical console input device has key input, signal the event.
2694 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2695 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2696 if (!EFI_ERROR (Status
)) {
2697 gBS
->SignalEvent (Event
);
2698 Private
->KeyEventSignalState
= TRUE
;
2705 ConSplitterSimplePointerReset (
2706 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2707 IN BOOLEAN ExtendedVerification
2711 Routine Description:
2712 Reset the input device and optionaly run diagnostics
2715 This - Protocol instance pointer.
2716 ExtendedVerification - Driver may perform diagnostics on reset.
2719 EFI_SUCCESS - The device was reset.
2720 EFI_DEVICE_ERROR - The device is not functioning properly and could
2726 EFI_STATUS ReturnStatus
;
2727 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2730 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2732 Private
->InputEventSignalState
= FALSE
;
2734 if (Private
->CurrentNumberOfPointers
== 0) {
2738 // return the worst status met
2740 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2741 Status
= Private
->PointerList
[Index
]->Reset (
2742 Private
->PointerList
[Index
],
2743 ExtendedVerification
2745 if (EFI_ERROR (Status
)) {
2746 ReturnStatus
= Status
;
2750 return ReturnStatus
;
2755 ConSplitterSimplePointerPrivateGetState (
2756 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2757 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2761 Routine Description:
2762 Reads the next keystroke from the input device. The WaitForKey Event can
2763 be used to test for existance of a keystroke via WaitForEvent () call.
2766 This - Protocol instance pointer.
2770 EFI_SUCCESS - The keystroke information was returned.
2771 EFI_NOT_READY - There was no keystroke data availiable.
2772 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2778 EFI_STATUS ReturnStatus
;
2780 EFI_SIMPLE_POINTER_STATE CurrentState
;
2782 State
->RelativeMovementX
= 0;
2783 State
->RelativeMovementY
= 0;
2784 State
->RelativeMovementZ
= 0;
2785 State
->LeftButton
= FALSE
;
2786 State
->RightButton
= FALSE
;
2789 // if no physical console input device exists, return EFI_NOT_READY;
2790 // if any physical console input device has key input,
2791 // return the key and EFI_SUCCESS.
2793 ReturnStatus
= EFI_NOT_READY
;
2794 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2796 Status
= Private
->PointerList
[Index
]->GetState (
2797 Private
->PointerList
[Index
],
2800 if (!EFI_ERROR (Status
)) {
2801 if (ReturnStatus
== EFI_NOT_READY
) {
2802 ReturnStatus
= EFI_SUCCESS
;
2805 if (CurrentState
.LeftButton
) {
2806 State
->LeftButton
= TRUE
;
2809 if (CurrentState
.RightButton
) {
2810 State
->RightButton
= TRUE
;
2813 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2814 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2817 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2818 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2821 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2822 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2824 } else if (Status
== EFI_DEVICE_ERROR
) {
2825 ReturnStatus
= EFI_DEVICE_ERROR
;
2829 return ReturnStatus
;
2834 ConSplitterSimplePointerGetState (
2835 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2836 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2840 Routine Description:
2841 Reads the next keystroke from the input device. The WaitForKey Event can
2842 be used to test for existance of a keystroke via WaitForEvent () call.
2843 If the ConIn is password locked make it look like no keystroke is availible
2846 This - Protocol instance pointer.
2850 EFI_SUCCESS - The keystroke information was returned.
2851 EFI_NOT_READY - There was no keystroke data availiable.
2852 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2857 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2859 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2860 if (Private
->PasswordEnabled
) {
2862 // If StdIn Locked return not ready
2864 return EFI_NOT_READY
;
2867 Private
->InputEventSignalState
= FALSE
;
2869 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2874 ConSplitterSimplePointerWaitForInput (
2880 Routine Description:
2881 This event agregates all the events of the ConIn devices in the spliter.
2882 If the ConIn is password locked then return.
2883 If any events of physical ConIn devices are signaled, signal the ConIn
2884 spliter event. This will cause the calling code to call
2885 ConSplitterTextInReadKeyStroke ().
2888 Event - The Event assoicated with callback.
2889 Context - Context registered when Event was created.
2897 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2900 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2901 if (Private
->PasswordEnabled
) {
2903 // If StdIn Locked return not ready
2909 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2911 if (Private
->InputEventSignalState
) {
2912 gBS
->SignalEvent (Event
);
2916 // if any physical console input device has key input, signal the event.
2918 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2919 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2920 if (!EFI_ERROR (Status
)) {
2921 gBS
->SignalEvent (Event
);
2922 Private
->InputEventSignalState
= TRUE
;
2929 ConSplitterTextOutReset (
2930 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2931 IN BOOLEAN ExtendedVerification
2935 Routine Description:
2936 Reset the text output device hardware and optionaly run diagnostics
2939 This - Protocol instance pointer.
2940 ExtendedVerification - Driver may perform more exhaustive verfication
2941 operation of the device during reset.
2944 EFI_SUCCESS - The text output device was reset.
2945 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2951 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2953 EFI_STATUS ReturnStatus
;
2955 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2958 // return the worst status met
2960 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2962 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2964 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2965 Private
->TextOutList
[Index
].TextOut
,
2966 ExtendedVerification
2968 if (EFI_ERROR (Status
)) {
2969 ReturnStatus
= Status
;
2974 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2976 Status
= DevNullTextOutSetMode (Private
, 0);
2977 if (EFI_ERROR (Status
)) {
2978 ReturnStatus
= Status
;
2981 return ReturnStatus
;
2986 ConSplitterTextOutOutputString (
2987 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
2992 Routine Description:
2993 Write a Unicode string to the output device.
2996 This - Protocol instance pointer.
2997 String - The NULL-terminated Unicode string to be displayed on the output
2998 device(s). All output devices must also support the Unicode
2999 drawing defined in this file.
3002 EFI_SUCCESS - The string was output to the device.
3003 EFI_DEVICE_ERROR - The device reported an error while attempting to output
3005 EFI_UNSUPPORTED - The output device's mode is not currently in a
3007 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
3008 characters in the Unicode string could not be
3009 rendered and were skipped.
3014 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3016 UINTN BackSpaceCount
;
3017 EFI_STATUS ReturnStatus
;
3018 CHAR16
*TargetString
;
3020 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3022 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3025 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3026 if (*TargetString
== CHAR_BACKSPACE
) {
3032 if (BackSpaceCount
== 0) {
3033 TargetString
= WString
;
3035 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3036 StrCpy (TargetString
, WString
);
3039 // return the worst status met
3041 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3042 if (EFI_ERROR (Status
)) {
3043 ReturnStatus
= Status
;
3046 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3048 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3049 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3050 Private
->TextOutList
[Index
].TextOut
,
3053 if (EFI_ERROR (Status
)) {
3054 ReturnStatus
= Status
;
3059 if (BackSpaceCount
) {
3060 gBS
->FreePool (TargetString
);
3063 return ReturnStatus
;
3068 ConSplitterTextOutTestString (
3069 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3074 Routine Description:
3075 Verifies that all characters in a Unicode string can be output to the
3079 This - Protocol instance pointer.
3080 String - The NULL-terminated Unicode string to be examined for the output
3084 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3085 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3086 rendered by one or more of the output devices mapped
3092 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3094 EFI_STATUS ReturnStatus
;
3096 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3099 // return the worst status met
3101 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3102 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3103 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3104 Private
->TextOutList
[Index
].TextOut
,
3107 if (EFI_ERROR (Status
)) {
3108 ReturnStatus
= Status
;
3113 // There is no DevNullTextOutTestString () since a Unicode buffer would
3114 // always return EFI_SUCCESS.
3115 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3117 return ReturnStatus
;
3122 ConSplitterTextOutQueryMode (
3123 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3124 IN UINTN ModeNumber
,
3130 Routine Description:
3131 Returns information for an available text mode that the output device(s)
3135 This - Protocol instance pointer.
3136 ModeNumber - The mode number to return information on.
3137 Columns, Rows - Returns the geometry of the text output device for the
3138 requested ModeNumber.
3141 EFI_SUCCESS - The requested mode information was returned.
3142 EFI_DEVICE_ERROR - The device had an error and could not
3143 complete the request.
3144 EFI_UNSUPPORTED - The mode number was not valid.
3148 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3150 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3153 // Check whether param ModeNumber is valid.
3154 // ModeNumber should be within range 0 ~ MaxMode - 1.
3156 if ( (ModeNumber
< 0) ||
3157 (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3158 return EFI_UNSUPPORTED
;
3161 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3162 return EFI_UNSUPPORTED
;
3165 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3166 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3168 if (*Columns
<= 0 && *Rows
<= 0) {
3169 return EFI_UNSUPPORTED
;
3178 ConSplitterTextOutSetMode (
3179 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3184 Routine Description:
3185 Sets the output device(s) to a specified mode.
3188 This - Protocol instance pointer.
3189 ModeNumber - The mode number to set.
3192 EFI_SUCCESS - The requested text mode was set.
3193 EFI_DEVICE_ERROR - The device had an error and
3194 could not complete the request.
3195 EFI_UNSUPPORTED - The mode number was not valid.
3200 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3202 INT32
*TextOutModeMap
;
3203 EFI_STATUS ReturnStatus
;
3205 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3208 // Check whether param ModeNumber is valid.
3209 // ModeNumber should be within range 0 ~ MaxMode - 1.
3211 if ( (ModeNumber
< 0) ||
3212 (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3213 return EFI_UNSUPPORTED
;
3216 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3217 return EFI_UNSUPPORTED
;
3220 // If the mode is being set to the curent mode, then just clear the screen and return.
3222 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3223 return ConSplitterTextOutClearScreen (This
);
3226 // return the worst status met
3228 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3229 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3231 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3232 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3233 Private
->TextOutList
[Index
].TextOut
,
3234 TextOutModeMap
[Index
]
3237 // If this console device is based on a UGA device, then sync up the bitmap from
3238 // the UGA splitter and reclear the text portion of the display in the new mode.
3240 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3241 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3244 if (EFI_ERROR (Status
)) {
3245 ReturnStatus
= Status
;
3250 // The DevNull Console will support any possible mode as it allocates memory
3252 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3253 if (EFI_ERROR (Status
)) {
3254 ReturnStatus
= Status
;
3257 return ReturnStatus
;
3262 ConSplitterTextOutSetAttribute (
3263 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3268 Routine Description:
3269 Sets the background and foreground colors for the OutputString () and
3270 ClearScreen () functions.
3273 This - Protocol instance pointer.
3274 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3275 bits 4..6 are the background color. All other bits are undefined
3276 and must be zero. The valid Attributes are defined in this file.
3279 EFI_SUCCESS - The attribute was set.
3280 EFI_DEVICE_ERROR - The device had an error and
3281 could not complete the request.
3282 EFI_UNSUPPORTED - The attribute requested is not defined.
3287 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3289 EFI_STATUS ReturnStatus
;
3291 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3294 // Check whether param Attribute is valid.
3296 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3297 return EFI_UNSUPPORTED
;
3301 // return the worst status met
3303 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3305 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3306 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3307 Private
->TextOutList
[Index
].TextOut
,
3310 if (EFI_ERROR (Status
)) {
3311 ReturnStatus
= Status
;
3316 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3318 return ReturnStatus
;
3323 ConSplitterTextOutClearScreen (
3324 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
3328 Routine Description:
3329 Clears the output device(s) display to the currently selected background
3333 This - Protocol instance pointer.
3336 EFI_SUCCESS - The operation completed successfully.
3337 EFI_DEVICE_ERROR - The device had an error and
3338 could not complete the request.
3339 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3344 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3346 EFI_STATUS ReturnStatus
;
3348 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3351 // return the worst status met
3353 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3355 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3356 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3357 if (EFI_ERROR (Status
)) {
3358 ReturnStatus
= Status
;
3363 Status
= DevNullTextOutClearScreen (Private
);
3364 if (EFI_ERROR (Status
)) {
3365 ReturnStatus
= Status
;
3368 return ReturnStatus
;
3373 ConSplitterTextOutSetCursorPosition (
3374 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3380 Routine Description:
3381 Sets the current coordinates of the cursor position
3384 This - Protocol instance pointer.
3385 Column, Row - the position to set the cursor to. Must be greater than or
3386 equal to zero and less than the number of columns and rows
3390 EFI_SUCCESS - The operation completed successfully.
3391 EFI_DEVICE_ERROR - The device had an error and
3392 could not complete the request.
3393 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3394 cursor position is invalid for the current mode.
3399 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3401 EFI_STATUS ReturnStatus
;
3405 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3407 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3408 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3410 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3411 return EFI_UNSUPPORTED
;
3414 // return the worst status met
3416 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3418 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3419 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3420 Private
->TextOutList
[Index
].TextOut
,
3424 if (EFI_ERROR (Status
)) {
3425 ReturnStatus
= Status
;
3430 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3432 return ReturnStatus
;
3437 ConSplitterTextOutEnableCursor (
3438 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
3443 Routine Description:
3444 Makes the cursor visible or invisible
3447 This - Protocol instance pointer.
3448 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3449 set to be invisible.
3452 EFI_SUCCESS - The operation completed successfully.
3453 EFI_DEVICE_ERROR - The device had an error and could not complete the
3454 request, or the device does not support changing
3456 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3461 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3463 EFI_STATUS ReturnStatus
;
3465 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3468 // return the worst status met
3470 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3472 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3473 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3474 Private
->TextOutList
[Index
].TextOut
,
3477 if (EFI_ERROR (Status
)) {
3478 ReturnStatus
= Status
;
3483 DevNullTextOutEnableCursor (Private
, Visible
);
3485 return ReturnStatus
;