2 Console Splitter Driver. Any Handle that attatched
3 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
5 So far it works like any other driver by opening a SimpleTextIn and/or
6 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
7 difference is this driver does not layer a protocol on the passed in
8 handle, or construct a child handle like a standard device or bus driver.
9 This driver produces three virtual handles as children, one for console input
10 splitter, one for console output splitter and one for error output splitter.
11 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
12 identify the splitter type.
14 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
15 and Console I/O protocol, will be produced in the driver entry point.
16 The virtual handle are added on driver entry and never removed.
17 Such design ensures sytem function well during none console device situation.
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "ConSplitter.h"
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
39 ConSplitterTextInReset
,
40 ConSplitterTextInReadKeyStroke
,
44 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
48 ConSplitterSimplePointerReset
,
49 ConSplitterSimplePointerGetState
,
51 (EFI_SIMPLE_POINTER_MODE
*) NULL
61 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
84 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
85 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
88 ConSplitterTextOutReset
,
89 ConSplitterTextOutOutputString
,
90 ConSplitterTextOutTestString
,
91 ConSplitterTextOutQueryMode
,
92 ConSplitterTextOutSetMode
,
93 ConSplitterTextOutSetAttribute
,
94 ConSplitterTextOutClearScreen
,
95 ConSplitterTextOutSetCursorPosition
,
96 ConSplitterTextOutEnableCursor
,
97 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
108 ConSpliterGraphicsOutputQueryMode
,
109 ConSpliterGraphicsOutputSetMode
,
110 ConSpliterGraphicsOutputBlt
,
113 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
114 (TEXT_OUT_GOP_MODE
*) NULL
,
118 ConSpliterConsoleControlGetMode
,
119 ConSpliterConsoleControlSetMode
,
120 ConSpliterConsoleControlLockStdIn
124 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
126 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
130 EfiConsoleControlScreenText
,
137 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
138 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
141 ConSplitterTextOutReset
,
142 ConSplitterTextOutOutputString
,
143 ConSplitterTextOutTestString
,
144 ConSplitterTextOutQueryMode
,
145 ConSplitterTextOutSetMode
,
146 ConSplitterTextOutSetAttribute
,
147 ConSplitterTextOutClearScreen
,
148 ConSplitterTextOutSetCursorPosition
,
149 ConSplitterTextOutEnableCursor
,
150 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
161 ConSpliterGraphicsOutputQueryMode
,
162 ConSpliterGraphicsOutputSetMode
,
163 ConSpliterGraphicsOutputBlt
,
166 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
167 (TEXT_OUT_GOP_MODE
*) NULL
,
171 ConSpliterConsoleControlGetMode
,
172 ConSpliterConsoleControlSetMode
,
173 ConSpliterConsoleControlLockStdIn
177 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
179 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
183 EfiConsoleControlScreenText
,
190 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
191 ConSplitterConInDriverBindingSupported
,
192 ConSplitterConInDriverBindingStart
,
193 ConSplitterConInDriverBindingStop
,
199 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
200 ConSplitterSimplePointerDriverBindingSupported
,
201 ConSplitterSimplePointerDriverBindingStart
,
202 ConSplitterSimplePointerDriverBindingStop
,
208 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
209 ConSplitterConOutDriverBindingSupported
,
210 ConSplitterConOutDriverBindingStart
,
211 ConSplitterConOutDriverBindingStop
,
217 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
218 ConSplitterStdErrDriverBindingSupported
,
219 ConSplitterStdErrDriverBindingStart
,
220 ConSplitterStdErrDriverBindingStop
,
227 The user Entry Point for module ConSplitter. The user code starts with this function.
229 @param[in] ImageHandle The firmware allocated handle for the EFI image.
230 @param[in] SystemTable A pointer to the EFI System Table.
232 @retval EFI_SUCCESS The entry point is executed successfully.
233 @retval other Some error occurs when executing this entry point.
238 InitializeConSplitter(
239 IN EFI_HANDLE ImageHandle
,
240 IN EFI_SYSTEM_TABLE
*SystemTable
246 // Install driver model protocol(s).
248 Status
= EfiLibInstallAllDriverProtocols (
251 &gConSplitterConInDriverBinding
,
253 &gConSplitterConInComponentName
,
257 ASSERT_EFI_ERROR (Status
);
259 Status
= EfiLibInstallAllDriverProtocols (
262 &gConSplitterSimplePointerDriverBinding
,
264 &gConSplitterSimplePointerComponentName
,
268 ASSERT_EFI_ERROR (Status
);
270 Status
= EfiLibInstallAllDriverProtocols (
273 &gConSplitterConOutDriverBinding
,
275 &gConSplitterConOutComponentName
,
279 ASSERT_EFI_ERROR (Status
);
281 Status
= EfiLibInstallAllDriverProtocols (
284 &gConSplitterStdErrDriverBinding
,
286 &gConSplitterStdErrComponentName
,
290 ASSERT_EFI_ERROR (Status
);
294 // Call the original Entry Point
296 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
304 ConSplitterDriverEntry (
305 IN EFI_HANDLE ImageHandle
,
306 IN EFI_SYSTEM_TABLE
*SystemTable
311 Intialize a virtual console device to act as an agrigator of physical console
315 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
316 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
325 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
326 // The virtual handles will always exist even if no console exist in the
327 // system. This is need to support hotplug devices like USB.
330 // Create virtual device handle for StdErr Splitter
332 Status
= ConSplitterTextOutConstructor (&mStdErr
);
333 if (!EFI_ERROR (Status
)) {
334 Status
= gBS
->InstallMultipleProtocolInterfaces (
335 &mStdErr
.VirtualHandle
,
336 &gEfiSimpleTextOutProtocolGuid
,
338 &gEfiPrimaryStandardErrorDeviceGuid
,
344 // Create virtual device handle for ConIn Splitter
346 Status
= ConSplitterTextInConstructor (&mConIn
);
347 if (!EFI_ERROR (Status
)) {
348 Status
= gBS
->InstallMultipleProtocolInterfaces (
349 &mConIn
.VirtualHandle
,
350 &gEfiSimpleTextInProtocolGuid
,
352 &gEfiSimplePointerProtocolGuid
,
353 &mConIn
.SimplePointer
,
354 &gEfiPrimaryConsoleInDeviceGuid
,
358 if (!EFI_ERROR (Status
)) {
360 // Update the EFI System Table with new virtual console
362 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
363 gST
->ConIn
= &mConIn
.TextIn
;
367 // Create virtual device handle for ConOut Splitter
369 Status
= ConSplitterTextOutConstructor (&mConOut
);
370 if (!EFI_ERROR (Status
)) {
372 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
374 Status
= gBS
->InstallMultipleProtocolInterfaces (
375 &mConOut
.VirtualHandle
,
376 &gEfiSimpleTextOutProtocolGuid
,
378 &gEfiGraphicsOutputProtocolGuid
,
379 &mConOut
.GraphicsOutput
,
380 &gEfiConsoleControlProtocolGuid
,
381 &mConOut
.ConsoleControl
,
382 &gEfiPrimaryConsoleOutDeviceGuid
,
387 if (!EFI_ERROR (Status
)) {
389 // Update the EFI System Table with new virtual console
391 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
392 gST
->ConOut
= &mConOut
.TextOut
;
397 // Update the CRC32 in the EFI System Table header
400 gBS
->CalculateCrc32 (
410 ConSplitterTextInConstructor (
411 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
417 Construct the ConSplitter.
421 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
424 EFI_OUT_OF_RESOURCES - Out of resources.
431 // Initilize console input splitter's private data.
433 Status
= ConSplitterGrowBuffer (
434 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
435 &ConInPrivate
->TextInListCount
,
436 (VOID
**) &ConInPrivate
->TextInList
438 if (EFI_ERROR (Status
)) {
439 return EFI_OUT_OF_RESOURCES
;
442 // Create Event to support locking StdIn Device
444 Status
= gBS
->CreateEvent (
445 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
447 ConSpliterConsoleControlLockStdInEvent
,
449 &ConInPrivate
->LockEvent
451 ASSERT_EFI_ERROR (Status
);
453 Status
= gBS
->CreateEvent (
456 ConSplitterTextInWaitForKey
,
458 &ConInPrivate
->TextIn
.WaitForKey
460 ASSERT_EFI_ERROR (Status
);
462 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
464 Status
= ConSplitterGrowBuffer (
465 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
466 &ConInPrivate
->PointerListCount
,
467 (VOID
**) &ConInPrivate
->PointerList
469 if (EFI_ERROR (Status
)) {
470 return EFI_OUT_OF_RESOURCES
;
473 Status
= gBS
->CreateEvent (
476 ConSplitterSimplePointerWaitForInput
,
478 &ConInPrivate
->SimplePointer
.WaitForInput
485 ConSplitterTextOutConstructor (
486 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
492 // Initilize console output splitter's private data.
494 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
496 Status
= ConSplitterGrowBuffer (
497 sizeof (TEXT_OUT_AND_GOP_DATA
),
498 &ConOutPrivate
->TextOutListCount
,
499 (VOID
**) &ConOutPrivate
->TextOutList
501 if (EFI_ERROR (Status
)) {
502 return EFI_OUT_OF_RESOURCES
;
505 Status
= ConSplitterGrowBuffer (
506 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
507 &ConOutPrivate
->TextOutQueryDataCount
,
508 (VOID
**) &ConOutPrivate
->TextOutQueryData
510 if (EFI_ERROR (Status
)) {
511 return EFI_OUT_OF_RESOURCES
;
514 // Setup the DevNullTextOut console to 80 x 25
516 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
517 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
518 DevNullTextOutSetMode (ConOutPrivate
, 0);
521 // Setup resource for mode information in Graphics Output Protocol interface
523 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
524 return EFI_OUT_OF_RESOURCES
;
526 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
527 return EFI_OUT_OF_RESOURCES
;
530 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
532 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE
))) == NULL
) {
533 return EFI_OUT_OF_RESOURCES
;
535 ConOutPrivate
->GraphicsOutputModeBuffer
[0].HorizontalResolution
= 800;
536 ConOutPrivate
->GraphicsOutputModeBuffer
[0].VerticalResolution
= 600;
539 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
540 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
541 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
543 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
544 ConOutPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
545 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
546 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
547 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
549 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
551 // Initial current mode to unknow state, and then set to mode 0
553 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
554 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
561 ConSplitterSupported (
562 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
563 IN EFI_HANDLE ControllerHandle
,
569 Generic Supported Check
572 This - Pointer to protocol.
573 ControllerHandle - Controller Handle.
578 EFI_UNSUPPORTED - unsupported.
579 EFI_SUCCESS - operation is OK.
587 // Make sure the Console Splitter does not attempt to attach to itself
589 if (ControllerHandle
== mConIn
.VirtualHandle
) {
590 return EFI_UNSUPPORTED
;
593 if (ControllerHandle
== mConOut
.VirtualHandle
) {
594 return EFI_UNSUPPORTED
;
597 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
598 return EFI_UNSUPPORTED
;
601 // Check to see whether the handle has the ConsoleInDevice GUID on it
603 Status
= gBS
->OpenProtocol (
607 This
->DriverBindingHandle
,
609 EFI_OPEN_PROTOCOL_BY_DRIVER
612 if (EFI_ERROR (Status
)) {
619 This
->DriverBindingHandle
,
628 ConSplitterConInDriverBindingSupported (
629 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
630 IN EFI_HANDLE ControllerHandle
,
631 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
636 Console In Supported Check
639 This - Pointer to protocol.
640 ControllerHandle - Controller handle.
641 RemainingDevicePath - Remaining device path.
649 return ConSplitterSupported (
652 &gEfiConsoleInDeviceGuid
658 ConSplitterSimplePointerDriverBindingSupported (
659 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
660 IN EFI_HANDLE ControllerHandle
,
661 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
666 Standard Error Supported Check
669 This - Pointer to protocol.
670 ControllerHandle - Controller handle.
671 RemainingDevicePath - Remaining device path.
679 return ConSplitterSupported (
682 &gEfiSimplePointerProtocolGuid
688 ConSplitterConOutDriverBindingSupported (
689 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
690 IN EFI_HANDLE ControllerHandle
,
691 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
696 Console Out Supported Check
699 This - Pointer to protocol.
700 ControllerHandle - Controller handle.
701 RemainingDevicePath - Remaining device path.
709 return ConSplitterSupported (
712 &gEfiConsoleOutDeviceGuid
718 ConSplitterStdErrDriverBindingSupported (
719 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
720 IN EFI_HANDLE ControllerHandle
,
721 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
726 Standard Error Supported Check
729 This - Pointer to protocol.
730 ControllerHandle - Controller handle.
731 RemainingDevicePath - Remaining device path.
739 return ConSplitterSupported (
742 &gEfiStandardErrorDeviceGuid
750 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
751 IN EFI_HANDLE ControllerHandle
,
752 IN EFI_HANDLE ConSplitterVirtualHandle
,
753 IN EFI_GUID
*DeviceGuid
,
754 IN EFI_GUID
*InterfaceGuid
,
760 Start ConSplitter on ControllerHandle, and create the virtual
761 agrogated console device on first call Start for a SimpleTextIn handle.
764 (Standard DriverBinding Protocol Start() function)
767 EFI_ERROR if a SimpleTextIn protocol is not started.
775 // Check to see whether the handle has the ConsoleInDevice GUID on it
777 Status
= gBS
->OpenProtocol (
781 This
->DriverBindingHandle
,
783 EFI_OPEN_PROTOCOL_BY_DRIVER
785 if (EFI_ERROR (Status
)) {
789 Status
= gBS
->OpenProtocol (
793 This
->DriverBindingHandle
,
794 ConSplitterVirtualHandle
,
795 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
797 if (EFI_ERROR (Status
)) {
801 return gBS
->OpenProtocol (
805 This
->DriverBindingHandle
,
806 ConSplitterVirtualHandle
,
807 EFI_OPEN_PROTOCOL_GET_PROTOCOL
813 ConSplitterConInDriverBindingStart (
814 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
815 IN EFI_HANDLE ControllerHandle
,
816 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
821 Start ConSplitter on ControllerHandle, and create the virtual
822 agrogated console device on first call Start for a SimpleTextIn handle.
825 This - Pointer to protocol.
826 ControllerHandle - Controller handle.
827 RemainingDevicePath - Remaining device path.
832 EFI_ERROR if a SimpleTextIn protocol is not started.
837 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
840 // Start ConSplitter on ControllerHandle, and create the virtual
841 // agrogated console device on first call Start for a SimpleTextIn handle.
843 Status
= ConSplitterStart (
846 mConIn
.VirtualHandle
,
847 &gEfiConsoleInDeviceGuid
,
848 &gEfiSimpleTextInProtocolGuid
,
851 if (EFI_ERROR (Status
)) {
855 return ConSplitterTextInAddDevice (&mConIn
, TextIn
);
860 ConSplitterSimplePointerDriverBindingStart (
861 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
862 IN EFI_HANDLE ControllerHandle
,
863 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
868 Start ConSplitter on ControllerHandle, and create the virtual
869 agrogated console device on first call Start for a SimpleTextIn handle.
872 This - Pointer to protocol.
873 ControllerHandle - Controller handle.
874 RemainingDevicePath - Remaining device path.
878 EFI_ERROR if a SimpleTextIn protocol is not started.
883 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
885 Status
= ConSplitterStart (
888 mConIn
.VirtualHandle
,
889 &gEfiSimplePointerProtocolGuid
,
890 &gEfiSimplePointerProtocolGuid
,
891 (VOID
**) &SimplePointer
893 if (EFI_ERROR (Status
)) {
897 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
902 ConSplitterConOutDriverBindingStart (
903 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
904 IN EFI_HANDLE ControllerHandle
,
905 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
910 Start ConSplitter on ControllerHandle, and create the virtual
911 agrogated console device on first call Start for a SimpleTextIn handle.
914 This - Pointer to protocol.
915 ControllerHandle - Controller handle.
916 RemainingDevicePath - Remaining device path.
919 EFI_ERROR if a SimpleTextIn protocol is not started.
924 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
925 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
926 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
928 Status
= ConSplitterStart (
931 mConOut
.VirtualHandle
,
932 &gEfiConsoleOutDeviceGuid
,
933 &gEfiSimpleTextOutProtocolGuid
,
936 if (EFI_ERROR (Status
)) {
940 // Try to Open Graphics Output protocol
942 Status
= gBS
->OpenProtocol (
944 &gEfiGraphicsOutputProtocolGuid
,
945 (VOID
**) &GraphicsOutput
,
946 This
->DriverBindingHandle
,
947 mConOut
.VirtualHandle
,
948 EFI_OPEN_PROTOCOL_GET_PROTOCOL
950 if (EFI_ERROR (Status
)) {
951 GraphicsOutput
= NULL
;
954 // Open UGA_DRAW protocol
956 Status
= gBS
->OpenProtocol (
958 &gEfiUgaDrawProtocolGuid
,
960 This
->DriverBindingHandle
,
961 mConOut
.VirtualHandle
,
962 EFI_OPEN_PROTOCOL_GET_PROTOCOL
964 if (EFI_ERROR (Status
)) {
968 // If both ConOut and StdErr incorporate the same Text Out device,
969 // their MaxMode and QueryData should be the intersection of both.
971 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
972 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
979 ConSplitterStdErrDriverBindingStart (
980 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
981 IN EFI_HANDLE ControllerHandle
,
982 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
987 Start ConSplitter on ControllerHandle, and create the virtual
988 agrogated console device on first call Start for a SimpleTextIn handle.
991 This - Pointer to protocol.
992 ControllerHandle - Controller handle.
993 RemainingDevicePath - Remaining device path.
996 EFI_ERROR if a SimpleTextIn protocol is not started.
1001 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1003 Status
= ConSplitterStart (
1006 mStdErr
.VirtualHandle
,
1007 &gEfiStandardErrorDeviceGuid
,
1008 &gEfiSimpleTextOutProtocolGuid
,
1011 if (EFI_ERROR (Status
)) {
1015 // If both ConOut and StdErr incorporate the same Text Out device,
1016 // their MaxMode and QueryData should be the intersection of both.
1018 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1019 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1020 if (EFI_ERROR (Status
)) {
1024 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1025 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1026 gST
->StdErr
= &mStdErr
.TextOut
;
1028 // Update the CRC32 in the EFI System Table header
1031 gBS
->CalculateCrc32 (
1032 (UINT8
*) &gST
->Hdr
,
1033 gST
->Hdr
.HeaderSize
,
1045 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1046 IN EFI_HANDLE ControllerHandle
,
1047 IN EFI_HANDLE ConSplitterVirtualHandle
,
1048 IN EFI_GUID
*DeviceGuid
,
1049 IN EFI_GUID
*InterfaceGuid
,
1054 Routine Description:
1057 (Standard DriverBinding Protocol Stop() function)
1067 Status
= gBS
->OpenProtocol (
1071 This
->DriverBindingHandle
,
1073 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1075 if (EFI_ERROR (Status
)) {
1079 // close the protocol refered.
1081 gBS
->CloseProtocol (
1084 This
->DriverBindingHandle
,
1085 ConSplitterVirtualHandle
1087 gBS
->CloseProtocol (
1090 This
->DriverBindingHandle
,
1099 ConSplitterConInDriverBindingStop (
1100 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1101 IN EFI_HANDLE ControllerHandle
,
1102 IN UINTN NumberOfChildren
,
1103 IN EFI_HANDLE
*ChildHandleBuffer
1107 Routine Description:
1110 (Standard DriverBinding Protocol Stop() function)
1119 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1121 if (NumberOfChildren
== 0) {
1125 Status
= ConSplitterStop (
1128 mConIn
.VirtualHandle
,
1129 &gEfiConsoleInDeviceGuid
,
1130 &gEfiSimpleTextInProtocolGuid
,
1133 if (EFI_ERROR (Status
)) {
1137 // Delete this console input device's data structures.
1139 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1144 ConSplitterSimplePointerDriverBindingStop (
1145 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1146 IN EFI_HANDLE ControllerHandle
,
1147 IN UINTN NumberOfChildren
,
1148 IN EFI_HANDLE
*ChildHandleBuffer
1152 Routine Description:
1155 (Standard DriverBinding Protocol Stop() function)
1164 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1166 if (NumberOfChildren
== 0) {
1170 Status
= ConSplitterStop (
1173 mConIn
.VirtualHandle
,
1174 &gEfiSimplePointerProtocolGuid
,
1175 &gEfiSimplePointerProtocolGuid
,
1176 (VOID
**) &SimplePointer
1178 if (EFI_ERROR (Status
)) {
1182 // Delete this console input device's data structures.
1184 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1189 ConSplitterConOutDriverBindingStop (
1190 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1191 IN EFI_HANDLE ControllerHandle
,
1192 IN UINTN NumberOfChildren
,
1193 IN EFI_HANDLE
*ChildHandleBuffer
1197 Routine Description:
1200 (Standard DriverBinding Protocol Stop() function)
1209 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1211 if (NumberOfChildren
== 0) {
1215 Status
= ConSplitterStop (
1218 mConOut
.VirtualHandle
,
1219 &gEfiConsoleOutDeviceGuid
,
1220 &gEfiSimpleTextOutProtocolGuid
,
1223 if (EFI_ERROR (Status
)) {
1228 // Delete this console output device's data structures.
1230 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1235 ConSplitterStdErrDriverBindingStop (
1236 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1237 IN EFI_HANDLE ControllerHandle
,
1238 IN UINTN NumberOfChildren
,
1239 IN EFI_HANDLE
*ChildHandleBuffer
1243 Routine Description:
1246 (Standard DriverBinding Protocol Stop() function)
1250 EFI_SUCCESS - Complete successfully.
1255 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1257 if (NumberOfChildren
== 0) {
1261 Status
= ConSplitterStop (
1264 mStdErr
.VirtualHandle
,
1265 &gEfiStandardErrorDeviceGuid
,
1266 &gEfiSimpleTextOutProtocolGuid
,
1269 if (EFI_ERROR (Status
)) {
1273 // Delete this console error out device's data structures.
1275 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1276 if (EFI_ERROR (Status
)) {
1280 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1281 gST
->StandardErrorHandle
= NULL
;
1284 // Update the CRC32 in the EFI System Table header
1287 gBS
->CalculateCrc32 (
1288 (UINT8
*) &gST
->Hdr
,
1289 gST
->Hdr
.HeaderSize
,
1298 ConSplitterGrowBuffer (
1299 IN UINTN SizeOfCount
,
1301 IN OUT VOID
**Buffer
1305 Routine Description:
1306 Take the passed in Buffer of size SizeOfCount and grow the buffer
1307 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1308 bytes. Copy the current data in Buffer to the new version of Buffer
1309 and free the old version of buffer.
1313 SizeOfCount - Size of element in array
1314 Count - Current number of elements in array
1315 Buffer - Bigger version of passed in Buffer with all the data
1318 EFI_SUCCESS - Buffer size has grown
1319 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1330 // grow the buffer to new buffer size,
1331 // copy the old buffer's content to the new-size buffer,
1332 // then free the old buffer.
1334 OldSize
= *Count
* SizeOfCount
;
1335 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1336 NewSize
= *Count
* SizeOfCount
;
1338 Ptr
= AllocateZeroPool (NewSize
);
1340 return EFI_OUT_OF_RESOURCES
;
1343 CopyMem (Ptr
, *Buffer
, OldSize
);
1345 if (*Buffer
!= NULL
) {
1355 ConSplitterTextInAddDevice (
1356 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1357 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1361 Routine Description:
1368 EFI_OUT_OF_RESOURCES
1375 // If the Text In List is full, enlarge it by calling growbuffer().
1377 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1378 Status
= ConSplitterGrowBuffer (
1379 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1380 &Private
->TextInListCount
,
1381 (VOID
**) &Private
->TextInList
1383 if (EFI_ERROR (Status
)) {
1384 return EFI_OUT_OF_RESOURCES
;
1388 // Add the new text-in device data structure into the Text In List.
1390 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1391 Private
->CurrentNumberOfConsoles
++;
1394 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1396 gBS
->CheckEvent (TextIn
->WaitForKey
);
1402 ConSplitterTextInDeleteDevice (
1403 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1404 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1408 Routine Description:
1421 // Remove the specified text-in device data structure from the Text In List,
1422 // and rearrange the remaining data structures in the Text In List.
1424 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1425 if (Private
->TextInList
[Index
] == TextIn
) {
1426 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1427 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1430 Private
->CurrentNumberOfConsoles
--;
1435 return EFI_NOT_FOUND
;
1439 ConSplitterSimplePointerAddDevice (
1440 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1441 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1445 Routine Description:
1451 EFI_OUT_OF_RESOURCES
1459 // If the Text In List is full, enlarge it by calling growbuffer().
1461 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1462 Status
= ConSplitterGrowBuffer (
1463 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1464 &Private
->PointerListCount
,
1465 (VOID
**) &Private
->PointerList
1467 if (EFI_ERROR (Status
)) {
1468 return EFI_OUT_OF_RESOURCES
;
1472 // Add the new text-in device data structure into the Text In List.
1474 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1475 Private
->CurrentNumberOfPointers
++;
1480 ConSplitterSimplePointerDeleteDevice (
1481 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1482 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1486 Routine Description:
1498 // Remove the specified text-in device data structure from the Text In List,
1499 // and rearrange the remaining data structures in the Text In List.
1501 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1502 if (Private
->PointerList
[Index
] == SimplePointer
) {
1503 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1504 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1507 Private
->CurrentNumberOfPointers
--;
1512 return EFI_NOT_FOUND
;
1517 ConSplitterGrowMapTable (
1518 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1522 Routine Description:
1535 INT32
*TextOutModeMap
;
1536 INT32
*OldTextOutModeMap
;
1540 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1541 OldTextOutModeMap
= Private
->TextOutModeMap
;
1542 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1544 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1545 if (TextOutModeMap
== NULL
) {
1546 return EFI_OUT_OF_RESOURCES
;
1549 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1550 Private
->TextOutModeMap
= TextOutModeMap
;
1553 // If TextOutList has been enlarged, need to realloc the mode map table
1554 // The mode map table is regarded as a two dimension array.
1557 // 0 ---------> TextOutListCount ----> TextOutListCount
1558 // | -------------------------------------------
1565 // -------------------------------------------
1568 if (OldTextOutModeMap
!= NULL
) {
1570 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1572 SrcAddress
= OldTextOutModeMap
;
1575 // Copy the old data to the new one
1577 while (Index
< Private
->TextOutMode
.MaxMode
) {
1578 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1579 TextOutModeMap
+= NewSize
;
1584 // Free the old buffer
1586 FreePool (OldTextOutModeMap
);
1594 ConSplitterAddOutputMode (
1595 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1596 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1600 Routine Description:
1615 MaxMode
= TextOut
->Mode
->MaxMode
;
1616 Private
->TextOutMode
.MaxMode
= MaxMode
;
1619 // Grow the buffer if query data buffer is not large enough to
1620 // hold all the mode supported by the first console.
1622 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
1623 Status
= ConSplitterGrowBuffer (
1624 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
1625 &Private
->TextOutQueryDataCount
,
1626 (VOID
**) &Private
->TextOutQueryData
1628 if (EFI_ERROR (Status
)) {
1629 return EFI_OUT_OF_RESOURCES
;
1633 // Allocate buffer for the output mode map
1635 Status
= ConSplitterGrowMapTable (Private
);
1636 if (EFI_ERROR (Status
)) {
1637 return EFI_OUT_OF_RESOURCES
;
1640 // As the first textout device, directly add the mode in to QueryData
1641 // and at the same time record the mapping between QueryData and TextOut.
1645 while (Mode
< MaxMode
) {
1646 TextOut
->QueryMode (
1649 &Private
->TextOutQueryData
[Mode
].Columns
,
1650 &Private
->TextOutQueryData
[Mode
].Rows
1652 Private
->TextOutModeMap
[Index
] = Mode
;
1654 Index
+= Private
->TextOutListCount
;
1662 ConSplitterGetIntersection (
1663 IN INT32
*TextOutModeMap
,
1664 IN INT32
*NewlyAddedMap
,
1665 IN UINTN MapStepSize
,
1666 IN UINTN NewMapStepSize
,
1668 OUT INT32
*CurrentMode
1672 INT32
*CurrentMapEntry
;
1673 INT32
*NextMapEntry
;
1674 INT32 CurrentMaxMode
;
1678 CurrentMapEntry
= TextOutModeMap
;
1679 NextMapEntry
= TextOutModeMap
;
1680 CurrentMaxMode
= *MaxMode
;
1681 Mode
= *CurrentMode
;
1683 while (Index
< CurrentMaxMode
) {
1684 if (*NewlyAddedMap
== -1) {
1686 // This mode is not supported any more. Remove it. Special care
1687 // must be taken as this remove will also affect current mode;
1689 if (Index
== *CurrentMode
) {
1691 } else if (Index
< *CurrentMode
) {
1696 if (CurrentMapEntry
!= NextMapEntry
) {
1697 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
1700 NextMapEntry
+= MapStepSize
;
1703 CurrentMapEntry
+= MapStepSize
;
1704 NewlyAddedMap
+= NewMapStepSize
;
1708 *CurrentMode
= Mode
;
1715 ConSplitterSyncOutputMode (
1716 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1717 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
1721 Routine Description:
1724 Private - Private data structure.
1725 TextOut - Text Out Protocol.
1732 INT32 CurrentMaxMode
;
1735 INT32
*TextOutModeMap
;
1737 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
1743 // Must make sure that current mode won't change even if mode number changes
1745 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
1746 TextOutModeMap
= Private
->TextOutModeMap
;
1747 StepSize
= Private
->TextOutListCount
;
1748 TextOutQueryData
= Private
->TextOutQueryData
;
1751 // Query all the mode that the newly added TextOut supports
1754 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
1755 while (Mode
< TextOut
->Mode
->MaxMode
) {
1756 TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
1759 // Search the QueryData database to see if they intersects
1762 while (Index
< CurrentMaxMode
) {
1763 if ((TextOutQueryData
[Index
].Rows
== Rows
) && (TextOutQueryData
[Index
].Columns
== Columns
)) {
1764 MapTable
[Index
* StepSize
] = Mode
;
1774 // Now search the TextOutModeMap table to find the intersection of supported
1775 // mode between ConSplitter and the newly added device.
1777 ConSplitterGetIntersection (
1782 &Private
->TextOutMode
.MaxMode
,
1783 &Private
->TextOutMode
.Mode
1791 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1796 Routine Description:
1803 EFI_OUT_OF_RESOURCES
1807 UINTN ConOutNumOfConsoles
;
1808 UINTN StdErrNumOfConsoles
;
1809 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
1810 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
1815 INT32 ConOutMaxMode
;
1816 INT32 StdErrMaxMode
;
1819 INT32
*ConOutModeMap
;
1820 INT32
*StdErrModeMap
;
1821 INT32
*ConOutMapTable
;
1822 INT32
*StdErrMapTable
;
1823 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
1824 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
1825 BOOLEAN FoundTheSameTextOut
;
1826 UINTN ConOutMapTableSize
;
1827 UINTN StdErrMapTableSize
;
1829 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
1830 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
1831 ConOutTextOutList
= mConOut
.TextOutList
;
1832 StdErrTextOutList
= mStdErr
.TextOutList
;
1835 FoundTheSameTextOut
= FALSE
;
1836 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
1838 while (Indexj
< StdErrNumOfConsoles
) {
1839 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
1840 FoundTheSameTextOut
= TRUE
;
1845 StdErrTextOutList
++;
1849 ConOutTextOutList
++;
1852 if (!FoundTheSameTextOut
) {
1856 // Must make sure that current mode won't change even if mode number changes
1858 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
1859 ConOutModeMap
= mConOut
.TextOutModeMap
;
1860 ConOutQueryData
= mConOut
.TextOutQueryData
;
1862 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
1863 StdErrModeMap
= mStdErr
.TextOutModeMap
;
1864 StdErrQueryData
= mStdErr
.TextOutQueryData
;
1867 // Allocate the map table and set the map table's index to -1.
1869 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
1870 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
1871 if (ConOutMapTable
== NULL
) {
1872 return EFI_OUT_OF_RESOURCES
;
1875 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
1877 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
1878 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
1879 if (StdErrMapTable
== NULL
) {
1880 return EFI_OUT_OF_RESOURCES
;
1883 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
1886 // Find the intersection of the two set of modes. If they actually intersect, the
1887 // correponding entry in the map table is set to 1.
1890 while (Mode
< ConOutMaxMode
) {
1892 // Search the other's QueryData database to see if they intersect
1895 Rows
= ConOutQueryData
[Mode
].Rows
;
1896 Columns
= ConOutQueryData
[Mode
].Columns
;
1897 while (Index
< StdErrMaxMode
) {
1898 if ((StdErrQueryData
[Index
].Rows
== Rows
) && (StdErrQueryData
[Index
].Columns
== Columns
)) {
1899 ConOutMapTable
[Mode
] = 1;
1900 StdErrMapTable
[Index
] = 1;
1910 // Now search the TextOutModeMap table to find the intersection of supported
1911 // mode between ConSplitter and the newly added device.
1913 ConSplitterGetIntersection (
1916 mConOut
.TextOutListCount
,
1918 &(mConOut
.TextOutMode
.MaxMode
),
1919 &(mConOut
.TextOutMode
.Mode
)
1921 if (mConOut
.TextOutMode
.Mode
< 0) {
1922 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
1925 ConSplitterGetIntersection (
1928 mStdErr
.TextOutListCount
,
1930 &(mStdErr
.TextOutMode
.MaxMode
),
1931 &(mStdErr
.TextOutMode
.Mode
)
1933 if (mStdErr
.TextOutMode
.Mode
< 0) {
1934 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
1937 FreePool (ConOutMapTable
);
1938 FreePool (StdErrMapTable
);
1945 ConSplitterAddGraphicsOutputMode (
1946 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1947 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1948 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1952 Routine Description:
1964 TEXT_OUT_GOP_MODE
*Mode
;
1966 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
1967 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
1968 TEXT_OUT_GOP_MODE
*ModeBuffer
;
1969 TEXT_OUT_GOP_MODE
*MatchedMode
;
1973 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
1974 return EFI_UNSUPPORTED
;
1977 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
1979 if (GraphicsOutput
!= NULL
) {
1980 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
1982 // This is the first Graphics Output device added
1984 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
1985 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
1986 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
1987 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
1988 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
1989 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
1992 // Allocate resource for the private mode buffer
1994 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * GraphicsOutput
->Mode
->MaxMode
);
1995 if (ModeBuffer
== NULL
) {
1996 return EFI_OUT_OF_RESOURCES
;
1998 FreePool (Private
->GraphicsOutputModeBuffer
);
1999 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2002 // Store all supported display modes to the private mode buffer
2005 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2006 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2007 if (EFI_ERROR (Status
)) {
2010 Mode
->HorizontalResolution
= Info
->HorizontalResolution
;
2011 Mode
->VerticalResolution
= Info
->VerticalResolution
;
2017 // Check intersection of display mode
2019 ModeBuffer
= AllocatePool (sizeof (TEXT_OUT_GOP_MODE
) * CurrentGraphicsOutputMode
->MaxMode
);
2020 if (ModeBuffer
== NULL
) {
2021 return EFI_OUT_OF_RESOURCES
;
2024 MatchedMode
= ModeBuffer
;
2025 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2026 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2029 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2030 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2031 if (EFI_ERROR (Status
)) {
2034 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2035 (Info
->VerticalResolution
== Mode
->VerticalResolution
)){
2044 CopyMem (MatchedMode
, Mode
, sizeof (TEXT_OUT_GOP_MODE
));
2052 // Drop the old mode buffer, assign it to a new one
2054 FreePool (Private
->GraphicsOutputModeBuffer
);
2055 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2058 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2060 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (TEXT_OUT_GOP_MODE
));
2061 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2062 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2063 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2064 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2065 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2069 // Select a prefered Display mode 800x600
2071 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2072 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2073 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2078 // Prefered mode is not found, set to mode 0
2080 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2085 // Current mode number may need update now, so set it to an invalide mode number
2087 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2090 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2091 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2093 CurrentGraphicsOutputMode
->MaxMode
= 1;
2094 CurrentGraphicsOutputMode
->Info
->Version
= 0;
2095 CurrentGraphicsOutputMode
->Info
->HorizontalResolution
= 800;
2096 CurrentGraphicsOutputMode
->Info
->VerticalResolution
= 600;
2097 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2098 CurrentGraphicsOutputMode
->Info
->PixelsPerScanLine
= 800;
2099 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2100 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
2101 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2104 // Update the private mode buffer
2106 ModeBuffer
= &Private
->GraphicsOutputModeBuffer
[0];
2107 ModeBuffer
->HorizontalResolution
= 800;
2108 ModeBuffer
->VerticalResolution
= 600;
2111 // Current mode is unknow now, set it to an invalid mode number 0xffff
2113 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2118 // Force GraphicsOutput mode to be set,
2119 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2121 Private
->HardwareNeedsStarting
= TRUE
;
2122 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) Index
);
2124 Private
->CurrentNumberOfGraphicsOutput
++;
2130 ConSplitterTextOutAddDevice (
2131 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2132 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2133 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2134 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2138 Routine Description:
2149 UINTN CurrentNumOfConsoles
;
2152 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2154 Status
= EFI_SUCCESS
;
2155 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2158 // If the Text Out List is full, enlarge it by calling growbuffer().
2160 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2161 Status
= ConSplitterGrowBuffer (
2162 sizeof (TEXT_OUT_AND_GOP_DATA
),
2163 &Private
->TextOutListCount
,
2164 (VOID
**) &Private
->TextOutList
2166 if (EFI_ERROR (Status
)) {
2167 return EFI_OUT_OF_RESOURCES
;
2170 // Also need to reallocate the TextOutModeMap table
2172 Status
= ConSplitterGrowMapTable (Private
);
2173 if (EFI_ERROR (Status
)) {
2174 return EFI_OUT_OF_RESOURCES
;
2178 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2180 TextAndGop
->TextOut
= TextOut
;
2181 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2182 TextAndGop
->UgaDraw
= UgaDraw
;
2184 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2186 // If No UGA device then use the ConOut device
2188 TextAndGop
->TextOutEnabled
= TRUE
;
2191 // If UGA device use ConOut device only used if UGA screen is in Text mode
2193 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2196 if (CurrentNumOfConsoles
== 0) {
2198 // Add the first device's output mode to console splitter's mode list
2200 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2202 ConSplitterSyncOutputMode (Private
, TextOut
);
2205 Private
->CurrentNumberOfConsoles
++;
2208 // Scan both TextOutList, for the intersection TextOut device
2209 // maybe both ConOut and StdErr incorporate the same Text Out
2210 // device in them, thus the output of both should be synced.
2212 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2214 CurrentMode
= Private
->TextOutMode
.Mode
;
2215 MaxMode
= Private
->TextOutMode
.MaxMode
;
2216 ASSERT (MaxMode
>= 1);
2218 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2219 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2222 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2224 // We just added a new UGA device in graphics mode
2226 DevNullGopSync (Private
, GraphicsOutput
, UgaDraw
);
2227 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2229 // The new console supports the same mode of the current console so sync up
2231 DevNullSyncGopStdOut (Private
);
2234 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2236 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2243 ConSplitterTextOutDeleteDevice (
2244 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2245 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2249 Routine Description:
2260 UINTN CurrentNumOfConsoles
;
2261 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2265 // Remove the specified text-out device data structure from the Text out List,
2266 // and rearrange the remaining data structures in the Text out List.
2268 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2269 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2270 TextOutList
= Private
->TextOutList
;
2271 while (Index
>= 0) {
2272 if (TextOutList
->TextOut
== TextOut
) {
2273 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2274 CurrentNumOfConsoles
--;
2282 // The specified TextOut is not managed by the ConSplitter driver
2285 return EFI_NOT_FOUND
;
2288 if (CurrentNumOfConsoles
== 0) {
2290 // If the number of consoles is zero clear the Dev NULL device
2292 Private
->CurrentNumberOfConsoles
= 0;
2293 Private
->TextOutMode
.MaxMode
= 1;
2294 Private
->TextOutQueryData
[0].Columns
= 80;
2295 Private
->TextOutQueryData
[0].Rows
= 25;
2296 DevNullTextOutSetMode (Private
, 0);
2301 // Max Mode is realy an intersection of the QueryMode command to all
2302 // devices. So we must copy the QueryMode of the first device to
2306 Private
->TextOutQueryData
,
2307 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2310 FreePool (Private
->TextOutModeMap
);
2311 Private
->TextOutModeMap
= NULL
;
2312 TextOutList
= Private
->TextOutList
;
2315 // Add the first TextOut to the QueryData array and ModeMap table
2317 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2320 // Now add one by one
2323 Private
->CurrentNumberOfConsoles
= 1;
2325 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
2326 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
2328 Private
->CurrentNumberOfConsoles
++;
2332 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2337 // ConSplitter TextIn member functions
2341 ConSplitterTextInReset (
2342 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2343 IN BOOLEAN ExtendedVerification
2347 Routine Description:
2348 Reset the input device and optionaly run diagnostics
2351 This - Protocol instance pointer.
2352 ExtendedVerification - Driver may perform diagnostics on reset.
2355 EFI_SUCCESS - The device was reset.
2356 EFI_DEVICE_ERROR - The device is not functioning properly and could
2362 EFI_STATUS ReturnStatus
;
2363 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2366 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2368 Private
->KeyEventSignalState
= FALSE
;
2371 // return the worst status met
2373 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2374 Status
= Private
->TextInList
[Index
]->Reset (
2375 Private
->TextInList
[Index
],
2376 ExtendedVerification
2378 if (EFI_ERROR (Status
)) {
2379 ReturnStatus
= Status
;
2383 return ReturnStatus
;
2388 ConSplitterTextInPrivateReadKeyStroke (
2389 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2390 OUT EFI_INPUT_KEY
*Key
2394 Routine Description:
2395 Reads the next keystroke from the input device. The WaitForKey Event can
2396 be used to test for existance of a keystroke via WaitForEvent () call.
2399 This - Protocol instance pointer.
2400 Key - Driver may perform diagnostics on reset.
2403 EFI_SUCCESS - The keystroke information was returned.
2404 EFI_NOT_READY - There was no keystroke data availiable.
2405 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2412 EFI_INPUT_KEY CurrentKey
;
2414 Key
->UnicodeChar
= 0;
2415 Key
->ScanCode
= SCAN_NULL
;
2418 // if no physical console input device exists, return EFI_NOT_READY;
2419 // if any physical console input device has key input,
2420 // return the key and EFI_SUCCESS.
2422 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2423 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
2424 Private
->TextInList
[Index
],
2427 if (!EFI_ERROR (Status
)) {
2433 return EFI_NOT_READY
;
2437 ConSpliterConssoleControlStdInLocked (
2442 Routine Description:
2443 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2444 the only device locked.
2451 FALSE - StdIn working normally
2455 return mConIn
.PasswordEnabled
;
2460 ConSpliterConsoleControlLockStdInEvent (
2466 Routine Description:
2467 This timer event will fire when StdIn is locked. It will check the key
2468 sequence on StdIn to see if it matches the password. Any error in the
2469 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2470 TRUE the StdIn splitter will not report any input.
2473 (Standard EFI_EVENT_NOTIFY)
2482 CHAR16 BackSpaceString
[2];
2483 CHAR16 SpaceString
[2];
2486 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
2487 if (!EFI_ERROR (Status
)) {
2489 // if it's an ENTER, match password
2491 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
2492 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
2493 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
2495 // Password not match
2497 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
2498 mConIn
.PwdIndex
= 0;
2501 // Key matches password sequence
2503 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
2504 mConIn
.PasswordEnabled
= FALSE
;
2505 Status
= EFI_NOT_READY
;
2507 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
2511 if (mConIn
.PwdIndex
> 0) {
2512 BackSpaceString
[0] = CHAR_BACKSPACE
;
2513 BackSpaceString
[1] = 0;
2515 SpaceString
[0] = ' ';
2518 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2519 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
2520 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
2524 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
2526 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2528 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
2529 if (mConIn
.PwdIndex
== 0) {
2530 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
2533 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
2534 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
2539 } while (!EFI_ERROR (Status
));
2544 ConSpliterConsoleControlLockStdIn (
2545 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
2550 Routine Description:
2551 If Password is NULL unlock the password state variable and set the event
2552 timer. If the Password is too big return an error. If the Password is valid
2553 Copy the Password and enable state variable and then arm the periodic timer
2558 EFI_SUCCESS - Lock the StdIn device
2559 EFI_INVALID_PARAMETER - Password is NULL
2560 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2564 if (Password
== NULL
) {
2565 return EFI_INVALID_PARAMETER
;
2568 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
2570 // Currently have a max password size
2572 return EFI_OUT_OF_RESOURCES
;
2575 // Save the password, initialize state variables and arm event timer
2577 StrCpy (mConIn
.Password
, Password
);
2578 mConIn
.PasswordEnabled
= TRUE
;
2579 mConIn
.PwdIndex
= 0;
2580 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
2587 ConSplitterTextInReadKeyStroke (
2588 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
2589 OUT EFI_INPUT_KEY
*Key
2593 Routine Description:
2594 Reads the next keystroke from the input device. The WaitForKey Event can
2595 be used to test for existance of a keystroke via WaitForEvent () call.
2596 If the ConIn is password locked make it look like no keystroke is availible
2599 This - Protocol instance pointer.
2600 Key - Driver may perform diagnostics on reset.
2603 EFI_SUCCESS - The keystroke information was returned.
2604 EFI_NOT_READY - There was no keystroke data availiable.
2605 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2610 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2612 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2613 if (Private
->PasswordEnabled
) {
2615 // If StdIn Locked return not ready
2617 return EFI_NOT_READY
;
2620 Private
->KeyEventSignalState
= FALSE
;
2622 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
2627 ConSplitterTextInWaitForKey (
2633 Routine Description:
2634 This event agregates all the events of the ConIn devices in the spliter.
2635 If the ConIn is password locked then return.
2636 If any events of physical ConIn devices are signaled, signal the ConIn
2637 spliter event. This will cause the calling code to call
2638 ConSplitterTextInReadKeyStroke ().
2641 Event - The Event assoicated with callback.
2642 Context - Context registered when Event was created.
2650 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2653 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2654 if (Private
->PasswordEnabled
) {
2656 // If StdIn Locked return not ready
2662 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2664 if (Private
->KeyEventSignalState
) {
2665 gBS
->SignalEvent (Event
);
2669 // if any physical console input device has key input, signal the event.
2671 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2672 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
2673 if (!EFI_ERROR (Status
)) {
2674 gBS
->SignalEvent (Event
);
2675 Private
->KeyEventSignalState
= TRUE
;
2682 ConSplitterSimplePointerReset (
2683 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2684 IN BOOLEAN ExtendedVerification
2688 Routine Description:
2689 Reset the input device and optionaly run diagnostics
2692 This - Protocol instance pointer.
2693 ExtendedVerification - Driver may perform diagnostics on reset.
2696 EFI_SUCCESS - The device was reset.
2697 EFI_DEVICE_ERROR - The device is not functioning properly and could
2703 EFI_STATUS ReturnStatus
;
2704 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2707 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2709 Private
->InputEventSignalState
= FALSE
;
2711 if (Private
->CurrentNumberOfPointers
== 0) {
2715 // return the worst status met
2717 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2718 Status
= Private
->PointerList
[Index
]->Reset (
2719 Private
->PointerList
[Index
],
2720 ExtendedVerification
2722 if (EFI_ERROR (Status
)) {
2723 ReturnStatus
= Status
;
2727 return ReturnStatus
;
2733 ConSplitterSimplePointerPrivateGetState (
2734 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
2735 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2739 Routine Description:
2740 Reads the next keystroke from the input device. The WaitForKey Event can
2741 be used to test for existance of a keystroke via WaitForEvent () call.
2744 This - Protocol instance pointer.
2748 EFI_SUCCESS - The keystroke information was returned.
2749 EFI_NOT_READY - There was no keystroke data availiable.
2750 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2756 EFI_STATUS ReturnStatus
;
2758 EFI_SIMPLE_POINTER_STATE CurrentState
;
2760 State
->RelativeMovementX
= 0;
2761 State
->RelativeMovementY
= 0;
2762 State
->RelativeMovementZ
= 0;
2763 State
->LeftButton
= FALSE
;
2764 State
->RightButton
= FALSE
;
2767 // if no physical console input device exists, return EFI_NOT_READY;
2768 // if any physical console input device has key input,
2769 // return the key and EFI_SUCCESS.
2771 ReturnStatus
= EFI_NOT_READY
;
2772 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2774 Status
= Private
->PointerList
[Index
]->GetState (
2775 Private
->PointerList
[Index
],
2778 if (!EFI_ERROR (Status
)) {
2779 if (ReturnStatus
== EFI_NOT_READY
) {
2780 ReturnStatus
= EFI_SUCCESS
;
2783 if (CurrentState
.LeftButton
) {
2784 State
->LeftButton
= TRUE
;
2787 if (CurrentState
.RightButton
) {
2788 State
->RightButton
= TRUE
;
2791 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
2792 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
2795 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
2796 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
2799 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
2800 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
2802 } else if (Status
== EFI_DEVICE_ERROR
) {
2803 ReturnStatus
= EFI_DEVICE_ERROR
;
2807 return ReturnStatus
;
2812 ConSplitterSimplePointerGetState (
2813 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
2814 IN OUT EFI_SIMPLE_POINTER_STATE
*State
2818 Routine Description:
2819 Reads the next keystroke from the input device. The WaitForKey Event can
2820 be used to test for existance of a keystroke via WaitForEvent () call.
2821 If the ConIn is password locked make it look like no keystroke is availible
2824 This - Protocol instance pointer.
2828 EFI_SUCCESS - The keystroke information was returned.
2829 EFI_NOT_READY - There was no keystroke data availiable.
2830 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2835 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2837 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
2838 if (Private
->PasswordEnabled
) {
2840 // If StdIn Locked return not ready
2842 return EFI_NOT_READY
;
2845 Private
->InputEventSignalState
= FALSE
;
2847 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
2852 ConSplitterSimplePointerWaitForInput (
2858 Routine Description:
2859 This event agregates all the events of the ConIn devices in the spliter.
2860 If the ConIn is password locked then return.
2861 If any events of physical ConIn devices are signaled, signal the ConIn
2862 spliter event. This will cause the calling code to call
2863 ConSplitterTextInReadKeyStroke ().
2866 Event - The Event assoicated with callback.
2867 Context - Context registered when Event was created.
2875 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
2878 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
2879 if (Private
->PasswordEnabled
) {
2881 // If StdIn Locked return not ready
2887 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2889 if (Private
->InputEventSignalState
) {
2890 gBS
->SignalEvent (Event
);
2894 // if any physical console input device has key input, signal the event.
2896 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
2897 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
2898 if (!EFI_ERROR (Status
)) {
2899 gBS
->SignalEvent (Event
);
2900 Private
->InputEventSignalState
= TRUE
;
2907 ConSplitterTextOutReset (
2908 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2909 IN BOOLEAN ExtendedVerification
2913 Routine Description:
2914 Reset the text output device hardware and optionaly run diagnostics
2917 This - Protocol instance pointer.
2918 ExtendedVerification - Driver may perform more exhaustive verfication
2919 operation of the device during reset.
2922 EFI_SUCCESS - The text output device was reset.
2923 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
2929 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2931 EFI_STATUS ReturnStatus
;
2933 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
2936 // return the worst status met
2938 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
2940 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
2942 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
2943 Private
->TextOutList
[Index
].TextOut
,
2944 ExtendedVerification
2946 if (EFI_ERROR (Status
)) {
2947 ReturnStatus
= Status
;
2952 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
2954 Status
= DevNullTextOutSetMode (Private
, 0);
2955 if (EFI_ERROR (Status
)) {
2956 ReturnStatus
= Status
;
2959 return ReturnStatus
;
2964 ConSplitterTextOutOutputString (
2965 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
2970 Routine Description:
2971 Write a Unicode string to the output device.
2974 This - Protocol instance pointer.
2975 String - The NULL-terminated Unicode string to be displayed on the output
2976 device(s). All output devices must also support the Unicode
2977 drawing defined in this file.
2980 EFI_SUCCESS - The string was output to the device.
2981 EFI_DEVICE_ERROR - The device reported an error while attempting to output
2983 EFI_UNSUPPORTED - The output device's mode is not currently in a
2985 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
2986 characters in the Unicode string could not be
2987 rendered and were skipped.
2992 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
2994 UINTN BackSpaceCount
;
2995 EFI_STATUS ReturnStatus
;
2996 CHAR16
*TargetString
;
2998 This
->SetAttribute (This
, This
->Mode
->Attribute
);
3000 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3003 for (TargetString
= WString
; *TargetString
; TargetString
++) {
3004 if (*TargetString
== CHAR_BACKSPACE
) {
3010 if (BackSpaceCount
== 0) {
3011 TargetString
= WString
;
3013 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
3014 StrCpy (TargetString
, WString
);
3017 // return the worst status met
3019 Status
= DevNullTextOutOutputString (Private
, TargetString
);
3020 if (EFI_ERROR (Status
)) {
3021 ReturnStatus
= Status
;
3024 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3026 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3027 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
3028 Private
->TextOutList
[Index
].TextOut
,
3031 if (EFI_ERROR (Status
)) {
3032 ReturnStatus
= Status
;
3037 if (BackSpaceCount
) {
3038 FreePool (TargetString
);
3041 return ReturnStatus
;
3046 ConSplitterTextOutTestString (
3047 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3052 Routine Description:
3053 Verifies that all characters in a Unicode string can be output to the
3057 This - Protocol instance pointer.
3058 String - The NULL-terminated Unicode string to be examined for the output
3062 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3063 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3064 rendered by one or more of the output devices mapped
3070 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3072 EFI_STATUS ReturnStatus
;
3074 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3077 // return the worst status met
3079 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3080 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3081 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
3082 Private
->TextOutList
[Index
].TextOut
,
3085 if (EFI_ERROR (Status
)) {
3086 ReturnStatus
= Status
;
3091 // There is no DevNullTextOutTestString () since a Unicode buffer would
3092 // always return EFI_SUCCESS.
3093 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3095 return ReturnStatus
;
3100 ConSplitterTextOutQueryMode (
3101 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3102 IN UINTN ModeNumber
,
3108 Routine Description:
3109 Returns information for an available text mode that the output device(s)
3113 This - Protocol instance pointer.
3114 ModeNumber - The mode number to return information on.
3115 Columns, Rows - Returns the geometry of the text output device for the
3116 requested ModeNumber.
3119 EFI_SUCCESS - The requested mode information was returned.
3120 EFI_DEVICE_ERROR - The device had an error and could not
3121 complete the request.
3122 EFI_UNSUPPORTED - The mode number was not valid.
3126 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3128 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3131 // Check whether param ModeNumber is valid.
3132 // ModeNumber should be within range 0 ~ MaxMode - 1.
3134 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3135 return EFI_UNSUPPORTED
;
3138 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3139 return EFI_UNSUPPORTED
;
3142 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
3143 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
3145 if (*Columns
<= 0 && *Rows
<= 0) {
3146 return EFI_UNSUPPORTED
;
3155 ConSplitterTextOutSetMode (
3156 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3161 Routine Description:
3162 Sets the output device(s) to a specified mode.
3165 This - Protocol instance pointer.
3166 ModeNumber - The mode number to set.
3169 EFI_SUCCESS - The requested text mode was set.
3170 EFI_DEVICE_ERROR - The device had an error and
3171 could not complete the request.
3172 EFI_UNSUPPORTED - The mode number was not valid.
3177 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3179 INT32
*TextOutModeMap
;
3180 EFI_STATUS ReturnStatus
;
3182 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3185 // Check whether param ModeNumber is valid.
3186 // ModeNumber should be within range 0 ~ MaxMode - 1.
3188 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3189 return EFI_UNSUPPORTED
;
3192 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
3193 return EFI_UNSUPPORTED
;
3196 // If the mode is being set to the curent mode, then just clear the screen and return.
3198 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
3199 return ConSplitterTextOutClearScreen (This
);
3202 // return the worst status met
3204 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
3205 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3207 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3208 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
3209 Private
->TextOutList
[Index
].TextOut
,
3210 TextOutModeMap
[Index
]
3213 // If this console device is based on a UGA device, then sync up the bitmap from
3214 // the UGA splitter and reclear the text portion of the display in the new mode.
3216 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
3217 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3220 if (EFI_ERROR (Status
)) {
3221 ReturnStatus
= Status
;
3226 // The DevNull Console will support any possible mode as it allocates memory
3228 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
3229 if (EFI_ERROR (Status
)) {
3230 ReturnStatus
= Status
;
3233 return ReturnStatus
;
3238 ConSplitterTextOutSetAttribute (
3239 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3244 Routine Description:
3245 Sets the background and foreground colors for the OutputString () and
3246 ClearScreen () functions.
3249 This - Protocol instance pointer.
3250 Attribute - The attribute to set. Bits 0..3 are the foreground color, and
3251 bits 4..6 are the background color. All other bits are undefined
3252 and must be zero. The valid Attributes are defined in this file.
3255 EFI_SUCCESS - The attribute was set.
3256 EFI_DEVICE_ERROR - The device had an error and
3257 could not complete the request.
3258 EFI_UNSUPPORTED - The attribute requested is not defined.
3263 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3265 EFI_STATUS ReturnStatus
;
3267 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3270 // Check whether param Attribute is valid.
3272 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
3273 return EFI_UNSUPPORTED
;
3277 // return the worst status met
3279 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3281 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3282 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
3283 Private
->TextOutList
[Index
].TextOut
,
3286 if (EFI_ERROR (Status
)) {
3287 ReturnStatus
= Status
;
3292 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
3294 return ReturnStatus
;
3299 ConSplitterTextOutClearScreen (
3300 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
3304 Routine Description:
3305 Clears the output device(s) display to the currently selected background
3309 This - Protocol instance pointer.
3312 EFI_SUCCESS - The operation completed successfully.
3313 EFI_DEVICE_ERROR - The device had an error and
3314 could not complete the request.
3315 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3320 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3322 EFI_STATUS ReturnStatus
;
3324 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3327 // return the worst status met
3329 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3331 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3332 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
3333 if (EFI_ERROR (Status
)) {
3334 ReturnStatus
= Status
;
3339 Status
= DevNullTextOutClearScreen (Private
);
3340 if (EFI_ERROR (Status
)) {
3341 ReturnStatus
= Status
;
3344 return ReturnStatus
;
3349 ConSplitterTextOutSetCursorPosition (
3350 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3356 Routine Description:
3357 Sets the current coordinates of the cursor position
3360 This - Protocol instance pointer.
3361 Column, Row - the position to set the cursor to. Must be greater than or
3362 equal to zero and less than the number of columns and rows
3366 EFI_SUCCESS - The operation completed successfully.
3367 EFI_DEVICE_ERROR - The device had an error and
3368 could not complete the request.
3369 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
3370 cursor position is invalid for the current mode.
3375 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3377 EFI_STATUS ReturnStatus
;
3381 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3383 MaxColumn
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Columns
;
3384 MaxRow
= Private
->TextOutQueryData
[Private
->TextOutMode
.Mode
].Rows
;
3386 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
3387 return EFI_UNSUPPORTED
;
3390 // return the worst status met
3392 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3394 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3395 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
3396 Private
->TextOutList
[Index
].TextOut
,
3400 if (EFI_ERROR (Status
)) {
3401 ReturnStatus
= Status
;
3406 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
3408 return ReturnStatus
;
3413 ConSplitterTextOutEnableCursor (
3414 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
3419 Routine Description:
3420 Makes the cursor visible or invisible
3423 This - Protocol instance pointer.
3424 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is
3425 set to be invisible.
3428 EFI_SUCCESS - The operation completed successfully.
3429 EFI_DEVICE_ERROR - The device had an error and could not complete the
3430 request, or the device does not support changing
3432 EFI_UNSUPPORTED - The output device is not in a valid text mode.
3437 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
3439 EFI_STATUS ReturnStatus
;
3441 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3444 // return the worst status met
3446 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3448 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
3449 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
3450 Private
->TextOutList
[Index
].TextOut
,
3453 if (EFI_ERROR (Status
)) {
3454 ReturnStatus
= Status
;
3459 DevNullTextOutEnableCursor (Private
, Visible
);
3461 return ReturnStatus
;