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 - 2008 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 #include "ConSplitter.h"
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn
= {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE
,
39 ConSplitterTextInReset
,
40 ConSplitterTextInReadKeyStroke
,
44 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
**) NULL
,
47 ConSplitterTextInResetEx
,
48 ConSplitterTextInReadKeyStrokeEx
,
50 ConSplitterTextInSetState
,
51 ConSplitterTextInRegisterKeyNotify
,
52 ConSplitterTextInUnregisterKeyNotify
55 (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
**) NULL
,
63 ConSplitterSimplePointerReset
,
64 ConSplitterSimplePointerGetState
,
66 (EFI_SIMPLE_POINTER_MODE
*) NULL
76 (EFI_SIMPLE_POINTER_PROTOCOL
**) NULL
,
80 ConSplitterAbsolutePointerReset
,
81 ConSplitterAbsolutePointerGetState
,
83 (EFI_ABSOLUTE_POINTER_MODE
*) NULL
90 0x10000, //AbsoluteMaxX
91 0x10000, //AbsoluteMaxY
92 0x10000, //AbsoluteMaxZ
96 (EFI_ABSOLUTE_POINTER_PROTOCOL
**) NULL
,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
120 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL gUgaDrawProtocolTemplate
= {
121 ConSpliterUgaDrawGetMode
,
122 ConSpliterUgaDrawSetMode
,
126 GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL gGraphicsOutputProtocolTemplate
= {
127 ConSpliterGraphicsOutputQueryMode
,
128 ConSpliterGraphicsOutputSetMode
,
129 ConSpliterGraphicsOutputBlt
,
133 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut
= {
134 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
137 ConSplitterTextOutReset
,
138 ConSplitterTextOutOutputString
,
139 ConSplitterTextOutTestString
,
140 ConSplitterTextOutQueryMode
,
141 ConSplitterTextOutSetMode
,
142 ConSplitterTextOutSetAttribute
,
143 ConSplitterTextOutClearScreen
,
144 ConSplitterTextOutSetCursorPosition
,
145 ConSplitterTextOutEnableCursor
,
146 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
165 (EFI_UGA_PIXEL
*) NULL
,
172 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
173 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
178 ConSpliterConsoleControlGetMode
,
179 ConSpliterConsoleControlSetMode
,
180 ConSpliterConsoleControlLockStdIn
184 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
186 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
190 EfiConsoleControlScreenText
,
197 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr
= {
198 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE
,
201 ConSplitterTextOutReset
,
202 ConSplitterTextOutOutputString
,
203 ConSplitterTextOutTestString
,
204 ConSplitterTextOutQueryMode
,
205 ConSplitterTextOutSetMode
,
206 ConSplitterTextOutSetAttribute
,
207 ConSplitterTextOutClearScreen
,
208 ConSplitterTextOutSetCursorPosition
,
209 ConSplitterTextOutEnableCursor
,
210 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
229 (EFI_UGA_PIXEL
*) NULL
,
236 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
237 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) NULL
,
242 ConSpliterConsoleControlGetMode
,
243 ConSpliterConsoleControlSetMode
,
244 ConSpliterConsoleControlLockStdIn
248 (TEXT_OUT_AND_GOP_DATA
*) NULL
,
250 (TEXT_OUT_SPLITTER_QUERY_DATA
*) NULL
,
254 EfiConsoleControlScreenText
,
261 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding
= {
262 ConSplitterConInDriverBindingSupported
,
263 ConSplitterConInDriverBindingStart
,
264 ConSplitterConInDriverBindingStop
,
270 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding
= {
271 ConSplitterSimplePointerDriverBindingSupported
,
272 ConSplitterSimplePointerDriverBindingStart
,
273 ConSplitterSimplePointerDriverBindingStop
,
280 // Driver binding instance for Absolute Pointer protocol
282 EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding
= {
283 ConSplitterAbsolutePointerDriverBindingSupported
,
284 ConSplitterAbsolutePointerDriverBindingStart
,
285 ConSplitterAbsolutePointerDriverBindingStop
,
291 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding
= {
292 ConSplitterConOutDriverBindingSupported
,
293 ConSplitterConOutDriverBindingStart
,
294 ConSplitterConOutDriverBindingStop
,
300 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding
= {
301 ConSplitterStdErrDriverBindingSupported
,
302 ConSplitterStdErrDriverBindingStart
,
303 ConSplitterStdErrDriverBindingStop
,
310 The user Entry Point for module ConSplitter. The user code starts with this function.
312 @param[in] ImageHandle The firmware allocated handle for the EFI image.
313 @param[in] SystemTable A pointer to the EFI System Table.
315 @retval EFI_SUCCESS The entry point is executed successfully.
316 @retval other Some error occurs when executing this entry point.
321 InitializeConSplitter(
322 IN EFI_HANDLE ImageHandle
,
323 IN EFI_SYSTEM_TABLE
*SystemTable
329 // Install driver model protocol(s).
331 Status
= EfiLibInstallDriverBindingComponentName2 (
334 &gConSplitterConInDriverBinding
,
336 &gConSplitterConInComponentName
,
337 &gConSplitterConInComponentName2
339 ASSERT_EFI_ERROR (Status
);
341 Status
= EfiLibInstallDriverBindingComponentName2 (
344 &gConSplitterSimplePointerDriverBinding
,
346 &gConSplitterSimplePointerComponentName
,
347 &gConSplitterSimplePointerComponentName2
349 ASSERT_EFI_ERROR (Status
);
351 Status
= EfiLibInstallDriverBindingComponentName2 (
354 &gConSplitterAbsolutePointerDriverBinding
,
356 &gConSplitterAbsolutePointerComponentName
,
357 &gConSplitterAbsolutePointerComponentName2
359 ASSERT_EFI_ERROR (Status
);
361 Status
= EfiLibInstallDriverBindingComponentName2 (
364 &gConSplitterConOutDriverBinding
,
366 &gConSplitterConOutComponentName
,
367 &gConSplitterConOutComponentName2
369 ASSERT_EFI_ERROR (Status
);
371 Status
= EfiLibInstallDriverBindingComponentName2 (
374 &gConSplitterStdErrDriverBinding
,
376 &gConSplitterStdErrComponentName
,
377 &gConSplitterStdErrComponentName2
379 ASSERT_EFI_ERROR (Status
);
383 // Call the original Entry Point
385 Status
= ConSplitterDriverEntry (ImageHandle
, SystemTable
);
393 Intialize a virtual console device to act as an agrigator of physical console
396 @param ImageHandle (Standard EFI Image entry -
397 EFI_IMAGE_ENTRY_POINT)
398 @param SystemTable (Standard EFI Image entry -
399 EFI_IMAGE_ENTRY_POINT)
405 ConSplitterDriverEntry (
406 IN EFI_HANDLE ImageHandle
,
407 IN EFI_SYSTEM_TABLE
*SystemTable
412 ASSERT (FeaturePcdGet (PcdConOutGopSupport
) ||
413 FeaturePcdGet (PcdConOutUgaSupport
));
415 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
416 // The virtual handles will always exist even if no console exist in the
417 // system. This is need to support hotplug devices like USB.
420 // Create virtual device handle for StdErr Splitter
422 Status
= ConSplitterTextOutConstructor (&mStdErr
);
423 if (!EFI_ERROR (Status
)) {
424 Status
= gBS
->InstallMultipleProtocolInterfaces (
425 &mStdErr
.VirtualHandle
,
426 &gEfiSimpleTextOutProtocolGuid
,
428 &gEfiPrimaryStandardErrorDeviceGuid
,
434 // Create virtual device handle for ConIn Splitter
436 Status
= ConSplitterTextInConstructor (&mConIn
);
437 if (!EFI_ERROR (Status
)) {
438 Status
= gBS
->InstallMultipleProtocolInterfaces (
439 &mConIn
.VirtualHandle
,
440 &gEfiSimpleTextInProtocolGuid
,
442 &gEfiSimpleTextInputExProtocolGuid
,
444 &gEfiSimplePointerProtocolGuid
,
445 &mConIn
.SimplePointer
,
446 &gEfiAbsolutePointerProtocolGuid
,
447 &mConIn
.AbsolutePointer
,
448 &gEfiPrimaryConsoleInDeviceGuid
,
452 if (!EFI_ERROR (Status
)) {
454 // Update the EFI System Table with new virtual console
456 gST
->ConsoleInHandle
= mConIn
.VirtualHandle
;
457 gST
->ConIn
= &mConIn
.TextIn
;
461 // Create virtual device handle for ConOut Splitter
463 Status
= ConSplitterTextOutConstructor (&mConOut
);
464 if (!EFI_ERROR (Status
)) {
465 if (!FeaturePcdGet (PcdConOutGopSupport
)) {
467 // In EFI mode, UGA Draw protocol is installed
469 Status
= gBS
->InstallMultipleProtocolInterfaces (
470 &mConOut
.VirtualHandle
,
471 &gEfiSimpleTextOutProtocolGuid
,
473 &gEfiUgaDrawProtocolGuid
,
475 &gEfiConsoleControlProtocolGuid
,
476 &mConOut
.ConsoleControl
,
477 &gEfiPrimaryConsoleOutDeviceGuid
,
481 } else if (!FeaturePcdGet (PcdConOutUgaSupport
)) {
483 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
485 Status
= gBS
->InstallMultipleProtocolInterfaces (
486 &mConOut
.VirtualHandle
,
487 &gEfiSimpleTextOutProtocolGuid
,
489 &gEfiGraphicsOutputProtocolGuid
,
490 &mConOut
.GraphicsOutput
,
491 &gEfiConsoleControlProtocolGuid
,
492 &mConOut
.ConsoleControl
,
493 &gEfiPrimaryConsoleOutDeviceGuid
,
499 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
500 // installed on virtual handle.
502 Status
= gBS
->InstallMultipleProtocolInterfaces (
503 &mConOut
.VirtualHandle
,
504 &gEfiSimpleTextOutProtocolGuid
,
506 &gEfiGraphicsOutputProtocolGuid
,
507 &mConOut
.GraphicsOutput
,
508 &gEfiUgaDrawProtocolGuid
,
510 &gEfiConsoleControlProtocolGuid
,
511 &mConOut
.ConsoleControl
,
512 &gEfiPrimaryConsoleOutDeviceGuid
,
518 if (!EFI_ERROR (Status
)) {
520 // Update the EFI System Table with new virtual console
522 gST
->ConsoleOutHandle
= mConOut
.VirtualHandle
;
523 gST
->ConOut
= &mConOut
.TextOut
;
528 // Update the CRC32 in the EFI System Table header
531 gBS
->CalculateCrc32 (
542 Construct the ConSplitter.
544 @param ConInPrivate A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA
547 @retval EFI_OUT_OF_RESOURCES Out of resources.
551 ConSplitterTextInConstructor (
552 TEXT_IN_SPLITTER_PRIVATE_DATA
*ConInPrivate
558 // Initilize console input splitter's private data.
560 Status
= ConSplitterGrowBuffer (
561 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
562 &ConInPrivate
->TextInListCount
,
563 (VOID
**) &ConInPrivate
->TextInList
565 if (EFI_ERROR (Status
)) {
566 return EFI_OUT_OF_RESOURCES
;
569 // Create Event to support locking StdIn Device
571 Status
= gBS
->CreateEvent (
572 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
574 ConSpliterConsoleControlLockStdInEvent
,
576 &ConInPrivate
->LockEvent
578 ASSERT_EFI_ERROR (Status
);
580 Status
= gBS
->CreateEvent (
583 ConSplitterTextInWaitForKey
,
585 &ConInPrivate
->TextIn
.WaitForKey
587 ASSERT_EFI_ERROR (Status
);
590 // Buffer for Simple Text Input Ex Protocol
592 Status
= ConSplitterGrowBuffer (
593 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
594 &ConInPrivate
->TextInExListCount
,
595 (VOID
**) &ConInPrivate
->TextInExList
597 if (EFI_ERROR (Status
)) {
598 return EFI_OUT_OF_RESOURCES
;
601 Status
= gBS
->CreateEvent (
604 ConSplitterTextInWaitForKey
,
606 &ConInPrivate
->TextInEx
.WaitForKeyEx
608 ASSERT_EFI_ERROR (Status
);
610 InitializeListHead (&ConInPrivate
->NotifyList
);
613 // Allocate Buffer and Create Event for Absolute Pointer and Simple Pointer Protocols
615 ConInPrivate
->AbsolutePointer
.Mode
= &ConInPrivate
->AbsolutePointerMode
;
617 Status
= ConSplitterGrowBuffer (
618 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
619 &ConInPrivate
->AbsolutePointerListCount
,
620 (VOID
**) &ConInPrivate
->AbsolutePointerList
622 if (EFI_ERROR (Status
)) {
623 return EFI_OUT_OF_RESOURCES
;
626 Status
= gBS
->CreateEvent (
629 ConSplitterAbsolutePointerWaitForInput
,
631 &ConInPrivate
->AbsolutePointer
.WaitForInput
633 ASSERT_EFI_ERROR (Status
);
635 ConInPrivate
->SimplePointer
.Mode
= &ConInPrivate
->SimplePointerMode
;
637 Status
= ConSplitterGrowBuffer (
638 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
639 &ConInPrivate
->PointerListCount
,
640 (VOID
**) &ConInPrivate
->PointerList
642 if (EFI_ERROR (Status
)) {
643 return EFI_OUT_OF_RESOURCES
;
646 Status
= gBS
->CreateEvent (
649 ConSplitterSimplePointerWaitForInput
,
651 &ConInPrivate
->SimplePointer
.WaitForInput
658 ConSplitterTextOutConstructor (
659 TEXT_OUT_SPLITTER_PRIVATE_DATA
*ConOutPrivate
663 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
666 // Copy protocols template
668 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
669 CopyMem (&ConOutPrivate
->UgaDraw
, &gUgaDrawProtocolTemplate
, sizeof (EFI_UGA_DRAW_PROTOCOL
));
672 if (FeaturePcdGet (PcdConOutGopSupport
)) {
673 CopyMem (&ConOutPrivate
->GraphicsOutput
, &gGraphicsOutputProtocolTemplate
, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL
));
677 // Initilize console output splitter's private data.
679 ConOutPrivate
->TextOut
.Mode
= &ConOutPrivate
->TextOutMode
;
682 // When new console device is added, the new mode will be set later,
683 // so put current mode back to init state.
685 ConOutPrivate
->TextOutMode
.Mode
= 0xFF;
687 Status
= ConSplitterGrowBuffer (
688 sizeof (TEXT_OUT_AND_GOP_DATA
),
689 &ConOutPrivate
->TextOutListCount
,
690 (VOID
**) &ConOutPrivate
->TextOutList
692 if (EFI_ERROR (Status
)) {
693 return EFI_OUT_OF_RESOURCES
;
696 Status
= ConSplitterGrowBuffer (
697 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
698 &ConOutPrivate
->TextOutQueryDataCount
,
699 (VOID
**) &ConOutPrivate
->TextOutQueryData
701 if (EFI_ERROR (Status
)) {
702 return EFI_OUT_OF_RESOURCES
;
705 // Setup the DevNullTextOut console to 80 x 25
707 ConOutPrivate
->TextOutQueryData
[0].Columns
= 80;
708 ConOutPrivate
->TextOutQueryData
[0].Rows
= 25;
709 DevNullTextOutSetMode (ConOutPrivate
, 0);
711 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
713 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
715 ConSpliterUgaDrawSetMode (&ConOutPrivate
->UgaDraw
, 800, 600, 32, 60);
717 if (FeaturePcdGet (PcdConOutGopSupport
)) {
719 // Setup resource for mode information in Graphics Output Protocol interface
721 if ((ConOutPrivate
->GraphicsOutput
.Mode
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
))) == NULL
) {
722 return EFI_OUT_OF_RESOURCES
;
724 if ((ConOutPrivate
->GraphicsOutput
.Mode
->Info
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
725 return EFI_OUT_OF_RESOURCES
;
728 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
729 // DevNull will be updated to user-defined mode after driver has started.
731 if ((ConOutPrivate
->GraphicsOutputModeBuffer
= AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
))) == NULL
) {
732 return EFI_OUT_OF_RESOURCES
;
734 Info
= &ConOutPrivate
->GraphicsOutputModeBuffer
[0];
736 Info
->HorizontalResolution
= 800;
737 Info
->VerticalResolution
= 600;
738 Info
->PixelFormat
= PixelBltOnly
;
739 Info
->PixelsPerScanLine
= 800;
740 CopyMem (ConOutPrivate
->GraphicsOutput
.Mode
->Info
, Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
741 ConOutPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
744 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
745 // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
747 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
748 ConOutPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
750 ConOutPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
752 // Initial current mode to unknow state, and then set to mode 0
754 ConOutPrivate
->GraphicsOutput
.Mode
->Mode
= 0xffff;
755 ConOutPrivate
->GraphicsOutput
.SetMode (&ConOutPrivate
->GraphicsOutput
, 0);
763 Generic Supported Check
765 @param This Pointer to protocol.
766 @param ControllerHandle Controller Handle.
769 @retval EFI_UNSUPPORTED unsupported.
770 @retval EFI_SUCCESS operation is OK.
774 ConSplitterSupported (
775 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
776 IN EFI_HANDLE ControllerHandle
,
784 // Make sure the Console Splitter does not attempt to attach to itself
786 if (ControllerHandle
== mConIn
.VirtualHandle
) {
787 return EFI_UNSUPPORTED
;
790 if (ControllerHandle
== mConOut
.VirtualHandle
) {
791 return EFI_UNSUPPORTED
;
794 if (ControllerHandle
== mStdErr
.VirtualHandle
) {
795 return EFI_UNSUPPORTED
;
798 // Check to see whether the handle has the ConsoleInDevice GUID on it
800 Status
= gBS
->OpenProtocol (
804 This
->DriverBindingHandle
,
806 EFI_OPEN_PROTOCOL_BY_DRIVER
809 if (EFI_ERROR (Status
)) {
816 This
->DriverBindingHandle
,
825 Console In Supported Check
827 @param This Pointer to protocol.
828 @param ControllerHandle Controller handle.
829 @param RemainingDevicePath Remaining device path.
836 ConSplitterConInDriverBindingSupported (
837 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
838 IN EFI_HANDLE ControllerHandle
,
839 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
842 return ConSplitterSupported (
845 &gEfiConsoleInDeviceGuid
851 Standard Error Supported Check
853 @param This Pointer to protocol.
854 @param ControllerHandle Controller handle.
855 @param RemainingDevicePath Remaining device path.
862 ConSplitterSimplePointerDriverBindingSupported (
863 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
864 IN EFI_HANDLE ControllerHandle
,
865 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
868 return ConSplitterSupported (
871 &gEfiSimplePointerProtocolGuid
877 Absolute Pointer Supported Check
879 @param This Pointer to protocol.
880 @param ControllerHandle Controller handle.
881 @param RemainingDevicePath Remaining device path.
888 ConSplitterAbsolutePointerDriverBindingSupported (
889 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
890 IN EFI_HANDLE ControllerHandle
,
891 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
894 return ConSplitterSupported (
897 &gEfiAbsolutePointerProtocolGuid
903 Console Out Supported Check
905 @param This Pointer to protocol.
906 @param ControllerHandle Controller handle.
907 @param RemainingDevicePath Remaining device path.
914 ConSplitterConOutDriverBindingSupported (
915 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
916 IN EFI_HANDLE ControllerHandle
,
917 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
920 return ConSplitterSupported (
923 &gEfiConsoleOutDeviceGuid
929 Standard Error Supported Check
931 @param This Pointer to protocol.
932 @param ControllerHandle Controller handle.
933 @param RemainingDevicePath Remaining device path.
940 ConSplitterStdErrDriverBindingSupported (
941 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
942 IN EFI_HANDLE ControllerHandle
,
943 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
946 return ConSplitterSupported (
949 &gEfiStandardErrorDeviceGuid
955 Start ConSplitter on ControllerHandle, and create the virtual
956 agrogated console device on first call Start for a SimpleTextIn handle.
958 (Standard DriverBinding Protocol Start() function)
960 @return EFI_ERROR if a SimpleTextIn protocol is not started.
966 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
967 IN EFI_HANDLE ControllerHandle
,
968 IN EFI_HANDLE ConSplitterVirtualHandle
,
969 IN EFI_GUID
*DeviceGuid
,
970 IN EFI_GUID
*InterfaceGuid
,
978 // Check to see whether the handle has the ConsoleInDevice GUID on it
980 Status
= gBS
->OpenProtocol (
984 This
->DriverBindingHandle
,
986 EFI_OPEN_PROTOCOL_BY_DRIVER
988 if (EFI_ERROR (Status
)) {
992 Status
= gBS
->OpenProtocol (
996 This
->DriverBindingHandle
,
997 ConSplitterVirtualHandle
,
998 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1000 if (EFI_ERROR (Status
)) {
1004 return gBS
->OpenProtocol (
1008 This
->DriverBindingHandle
,
1009 ConSplitterVirtualHandle
,
1010 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1016 Start ConSplitter on ControllerHandle, and create the virtual
1017 agrogated console device on first call Start for a SimpleTextIn handle.
1019 @param This Pointer to protocol.
1020 @param ControllerHandle Controller handle.
1021 @param RemainingDevicePath Remaining device path.
1024 @return EFI_ERROR if a SimpleTextIn protocol is not started.
1029 ConSplitterConInDriverBindingStart (
1030 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1031 IN EFI_HANDLE ControllerHandle
,
1032 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1036 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1037 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1040 // Start ConSplitter on ControllerHandle, and create the virtual
1041 // agrogated console device on first call Start for a SimpleTextIn handle.
1043 Status
= ConSplitterStart (
1046 mConIn
.VirtualHandle
,
1047 &gEfiConsoleInDeviceGuid
,
1048 &gEfiSimpleTextInProtocolGuid
,
1051 if (EFI_ERROR (Status
)) {
1055 Status
= ConSplitterTextInAddDevice (&mConIn
, TextIn
);
1056 if (EFI_ERROR (Status
)) {
1060 Status
= gBS
->OpenProtocol (
1062 &gEfiSimpleTextInputExProtocolGuid
,
1063 (VOID
**) &TextInEx
,
1064 This
->DriverBindingHandle
,
1065 mConIn
.VirtualHandle
,
1066 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1068 if (EFI_ERROR (Status
)) {
1072 Status
= ConSplitterTextInExAddDevice (&mConIn
, TextInEx
);
1079 Start ConSplitter on ControllerHandle, and create the virtual
1080 agrogated console device on first call Start for a SimpleTextIn handle.
1082 @param This Pointer to protocol.
1083 @param ControllerHandle Controller handle.
1084 @param RemainingDevicePath Remaining device path.
1086 @return EFI_ERROR if a SimpleTextIn protocol is not started.
1091 ConSplitterSimplePointerDriverBindingStart (
1092 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1093 IN EFI_HANDLE ControllerHandle
,
1094 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1098 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1100 Status
= ConSplitterStart (
1103 mConIn
.VirtualHandle
,
1104 &gEfiSimplePointerProtocolGuid
,
1105 &gEfiSimplePointerProtocolGuid
,
1106 (VOID
**) &SimplePointer
1108 if (EFI_ERROR (Status
)) {
1112 return ConSplitterSimplePointerAddDevice (&mConIn
, SimplePointer
);
1117 Start ConSplitter on ControllerHandle, and create the virtual
1118 agrogated console device on first call Start for a ConIn handle.
1120 @param This Pointer to protocol.
1121 @param ControllerHandle Controller handle.
1122 @param RemainingDevicePath Remaining device path.
1124 @return EFI_ERROR if a AbsolutePointer protocol is not started.
1129 ConSplitterAbsolutePointerDriverBindingStart (
1130 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1131 IN EFI_HANDLE ControllerHandle
,
1132 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1136 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1138 Status
= ConSplitterStart (
1141 mConIn
.VirtualHandle
,
1142 &gEfiAbsolutePointerProtocolGuid
,
1143 &gEfiAbsolutePointerProtocolGuid
,
1144 (VOID
**) &AbsolutePointer
1147 if (EFI_ERROR (Status
)) {
1151 return ConSplitterAbsolutePointerAddDevice (&mConIn
, AbsolutePointer
);
1156 Start ConSplitter on ControllerHandle, and create the virtual
1157 agrogated console device on first call Start for a SimpleTextIn handle.
1159 @param This Pointer to protocol.
1160 @param ControllerHandle Controller handle.
1161 @param RemainingDevicePath Remaining device path.
1163 @return EFI_ERROR if a SimpleTextIn protocol is not started.
1168 ConSplitterConOutDriverBindingStart (
1169 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1170 IN EFI_HANDLE ControllerHandle
,
1171 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1175 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1176 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1177 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1179 Status
= ConSplitterStart (
1182 mConOut
.VirtualHandle
,
1183 &gEfiConsoleOutDeviceGuid
,
1184 &gEfiSimpleTextOutProtocolGuid
,
1187 if (EFI_ERROR (Status
)) {
1191 GraphicsOutput
= NULL
;
1194 // Try to Open Graphics Output protocol
1196 Status
= gBS
->OpenProtocol (
1198 &gEfiGraphicsOutputProtocolGuid
,
1199 (VOID
**) &GraphicsOutput
,
1200 This
->DriverBindingHandle
,
1201 mConOut
.VirtualHandle
,
1202 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1205 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1207 // Open UGA_DRAW protocol
1209 Status
= gBS
->OpenProtocol (
1211 &gEfiUgaDrawProtocolGuid
,
1213 This
->DriverBindingHandle
,
1214 mConOut
.VirtualHandle
,
1215 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1220 // When new console device is added, the new mode will be set later,
1221 // so put current mode back to init state.
1223 mConOut
.TextOutMode
.Mode
= 0xFF;
1226 // If both ConOut and StdErr incorporate the same Text Out device,
1227 // their MaxMode and QueryData should be the intersection of both.
1229 Status
= ConSplitterTextOutAddDevice (&mConOut
, TextOut
, GraphicsOutput
, UgaDraw
);
1230 ConSplitterTextOutSetAttribute (&mConOut
.TextOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
1232 if (FeaturePcdGet (PcdConOutUgaSupport
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
1234 // Match the UGA mode data of ConOut with the current mode
1236 if (UgaDraw
!= NULL
) {
1239 &mConOut
.UgaHorizontalResolution
,
1240 &mConOut
.UgaVerticalResolution
,
1241 &mConOut
.UgaColorDepth
,
1242 &mConOut
.UgaRefreshRate
1251 Start ConSplitter on ControllerHandle, and create the virtual
1252 agrogated console device on first call Start for a SimpleTextIn handle.
1254 @param This Pointer to protocol.
1255 @param ControllerHandle Controller handle.
1256 @param RemainingDevicePath Remaining device path.
1258 @return EFI_ERROR if a SimpleTextIn protocol is not started.
1263 ConSplitterStdErrDriverBindingStart (
1264 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1265 IN EFI_HANDLE ControllerHandle
,
1266 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1270 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1272 Status
= ConSplitterStart (
1275 mStdErr
.VirtualHandle
,
1276 &gEfiStandardErrorDeviceGuid
,
1277 &gEfiSimpleTextOutProtocolGuid
,
1280 if (EFI_ERROR (Status
)) {
1285 // When new console device is added, the new mode will be set later,
1286 // so put current mode back to init state.
1288 mStdErr
.TextOutMode
.Mode
= 0xFF;
1291 // If both ConOut and StdErr incorporate the same Text Out device,
1292 // their MaxMode and QueryData should be the intersection of both.
1294 Status
= ConSplitterTextOutAddDevice (&mStdErr
, TextOut
, NULL
, NULL
);
1295 ConSplitterTextOutSetAttribute (&mStdErr
.TextOut
, EFI_TEXT_ATTR (EFI_MAGENTA
, EFI_BLACK
));
1296 if (EFI_ERROR (Status
)) {
1300 if (mStdErr
.CurrentNumberOfConsoles
== 1) {
1301 gST
->StandardErrorHandle
= mStdErr
.VirtualHandle
;
1302 gST
->StdErr
= &mStdErr
.TextOut
;
1304 // Update the CRC32 in the EFI System Table header
1307 gBS
->CalculateCrc32 (
1308 (UINT8
*) &gST
->Hdr
,
1309 gST
->Hdr
.HeaderSize
,
1320 (Standard DriverBinding Protocol Stop() function)
1328 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1329 IN EFI_HANDLE ControllerHandle
,
1330 IN EFI_HANDLE ConSplitterVirtualHandle
,
1331 IN EFI_GUID
*DeviceGuid
,
1332 IN EFI_GUID
*InterfaceGuid
,
1338 Status
= gBS
->OpenProtocol (
1342 This
->DriverBindingHandle
,
1344 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1346 if (EFI_ERROR (Status
)) {
1350 // close the protocol refered.
1352 gBS
->CloseProtocol (
1355 This
->DriverBindingHandle
,
1356 ConSplitterVirtualHandle
1358 gBS
->CloseProtocol (
1361 This
->DriverBindingHandle
,
1371 (Standard DriverBinding Protocol Stop() function)
1378 ConSplitterConInDriverBindingStop (
1379 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1380 IN EFI_HANDLE ControllerHandle
,
1381 IN UINTN NumberOfChildren
,
1382 IN EFI_HANDLE
*ChildHandleBuffer
1386 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
1388 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
;
1389 if (NumberOfChildren
== 0) {
1393 Status
= gBS
->OpenProtocol (
1395 &gEfiSimpleTextInputExProtocolGuid
,
1396 (VOID
**) &TextInEx
,
1397 This
->DriverBindingHandle
,
1399 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1401 if (EFI_ERROR (Status
)) {
1405 Status
= ConSplitterTextInExDeleteDevice (&mConIn
, TextInEx
);
1406 if (EFI_ERROR (Status
)) {
1411 Status
= ConSplitterStop (
1414 mConIn
.VirtualHandle
,
1415 &gEfiConsoleInDeviceGuid
,
1416 &gEfiSimpleTextInProtocolGuid
,
1419 if (EFI_ERROR (Status
)) {
1423 // Delete this console input device's data structures.
1425 return ConSplitterTextInDeleteDevice (&mConIn
, TextIn
);
1431 (Standard DriverBinding Protocol Stop() function)
1438 ConSplitterSimplePointerDriverBindingStop (
1439 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1440 IN EFI_HANDLE ControllerHandle
,
1441 IN UINTN NumberOfChildren
,
1442 IN EFI_HANDLE
*ChildHandleBuffer
1446 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
;
1448 if (NumberOfChildren
== 0) {
1452 Status
= ConSplitterStop (
1455 mConIn
.VirtualHandle
,
1456 &gEfiSimplePointerProtocolGuid
,
1457 &gEfiSimplePointerProtocolGuid
,
1458 (VOID
**) &SimplePointer
1460 if (EFI_ERROR (Status
)) {
1464 // Delete this console input device's data structures.
1466 return ConSplitterSimplePointerDeleteDevice (&mConIn
, SimplePointer
);
1472 (Standard DriverBinding Protocol Stop() function)
1479 ConSplitterAbsolutePointerDriverBindingStop (
1480 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1481 IN EFI_HANDLE ControllerHandle
,
1482 IN UINTN NumberOfChildren
,
1483 IN EFI_HANDLE
*ChildHandleBuffer
1487 EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
;
1489 if (NumberOfChildren
== 0) {
1493 Status
= ConSplitterStop (
1496 mConIn
.VirtualHandle
,
1497 &gEfiAbsolutePointerProtocolGuid
,
1498 &gEfiAbsolutePointerProtocolGuid
,
1499 (VOID
**) &AbsolutePointer
1501 if (EFI_ERROR (Status
)) {
1505 // Delete this console input device's data structures.
1507 return ConSplitterAbsolutePointerDeleteDevice (&mConIn
, AbsolutePointer
);
1513 (Standard DriverBinding Protocol Stop() function)
1520 ConSplitterConOutDriverBindingStop (
1521 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1522 IN EFI_HANDLE ControllerHandle
,
1523 IN UINTN NumberOfChildren
,
1524 IN EFI_HANDLE
*ChildHandleBuffer
1528 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1530 if (NumberOfChildren
== 0) {
1534 Status
= ConSplitterStop (
1537 mConOut
.VirtualHandle
,
1538 &gEfiConsoleOutDeviceGuid
,
1539 &gEfiSimpleTextOutProtocolGuid
,
1542 if (EFI_ERROR (Status
)) {
1547 // Delete this console output device's data structures.
1549 return ConSplitterTextOutDeleteDevice (&mConOut
, TextOut
);
1555 (Standard DriverBinding Protocol Stop() function)
1557 @retval EFI_SUCCESS Complete successfully.
1562 ConSplitterStdErrDriverBindingStop (
1563 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1564 IN EFI_HANDLE ControllerHandle
,
1565 IN UINTN NumberOfChildren
,
1566 IN EFI_HANDLE
*ChildHandleBuffer
1570 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
1572 if (NumberOfChildren
== 0) {
1576 Status
= ConSplitterStop (
1579 mStdErr
.VirtualHandle
,
1580 &gEfiStandardErrorDeviceGuid
,
1581 &gEfiSimpleTextOutProtocolGuid
,
1584 if (EFI_ERROR (Status
)) {
1588 // Delete this console error out device's data structures.
1590 Status
= ConSplitterTextOutDeleteDevice (&mStdErr
, TextOut
);
1591 if (EFI_ERROR (Status
)) {
1595 if (mStdErr
.CurrentNumberOfConsoles
== 0) {
1596 gST
->StandardErrorHandle
= NULL
;
1599 // Update the CRC32 in the EFI System Table header
1602 gBS
->CalculateCrc32 (
1603 (UINT8
*) &gST
->Hdr
,
1604 gST
->Hdr
.HeaderSize
,
1614 Take the passed in Buffer of size SizeOfCount and grow the buffer
1615 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1616 bytes. Copy the current data in Buffer to the new version of Buffer
1617 and free the old version of buffer.
1619 @param SizeOfCount Size of element in array
1620 @param Count Current number of elements in array
1621 @param Buffer Bigger version of passed in Buffer with all the
1624 @retval EFI_SUCCESS Buffer size has grown
1625 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size
1630 ConSplitterGrowBuffer (
1631 IN UINTN SizeOfCount
,
1633 IN OUT VOID
**Buffer
1641 // grow the buffer to new buffer size,
1642 // copy the old buffer's content to the new-size buffer,
1643 // then free the old buffer.
1645 OldSize
= *Count
* SizeOfCount
;
1646 *Count
+= CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT
;
1647 NewSize
= *Count
* SizeOfCount
;
1649 Ptr
= AllocateZeroPool (NewSize
);
1651 return EFI_OUT_OF_RESOURCES
;
1654 CopyMem (Ptr
, *Buffer
, OldSize
);
1656 if (*Buffer
!= NULL
) {
1670 @return EFI_OUT_OF_RESOURCES
1674 ConSplitterTextInAddDevice (
1675 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1676 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1682 // If the Text In List is full, enlarge it by calling growbuffer().
1684 if (Private
->CurrentNumberOfConsoles
>= Private
->TextInListCount
) {
1685 Status
= ConSplitterGrowBuffer (
1686 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*),
1687 &Private
->TextInListCount
,
1688 (VOID
**) &Private
->TextInList
1690 if (EFI_ERROR (Status
)) {
1691 return EFI_OUT_OF_RESOURCES
;
1695 // Add the new text-in device data structure into the Text In List.
1697 Private
->TextInList
[Private
->CurrentNumberOfConsoles
] = TextIn
;
1698 Private
->CurrentNumberOfConsoles
++;
1701 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1703 gBS
->CheckEvent (TextIn
->WaitForKey
);
1713 @return EFI_NOT_FOUND
1717 ConSplitterTextInDeleteDevice (
1718 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1719 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
1724 // Remove the specified text-in device data structure from the Text In List,
1725 // and rearrange the remaining data structures in the Text In List.
1727 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1728 if (Private
->TextInList
[Index
] == TextIn
) {
1729 for (Index
= Index
; Index
< Private
->CurrentNumberOfConsoles
- 1; Index
++) {
1730 Private
->TextInList
[Index
] = Private
->TextInList
[Index
+ 1];
1733 Private
->CurrentNumberOfConsoles
--;
1738 return EFI_NOT_FOUND
;
1742 ConSplitterTextInExAddDevice (
1743 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1744 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1750 // If the TextInEx List is full, enlarge it by calling growbuffer().
1752 if (Private
->CurrentNumberOfExConsoles
>= Private
->TextInExListCount
) {
1753 Status
= ConSplitterGrowBuffer (
1754 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*),
1755 &Private
->TextInExListCount
,
1756 (VOID
**) &Private
->TextInExList
1758 if (EFI_ERROR (Status
)) {
1759 return EFI_OUT_OF_RESOURCES
;
1763 // Add the new text-in device data structure into the Text In List.
1765 Private
->TextInExList
[Private
->CurrentNumberOfExConsoles
] = TextInEx
;
1766 Private
->CurrentNumberOfExConsoles
++;
1769 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1771 gBS
->CheckEvent (TextInEx
->WaitForKeyEx
);
1777 ConSplitterTextInExDeleteDevice (
1778 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1779 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInEx
1784 // Remove the specified text-in device data structure from the Text In List,
1785 // and rearrange the remaining data structures in the Text In List.
1787 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
1788 if (Private
->TextInExList
[Index
] == TextInEx
) {
1789 for (Index
= Index
; Index
< Private
->CurrentNumberOfExConsoles
- 1; Index
++) {
1790 Private
->TextInExList
[Index
] = Private
->TextInExList
[Index
+ 1];
1793 Private
->CurrentNumberOfExConsoles
--;
1798 return EFI_NOT_FOUND
;
1805 @return EFI_OUT_OF_RESOURCES
1810 ConSplitterSimplePointerAddDevice (
1811 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1812 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1818 // If the Text In List is full, enlarge it by calling growbuffer().
1820 if (Private
->CurrentNumberOfPointers
>= Private
->PointerListCount
) {
1821 Status
= ConSplitterGrowBuffer (
1822 sizeof (EFI_SIMPLE_POINTER_PROTOCOL
*),
1823 &Private
->PointerListCount
,
1824 (VOID
**) &Private
->PointerList
1826 if (EFI_ERROR (Status
)) {
1827 return EFI_OUT_OF_RESOURCES
;
1831 // Add the new text-in device data structure into the Text In List.
1833 Private
->PointerList
[Private
->CurrentNumberOfPointers
] = SimplePointer
;
1834 Private
->CurrentNumberOfPointers
++;
1846 ConSplitterSimplePointerDeleteDevice (
1847 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1848 IN EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointer
1853 // Remove the specified text-in device data structure from the Text In List,
1854 // and rearrange the remaining data structures in the Text In List.
1856 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
1857 if (Private
->PointerList
[Index
] == SimplePointer
) {
1858 for (Index
= Index
; Index
< Private
->CurrentNumberOfPointers
- 1; Index
++) {
1859 Private
->PointerList
[Index
] = Private
->PointerList
[Index
+ 1];
1862 Private
->CurrentNumberOfPointers
--;
1867 return EFI_NOT_FOUND
;
1874 @return EFI_OUT_OF_RESOURCES
1879 ConSplitterAbsolutePointerAddDevice (
1880 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1881 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
1887 // If the Absolute Pointer List is full, enlarge it by calling growbuffer().
1889 if (Private
->CurrentNumberOfAbsolutePointers
>= Private
->AbsolutePointerListCount
) {
1890 Status
= ConSplitterGrowBuffer (
1891 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL
*),
1892 &Private
->AbsolutePointerListCount
,
1893 (VOID
**) &Private
->AbsolutePointerList
1895 if (EFI_ERROR (Status
)) {
1896 return EFI_OUT_OF_RESOURCES
;
1900 // Add the new text-in device data structure into the Text In List.
1902 Private
->AbsolutePointerList
[Private
->CurrentNumberOfAbsolutePointers
] = AbsolutePointer
;
1903 Private
->CurrentNumberOfAbsolutePointers
++;
1915 ConSplitterAbsolutePointerDeleteDevice (
1916 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
1917 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*AbsolutePointer
1922 // Remove the specified text-in device data structure from the Text In List,
1923 // and rearrange the remaining data structures in the Text In List.
1925 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
1926 if (Private
->AbsolutePointerList
[Index
] == AbsolutePointer
) {
1927 for (Index
= Index
; Index
< Private
->CurrentNumberOfAbsolutePointers
- 1; Index
++) {
1928 Private
->AbsolutePointerList
[Index
] = Private
->AbsolutePointerList
[Index
+ 1];
1931 Private
->CurrentNumberOfAbsolutePointers
--;
1936 return EFI_NOT_FOUND
;
1947 ConSplitterGrowMapTable (
1948 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1954 INT32
*TextOutModeMap
;
1955 INT32
*OldTextOutModeMap
;
1959 NewSize
= Private
->TextOutListCount
* sizeof (INT32
);
1960 OldTextOutModeMap
= Private
->TextOutModeMap
;
1961 TotalSize
= NewSize
* Private
->TextOutQueryDataCount
;
1963 TextOutModeMap
= AllocateZeroPool (TotalSize
);
1964 if (TextOutModeMap
== NULL
) {
1965 return EFI_OUT_OF_RESOURCES
;
1968 SetMem (TextOutModeMap
, TotalSize
, 0xFF);
1969 Private
->TextOutModeMap
= TextOutModeMap
;
1972 // If TextOutList has been enlarged, need to realloc the mode map table
1973 // The mode map table is regarded as a two dimension array.
1976 // 0 ---------> TextOutListCount ----> TextOutListCount
1977 // | -------------------------------------------
1984 // -------------------------------------------
1987 if (OldTextOutModeMap
!= NULL
) {
1989 Size
= Private
->CurrentNumberOfConsoles
* sizeof (INT32
);
1991 SrcAddress
= OldTextOutModeMap
;
1994 // Copy the old data to the new one
1996 while (Index
< Private
->TextOutMode
.MaxMode
) {
1997 CopyMem (TextOutModeMap
, SrcAddress
, Size
);
1998 TextOutModeMap
+= NewSize
;
2003 // Free the old buffer
2005 FreePool (OldTextOutModeMap
);
2019 ConSplitterAddOutputMode (
2020 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2021 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2029 MaxMode
= TextOut
->Mode
->MaxMode
;
2030 Private
->TextOutMode
.MaxMode
= MaxMode
;
2033 // Grow the buffer if query data buffer is not large enough to
2034 // hold all the mode supported by the first console.
2036 while (MaxMode
> (INT32
) Private
->TextOutQueryDataCount
) {
2037 Status
= ConSplitterGrowBuffer (
2038 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
),
2039 &Private
->TextOutQueryDataCount
,
2040 (VOID
**) &Private
->TextOutQueryData
2042 if (EFI_ERROR (Status
)) {
2043 return EFI_OUT_OF_RESOURCES
;
2047 // Allocate buffer for the output mode map
2049 Status
= ConSplitterGrowMapTable (Private
);
2050 if (EFI_ERROR (Status
)) {
2051 return EFI_OUT_OF_RESOURCES
;
2054 // As the first textout device, directly add the mode in to QueryData
2055 // and at the same time record the mapping between QueryData and TextOut.
2059 while (Mode
< MaxMode
) {
2060 Status
= TextOut
->QueryMode (
2063 &Private
->TextOutQueryData
[Mode
].Columns
,
2064 &Private
->TextOutQueryData
[Mode
].Rows
2067 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2070 if ((EFI_ERROR(Status
)) && (Mode
== 1)) {
2071 Private
->TextOutQueryData
[Mode
].Columns
= 0;
2072 Private
->TextOutQueryData
[Mode
].Rows
= 0;
2074 Private
->TextOutModeMap
[Index
] = Mode
;
2076 Index
+= Private
->TextOutListCount
;
2083 Reconstruct TextOutModeMap to get intersection of modes
2085 This routine reconstruct TextOutModeMap to get the intersection
2086 of modes for all console out devices. Because EFI/UEFI spec require
2087 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2088 intersection for mode 0 and mode 1.
2090 @param TextOutModeMap Current text out mode map, begin with the mode 80x25
2091 @param NewlyAddedMap New text out mode map, begin with the mode 80x25
2092 @param MapStepSize Mode step size for one console device
2093 @param NewMapStepSize Mode step size for one console device
2094 @param MaxMode Current max text mode
2095 @param CurrentMode Current text mode
2101 ConSplitterGetIntersection (
2102 IN INT32
*TextOutModeMap
,
2103 IN INT32
*NewlyAddedMap
,
2104 IN UINTN MapStepSize
,
2105 IN UINTN NewMapStepSize
,
2107 OUT INT32
*CurrentMode
2111 INT32
*CurrentMapEntry
;
2112 INT32
*NextMapEntry
;
2113 INT32 CurrentMaxMode
;
2117 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2118 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2119 // for mode 0 and mode 1, mode number starts from 2.
2122 CurrentMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2123 NextMapEntry
= &TextOutModeMap
[MapStepSize
* 2];
2124 NewlyAddedMap
= &NewlyAddedMap
[NewMapStepSize
* 2];
2126 CurrentMaxMode
= *MaxMode
;
2127 Mode
= *CurrentMode
;
2129 while (Index
< CurrentMaxMode
) {
2130 if (*NewlyAddedMap
== -1) {
2132 // This mode is not supported any more. Remove it. Special care
2133 // must be taken as this remove will also affect current mode;
2135 if (Index
== *CurrentMode
) {
2137 } else if (Index
< *CurrentMode
) {
2142 if (CurrentMapEntry
!= NextMapEntry
) {
2143 CopyMem (NextMapEntry
, CurrentMapEntry
, MapStepSize
* sizeof (INT32
));
2146 NextMapEntry
+= MapStepSize
;
2149 CurrentMapEntry
+= MapStepSize
;
2150 NewlyAddedMap
+= NewMapStepSize
;
2154 *CurrentMode
= Mode
;
2162 @param Private Private data structure.
2163 @param TextOut Text Out Protocol.
2169 ConSplitterSyncOutputMode (
2170 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2171 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2174 INT32 CurrentMaxMode
;
2177 INT32
*TextOutModeMap
;
2180 TEXT_OUT_SPLITTER_QUERY_DATA
*TextOutQueryData
;
2187 // Must make sure that current mode won't change even if mode number changes
2189 CurrentMaxMode
= Private
->TextOutMode
.MaxMode
;
2190 TextOutModeMap
= Private
->TextOutModeMap
;
2191 StepSize
= Private
->TextOutListCount
;
2192 TextOutQueryData
= Private
->TextOutQueryData
;
2195 // Query all the mode that the newly added TextOut supports
2198 MapTable
= TextOutModeMap
+ Private
->CurrentNumberOfConsoles
;
2199 while (Mode
< TextOut
->Mode
->MaxMode
) {
2200 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Columns
, &Rows
);
2201 if (EFI_ERROR(Status
)) {
2203 MapTable
[StepSize
] = Mode
;
2204 TextOutQueryData
[Mode
].Columns
= 0;
2205 TextOutQueryData
[Mode
].Rows
= 0;
2211 // Search the intersection map and QueryData database to see if they intersects
2214 while (Index
< CurrentMaxMode
) {
2215 QueryMode
= *(TextOutModeMap
+ Index
* StepSize
);
2216 if ((TextOutQueryData
[QueryMode
].Rows
== Rows
) && (TextOutQueryData
[QueryMode
].Columns
== Columns
)) {
2217 MapTable
[Index
* StepSize
] = Mode
;
2227 // Now search the TextOutModeMap table to find the intersection of supported
2228 // mode between ConSplitter and the newly added device.
2230 ConSplitterGetIntersection (
2235 &Private
->TextOutMode
.MaxMode
,
2236 &Private
->TextOutMode
.Mode
2247 @return EFI_OUT_OF_RESOURCES
2251 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2255 UINTN ConOutNumOfConsoles
;
2256 UINTN StdErrNumOfConsoles
;
2257 TEXT_OUT_AND_GOP_DATA
*ConOutTextOutList
;
2258 TEXT_OUT_AND_GOP_DATA
*StdErrTextOutList
;
2262 UINTN ConOutColumns
;
2264 UINTN StdErrColumns
;
2265 INT32 ConOutMaxMode
;
2266 INT32 StdErrMaxMode
;
2271 INT32
*ConOutModeMap
;
2272 INT32
*StdErrModeMap
;
2273 INT32
*ConOutMapTable
;
2274 INT32
*StdErrMapTable
;
2275 TEXT_OUT_SPLITTER_QUERY_DATA
*ConOutQueryData
;
2276 TEXT_OUT_SPLITTER_QUERY_DATA
*StdErrQueryData
;
2277 UINTN ConOutStepSize
;
2278 UINTN StdErrStepSize
;
2279 BOOLEAN FoundTheSameTextOut
;
2280 UINTN ConOutMapTableSize
;
2281 UINTN StdErrMapTableSize
;
2283 ConOutNumOfConsoles
= mConOut
.CurrentNumberOfConsoles
;
2284 StdErrNumOfConsoles
= mStdErr
.CurrentNumberOfConsoles
;
2285 ConOutTextOutList
= mConOut
.TextOutList
;
2286 StdErrTextOutList
= mStdErr
.TextOutList
;
2289 FoundTheSameTextOut
= FALSE
;
2290 while ((Indexi
< ConOutNumOfConsoles
) && (!FoundTheSameTextOut
)) {
2292 while (Indexj
< StdErrNumOfConsoles
) {
2293 if (ConOutTextOutList
->TextOut
== StdErrTextOutList
->TextOut
) {
2294 FoundTheSameTextOut
= TRUE
;
2299 StdErrTextOutList
++;
2303 ConOutTextOutList
++;
2306 if (!FoundTheSameTextOut
) {
2310 // Must make sure that current mode won't change even if mode number changes
2312 ConOutMaxMode
= mConOut
.TextOutMode
.MaxMode
;
2313 ConOutModeMap
= mConOut
.TextOutModeMap
;
2314 ConOutStepSize
= mConOut
.TextOutListCount
;
2315 ConOutQueryData
= mConOut
.TextOutQueryData
;
2317 StdErrMaxMode
= mStdErr
.TextOutMode
.MaxMode
;
2318 StdErrModeMap
= mStdErr
.TextOutModeMap
;
2319 StdErrStepSize
= mStdErr
.TextOutListCount
;
2320 StdErrQueryData
= mStdErr
.TextOutQueryData
;
2323 // Allocate the map table and set the map table's index to -1.
2325 ConOutMapTableSize
= ConOutMaxMode
* sizeof (INT32
);
2326 ConOutMapTable
= AllocateZeroPool (ConOutMapTableSize
);
2327 if (ConOutMapTable
== NULL
) {
2328 return EFI_OUT_OF_RESOURCES
;
2331 SetMem (ConOutMapTable
, ConOutMapTableSize
, 0xFF);
2333 StdErrMapTableSize
= StdErrMaxMode
* sizeof (INT32
);
2334 StdErrMapTable
= AllocateZeroPool (StdErrMapTableSize
);
2335 if (StdErrMapTable
== NULL
) {
2336 return EFI_OUT_OF_RESOURCES
;
2339 SetMem (StdErrMapTable
, StdErrMapTableSize
, 0xFF);
2342 // Find the intersection of the two set of modes. If they actually intersect, the
2343 // correponding entry in the map table is set to 1.
2346 while (Mode
< ConOutMaxMode
) {
2348 // Search the intersection map and QueryData database to see if they intersect
2351 ConOutMode
= *(ConOutModeMap
+ Mode
* ConOutStepSize
);
2352 ConOutRows
= ConOutQueryData
[ConOutMode
].Rows
;
2353 ConOutColumns
= ConOutQueryData
[ConOutMode
].Columns
;
2354 while (Index
< StdErrMaxMode
) {
2355 StdErrMode
= *(StdErrModeMap
+ Index
* StdErrStepSize
);
2356 StdErrRows
= StdErrQueryData
[StdErrMode
].Rows
;
2357 StdErrColumns
= StdErrQueryData
[StdErrMode
].Columns
;
2358 if ((StdErrRows
== ConOutRows
) && (StdErrColumns
== ConOutColumns
)) {
2359 ConOutMapTable
[Mode
] = 1;
2360 StdErrMapTable
[Index
] = 1;
2370 // Now search the TextOutModeMap table to find the intersection of supported
2371 // mode between ConSplitter and the newly added device.
2373 ConSplitterGetIntersection (
2376 mConOut
.TextOutListCount
,
2378 &(mConOut
.TextOutMode
.MaxMode
),
2379 &(mConOut
.TextOutMode
.Mode
)
2381 if (mConOut
.TextOutMode
.Mode
< 0) {
2382 mConOut
.TextOut
.SetMode (&(mConOut
.TextOut
), 0);
2385 ConSplitterGetIntersection (
2388 mStdErr
.TextOutListCount
,
2390 &(mStdErr
.TextOutMode
.MaxMode
),
2391 &(mStdErr
.TextOutMode
.Mode
)
2393 if (mStdErr
.TextOutMode
.Mode
< 0) {
2394 mStdErr
.TextOut
.SetMode (&(mStdErr
.TextOut
), 0);
2397 FreePool (ConOutMapTable
);
2398 FreePool (StdErrMapTable
);
2411 ConSplitterAddGraphicsOutputMode (
2412 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2413 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2414 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2420 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
2422 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
2423 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*CurrentGraphicsOutputMode
;
2424 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*ModeBuffer
;
2425 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*MatchedMode
;
2428 BOOLEAN AlreadyExist
;
2429 UINT32 UgaHorizontalResolution
;
2430 UINT32 UgaVerticalResolution
;
2431 UINT32 UgaColorDepth
;
2432 UINT32 UgaRefreshRate
;
2434 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2435 return EFI_UNSUPPORTED
;
2438 CurrentGraphicsOutputMode
= Private
->GraphicsOutput
.Mode
;
2443 if (Private
->CurrentNumberOfUgaDraw
!= 0) {
2445 // If any UGA device has already been added, then there is no need to
2446 // calculate intersection of display mode of different GOP/UGA device,
2447 // since only one display mode will be exported (i.e. user-defined mode)
2452 if (GraphicsOutput
!= NULL
) {
2453 if (Private
->CurrentNumberOfGraphicsOutput
== 0) {
2455 // This is the first Graphics Output device added
2457 CurrentGraphicsOutputMode
->MaxMode
= GraphicsOutput
->Mode
->MaxMode
;
2458 CurrentGraphicsOutputMode
->Mode
= GraphicsOutput
->Mode
->Mode
;
2459 CopyMem (CurrentGraphicsOutputMode
->Info
, GraphicsOutput
->Mode
->Info
, GraphicsOutput
->Mode
->SizeOfInfo
);
2460 CurrentGraphicsOutputMode
->SizeOfInfo
= GraphicsOutput
->Mode
->SizeOfInfo
;
2461 CurrentGraphicsOutputMode
->FrameBufferBase
= GraphicsOutput
->Mode
->FrameBufferBase
;
2462 CurrentGraphicsOutputMode
->FrameBufferSize
= GraphicsOutput
->Mode
->FrameBufferSize
;
2465 // Allocate resource for the private mode buffer
2467 ModeBuffer
= AllocatePool (GraphicsOutput
->Mode
->SizeOfInfo
* GraphicsOutput
->Mode
->MaxMode
);
2468 if (ModeBuffer
== NULL
) {
2469 return EFI_OUT_OF_RESOURCES
;
2471 FreePool (Private
->GraphicsOutputModeBuffer
);
2472 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2475 // Store all supported display modes to the private mode buffer
2478 for (Index
= 0; Index
< GraphicsOutput
->Mode
->MaxMode
; Index
++) {
2479 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) Index
, &SizeOfInfo
, &Info
);
2480 if (EFI_ERROR (Status
)) {
2483 CopyMem (Mode
, Info
, SizeOfInfo
);
2489 // Check intersection of display mode
2491 ModeBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
) * CurrentGraphicsOutputMode
->MaxMode
);
2492 if (ModeBuffer
== NULL
) {
2493 return EFI_OUT_OF_RESOURCES
;
2496 MatchedMode
= ModeBuffer
;
2497 Mode
= &Private
->GraphicsOutputModeBuffer
[0];
2498 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2501 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
2502 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
2503 if (EFI_ERROR (Status
)) {
2506 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2507 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2516 AlreadyExist
= FALSE
;
2518 for (Info
= ModeBuffer
; Info
< MatchedMode
; Info
++) {
2519 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) &&
2520 (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
2521 AlreadyExist
= TRUE
;
2526 if (!AlreadyExist
) {
2527 CopyMem (MatchedMode
, Mode
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2530 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2532 MatchedMode
->Version
= 0;
2533 MatchedMode
->PixelFormat
= PixelBltOnly
;
2534 ZeroMem (&MatchedMode
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2544 // Drop the old mode buffer, assign it to a new one
2546 FreePool (Private
->GraphicsOutputModeBuffer
);
2547 Private
->GraphicsOutputModeBuffer
= ModeBuffer
;
2550 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2552 CurrentGraphicsOutputMode
->MaxMode
= (UINT32
) (((UINTN
) MatchedMode
- (UINTN
) ModeBuffer
) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2553 CurrentGraphicsOutputMode
->Info
->PixelFormat
= PixelBltOnly
;
2554 ZeroMem (&CurrentGraphicsOutputMode
->Info
->PixelInformation
, sizeof (EFI_PIXEL_BITMASK
));
2555 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2556 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2557 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2561 // Graphics console driver can ensure the same mode for all GOP devices
2563 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2564 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2565 if ((Mode
->HorizontalResolution
== GraphicsOutput
->Mode
->Info
->HorizontalResolution
) &&
2566 (Mode
->VerticalResolution
== GraphicsOutput
->Mode
->Info
->VerticalResolution
)) {
2567 CurrentIndex
= Index
;
2571 if (Index
>= CurrentGraphicsOutputMode
->MaxMode
) {
2573 // if user defined mode is not found, set to default mode 800x600
2575 for (Index
= 0; Index
< CurrentGraphicsOutputMode
->MaxMode
; Index
++) {
2576 Mode
= &Private
->GraphicsOutputModeBuffer
[Index
];
2577 if ((Mode
->HorizontalResolution
== 800) && (Mode
->VerticalResolution
== 600)) {
2578 CurrentIndex
= Index
;
2584 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2586 // Graphics console driver can ensure the same mode for all GOP devices
2587 // so we can get the current mode from this video device
2591 &UgaHorizontalResolution
,
2592 &UgaVerticalResolution
,
2597 CurrentGraphicsOutputMode
->MaxMode
= 1;
2598 Info
= CurrentGraphicsOutputMode
->Info
;
2600 Info
->HorizontalResolution
= UgaHorizontalResolution
;
2601 Info
->VerticalResolution
= UgaVerticalResolution
;
2602 Info
->PixelFormat
= PixelBltOnly
;
2603 Info
->PixelsPerScanLine
= UgaHorizontalResolution
;
2604 CurrentGraphicsOutputMode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2605 CurrentGraphicsOutputMode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
2606 CurrentGraphicsOutputMode
->FrameBufferSize
= 0;
2609 // Update the private mode buffer
2611 CopyMem (&Private
->GraphicsOutputModeBuffer
[0], Info
, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
2614 // Only mode 0 is available to be set
2621 if (GraphicsOutput
!= NULL
) {
2622 Private
->CurrentNumberOfGraphicsOutput
++;
2624 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2625 Private
->CurrentNumberOfUgaDraw
++;
2629 // Force GraphicsOutput mode to be set,
2630 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2632 Private
->HardwareNeedsStarting
= TRUE
;
2634 // Current mode number may need update now, so set it to an invalid mode number
2636 CurrentGraphicsOutputMode
->Mode
= 0xffff;
2638 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2640 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, (UINT32
) CurrentIndex
);
2643 // If user defined mode is not valid for UGA, set to the default mode 800x600.
2645 if (EFI_ERROR(Status
)) {
2646 (Private
->GraphicsOutputModeBuffer
[0]).HorizontalResolution
= 800;
2647 (Private
->GraphicsOutputModeBuffer
[0]).VerticalResolution
= 600;
2648 Status
= Private
->GraphicsOutput
.SetMode (&Private
->GraphicsOutput
, 0);
2656 This routine will get the current console mode information (column, row)
2657 from ConsoleOutMode variable and set it; if the variable does not exist,
2658 set to user defined console mode.
2666 ConsplitterSetConsoleOutMode (
2667 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
2678 CONSOLE_OUT_MODE
*ModeInfo
;
2679 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
2683 TextOut
= &Private
->TextOut
;
2684 MaxMode
= (UINTN
) (TextOut
->Mode
->MaxMode
);
2685 ModeInfoSize
= sizeof (CONSOLE_OUT_MODE
);
2687 ModeInfo
= AllocateZeroPool (sizeof(CONSOLE_OUT_MODE
));
2688 ASSERT(ModeInfo
!= NULL
);
2690 Status
= gRT
->GetVariable (
2692 &gEfiGenericPlatformVariableGuid
,
2699 // Set to the default mode 80 x 25 required by EFI/UEFI spec;
2700 // user can also define other valid default console mode here.
2702 if (EFI_ERROR(Status
)) {
2703 ModeInfo
->Column
= 80;
2705 Status
= gRT
->SetVariable (
2707 &gEfiGenericPlatformVariableGuid
,
2708 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2709 sizeof (CONSOLE_OUT_MODE
),
2714 for (Mode
= 0; Mode
< MaxMode
; Mode
++) {
2715 Status
= TextOut
->QueryMode (TextOut
, Mode
, &Col
, &Row
);
2716 if (!EFI_ERROR(Status
)) {
2717 if (Col
== ModeInfo
->Column
&& Row
== ModeInfo
->Row
) {
2720 if (Col
== 80 && Row
== 25) {
2726 Status
= TextOut
->SetMode (TextOut
, PreferMode
);
2729 // if current mode setting is failed, default 80x25 mode will be set.
2731 if (EFI_ERROR(Status
)) {
2732 Status
= TextOut
->SetMode (TextOut
, BaseMode
);
2733 ASSERT(!EFI_ERROR(Status
));
2735 ModeInfo
->Column
= 80;
2739 // Update ConOutMode variable
2741 Status
= gRT
->SetVariable (
2743 &gEfiGenericPlatformVariableGuid
,
2744 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2745 sizeof (CONSOLE_OUT_MODE
),
2750 gBS
->FreePool (ModeInfo
);
2762 ConSplitterTextOutAddDevice (
2763 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2764 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
,
2765 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
2766 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
2770 UINTN CurrentNumOfConsoles
;
2773 UINT32 UgaHorizontalResolution
;
2774 UINT32 UgaVerticalResolution
;
2775 UINT32 UgaColorDepth
;
2776 UINT32 UgaRefreshRate
;
2777 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
2779 Status
= EFI_SUCCESS
;
2780 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2783 // If the Text Out List is full, enlarge it by calling growbuffer().
2785 while (CurrentNumOfConsoles
>= Private
->TextOutListCount
) {
2786 Status
= ConSplitterGrowBuffer (
2787 sizeof (TEXT_OUT_AND_GOP_DATA
),
2788 &Private
->TextOutListCount
,
2789 (VOID
**) &Private
->TextOutList
2791 if (EFI_ERROR (Status
)) {
2792 return EFI_OUT_OF_RESOURCES
;
2795 // Also need to reallocate the TextOutModeMap table
2797 Status
= ConSplitterGrowMapTable (Private
);
2798 if (EFI_ERROR (Status
)) {
2799 return EFI_OUT_OF_RESOURCES
;
2803 TextAndGop
= &Private
->TextOutList
[CurrentNumOfConsoles
];
2805 TextAndGop
->TextOut
= TextOut
;
2806 TextAndGop
->GraphicsOutput
= GraphicsOutput
;
2807 TextAndGop
->UgaDraw
= UgaDraw
;
2809 if ((GraphicsOutput
== NULL
) && (UgaDraw
== NULL
)) {
2811 // If No GOP/UGA device then use the ConOut device
2813 TextAndGop
->TextOutEnabled
= TRUE
;
2816 // If GOP/UGA device use ConOut device only used if screen is in Text mode
2818 TextAndGop
->TextOutEnabled
= (BOOLEAN
) (Private
->ConsoleOutputMode
== EfiConsoleControlScreenText
);
2821 if (CurrentNumOfConsoles
== 0) {
2823 // Add the first device's output mode to console splitter's mode list
2825 Status
= ConSplitterAddOutputMode (Private
, TextOut
);
2827 ConSplitterSyncOutputMode (Private
, TextOut
);
2830 Private
->CurrentNumberOfConsoles
++;
2833 // Scan both TextOutList, for the intersection TextOut device
2834 // maybe both ConOut and StdErr incorporate the same Text Out
2835 // device in them, thus the output of both should be synced.
2837 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2839 CurrentMode
= Private
->TextOutMode
.Mode
;
2840 MaxMode
= Private
->TextOutMode
.MaxMode
;
2841 ASSERT (MaxMode
>= 1);
2844 // Update DevNull mode according to current video device
2846 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2847 if ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) {
2848 ConSplitterAddGraphicsOutputMode (Private
, GraphicsOutput
, UgaDraw
);
2851 if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2852 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2853 Status
= UgaDraw
->GetMode (
2855 &UgaHorizontalResolution
,
2856 &UgaVerticalResolution
,
2860 if (!EFI_ERROR (Status
)) {
2861 Status
= ConSpliterUgaDrawSetMode (
2863 UgaHorizontalResolution
,
2864 UgaVerticalResolution
,
2870 // If GetMode/SetMode is failed, set to 800x600 mode
2872 if(EFI_ERROR (Status
)) {
2873 Status
= ConSpliterUgaDrawSetMode (
2884 if (Private
->ConsoleOutputMode
== EfiConsoleControlScreenGraphics
&& GraphicsOutput
!= NULL
) {
2886 // We just added a new GOP or UGA device in graphics mode
2888 if (FeaturePcdGet (PcdConOutGopSupport
)) {
2889 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2890 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
2891 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
2893 } else if ((CurrentMode
>= 0) && ((GraphicsOutput
!= NULL
) || (UgaDraw
!= NULL
)) && (CurrentMode
< Private
->TextOutMode
.MaxMode
)) {
2895 // The new console supports the same mode of the current console so sync up
2897 DevNullSyncStdOut (Private
);
2900 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2902 Private
->TextOut
.SetMode (&Private
->TextOut
, 0);
2906 // After adding new console device, all existing console devices should be
2907 // synced to the current shared mode.
2909 ConsplitterSetConsoleOutMode (Private
);
2922 ConSplitterTextOutDeleteDevice (
2923 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
2924 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
2928 UINTN CurrentNumOfConsoles
;
2929 TEXT_OUT_AND_GOP_DATA
*TextOutList
;
2933 // Remove the specified text-out device data structure from the Text out List,
2934 // and rearrange the remaining data structures in the Text out List.
2936 CurrentNumOfConsoles
= Private
->CurrentNumberOfConsoles
;
2937 Index
= (INT32
) CurrentNumOfConsoles
- 1;
2938 TextOutList
= Private
->TextOutList
;
2939 while (Index
>= 0) {
2940 if (TextOutList
->TextOut
== TextOut
) {
2941 CopyMem (TextOutList
, TextOutList
+ 1, sizeof (TEXT_OUT_AND_GOP_DATA
) * Index
);
2942 CurrentNumOfConsoles
--;
2943 if (TextOutList
->UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
2944 Private
->CurrentNumberOfUgaDraw
--;
2946 if (TextOutList
->GraphicsOutput
!= NULL
) {
2947 Private
->CurrentNumberOfGraphicsOutput
--;
2956 // The specified TextOut is not managed by the ConSplitter driver
2959 return EFI_NOT_FOUND
;
2962 if (CurrentNumOfConsoles
== 0) {
2964 // If the number of consoles is zero clear the Dev NULL device
2966 Private
->CurrentNumberOfConsoles
= 0;
2967 Private
->TextOutMode
.MaxMode
= 1;
2968 Private
->TextOutQueryData
[0].Columns
= 80;
2969 Private
->TextOutQueryData
[0].Rows
= 25;
2970 DevNullTextOutSetMode (Private
, 0);
2975 // Max Mode is realy an intersection of the QueryMode command to all
2976 // devices. So we must copy the QueryMode of the first device to
2980 Private
->TextOutQueryData
,
2981 Private
->TextOutQueryDataCount
* sizeof (TEXT_OUT_SPLITTER_QUERY_DATA
)
2984 FreePool (Private
->TextOutModeMap
);
2985 Private
->TextOutModeMap
= NULL
;
2986 TextOutList
= Private
->TextOutList
;
2989 // Add the first TextOut to the QueryData array and ModeMap table
2991 Status
= ConSplitterAddOutputMode (Private
, TextOutList
->TextOut
);
2994 // Now add one by one
2997 Private
->CurrentNumberOfConsoles
= 1;
2999 while ((UINTN
) Index
< CurrentNumOfConsoles
) {
3000 ConSplitterSyncOutputMode (Private
, TextOutList
->TextOut
);
3002 Private
->CurrentNumberOfConsoles
++;
3006 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3011 // ConSplitter TextIn member functions
3015 Reset the input device and optionaly run diagnostics
3017 @param This Protocol instance pointer.
3018 @param ExtendedVerification Driver may perform diagnostics on reset.
3020 @retval EFI_SUCCESS The device was reset.
3021 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3027 ConSplitterTextInReset (
3028 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3029 IN BOOLEAN ExtendedVerification
3033 EFI_STATUS ReturnStatus
;
3034 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3037 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3039 Private
->KeyEventSignalState
= FALSE
;
3042 // return the worst status met
3044 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3045 Status
= Private
->TextInList
[Index
]->Reset (
3046 Private
->TextInList
[Index
],
3047 ExtendedVerification
3049 if (EFI_ERROR (Status
)) {
3050 ReturnStatus
= Status
;
3054 return ReturnStatus
;
3059 Reads the next keystroke from the input device. The WaitForKey Event can
3060 be used to test for existance of a keystroke via WaitForEvent () call.
3062 @param This Protocol instance pointer.
3063 @param Key Driver may perform diagnostics on reset.
3065 @retval EFI_SUCCESS The keystroke information was returned.
3066 @retval EFI_NOT_READY There was no keystroke data availiable.
3067 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3073 ConSplitterTextInPrivateReadKeyStroke (
3074 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3075 OUT EFI_INPUT_KEY
*Key
3080 EFI_INPUT_KEY CurrentKey
;
3082 Key
->UnicodeChar
= 0;
3083 Key
->ScanCode
= SCAN_NULL
;
3086 // if no physical console input device exists, return EFI_NOT_READY;
3087 // if any physical console input device has key input,
3088 // return the key and EFI_SUCCESS.
3090 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3091 Status
= Private
->TextInList
[Index
]->ReadKeyStroke (
3092 Private
->TextInList
[Index
],
3095 if (!EFI_ERROR (Status
)) {
3101 return EFI_NOT_READY
;
3106 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
3107 the only device locked.
3111 @retval TRUE StdIn locked
3112 @retval FALSE StdIn working normally
3116 ConSpliterConssoleControlStdInLocked (
3120 return mConIn
.PasswordEnabled
;
3125 This timer event will fire when StdIn is locked. It will check the key
3126 sequence on StdIn to see if it matches the password. Any error in the
3127 password will cause the check to reset. As long a mConIn.PasswordEnabled is
3128 TRUE the StdIn splitter will not report any input.
3130 (Standard EFI_EVENT_NOTIFY)
3137 ConSpliterConsoleControlLockStdInEvent (
3144 CHAR16 BackSpaceString
[2];
3145 CHAR16 SpaceString
[2];
3148 Status
= ConSplitterTextInPrivateReadKeyStroke (&mConIn
, &Key
);
3149 if (!EFI_ERROR (Status
)) {
3151 // if it's an ENTER, match password
3153 if ((Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) && (Key
.ScanCode
== SCAN_NULL
)) {
3154 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = CHAR_NULL
;
3155 if (StrCmp (mConIn
.Password
, mConIn
.PwdAttempt
)) {
3157 // Password not match
3159 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\rPassword not correct\n\r");
3160 mConIn
.PwdIndex
= 0;
3163 // Key matches password sequence
3165 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, 0);
3166 mConIn
.PasswordEnabled
= FALSE
;
3167 Status
= EFI_NOT_READY
;
3169 } else if ((Key
.UnicodeChar
== CHAR_BACKSPACE
) && (Key
.ScanCode
== SCAN_NULL
)) {
3173 if (mConIn
.PwdIndex
> 0) {
3174 BackSpaceString
[0] = CHAR_BACKSPACE
;
3175 BackSpaceString
[1] = 0;
3177 SpaceString
[0] = ' ';
3180 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3181 ConSplitterTextOutOutputString (&mConOut
.TextOut
, SpaceString
);
3182 ConSplitterTextOutOutputString (&mConOut
.TextOut
, BackSpaceString
);
3186 } else if ((Key
.ScanCode
== SCAN_NULL
) && (Key
.UnicodeChar
>= 32)) {
3188 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
3190 if (mConIn
.PwdIndex
< (MAX_STD_IN_PASSWORD
- 1)) {
3191 if (mConIn
.PwdIndex
== 0) {
3192 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"\n\r");
3195 ConSplitterTextOutOutputString (&mConOut
.TextOut
, (CHAR16
*) L
"*");
3196 mConIn
.PwdAttempt
[mConIn
.PwdIndex
] = Key
.UnicodeChar
;
3201 } while (!EFI_ERROR (Status
));
3206 If Password is NULL unlock the password state variable and set the event
3207 timer. If the Password is too big return an error. If the Password is valid
3208 Copy the Password and enable state variable and then arm the periodic timer
3211 @retval EFI_SUCCESS Lock the StdIn device
3212 @retval EFI_INVALID_PARAMETER Password is NULL
3213 @retval EFI_OUT_OF_RESOURCES Buffer allocation to store the password fails
3218 ConSpliterConsoleControlLockStdIn (
3219 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
3223 if (Password
== NULL
) {
3224 return EFI_INVALID_PARAMETER
;
3227 if (StrLen (Password
) >= MAX_STD_IN_PASSWORD
) {
3229 // Currently have a max password size
3231 return EFI_OUT_OF_RESOURCES
;
3234 // Save the password, initialize state variables and arm event timer
3236 StrCpy (mConIn
.Password
, Password
);
3237 mConIn
.PasswordEnabled
= TRUE
;
3238 mConIn
.PwdIndex
= 0;
3239 gBS
->SetTimer (mConIn
.LockEvent
, TimerPeriodic
, (10000 * 25));
3246 Reads the next keystroke from the input device. The WaitForKey Event can
3247 be used to test for existance of a keystroke via WaitForEvent () call.
3248 If the ConIn is password locked make it look like no keystroke is availible
3250 @param This Protocol instance pointer.
3251 @param Key Driver may perform diagnostics on reset.
3253 @retval EFI_SUCCESS The keystroke information was returned.
3254 @retval EFI_NOT_READY There was no keystroke data availiable.
3255 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3261 ConSplitterTextInReadKeyStroke (
3262 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
3263 OUT EFI_INPUT_KEY
*Key
3266 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3268 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3269 if (Private
->PasswordEnabled
) {
3271 // If StdIn Locked return not ready
3273 return EFI_NOT_READY
;
3276 Private
->KeyEventSignalState
= FALSE
;
3278 return ConSplitterTextInPrivateReadKeyStroke (Private
, Key
);
3283 This event agregates all the events of the ConIn devices in the spliter.
3284 If the ConIn is password locked then return.
3285 If any events of physical ConIn devices are signaled, signal the ConIn
3286 spliter event. This will cause the calling code to call
3287 ConSplitterTextInReadKeyStroke ().
3289 @param Event The Event assoicated with callback.
3290 @param Context Context registered when Event was created.
3297 ConSplitterTextInWaitForKey (
3303 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3306 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3307 if (Private
->PasswordEnabled
) {
3309 // If StdIn Locked return not ready
3315 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3317 if (Private
->KeyEventSignalState
) {
3318 gBS
->SignalEvent (Event
);
3322 // if any physical console input device has key input, signal the event.
3324 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
3325 Status
= gBS
->CheckEvent (Private
->TextInList
[Index
]->WaitForKey
);
3326 if (!EFI_ERROR (Status
)) {
3327 gBS
->SignalEvent (Event
);
3328 Private
->KeyEventSignalState
= TRUE
;
3337 @param RegsiteredData A pointer to a buffer that is filled in with the
3338 keystroke state data for the key that was
3340 @param InputData A pointer to a buffer that is filled in with the
3341 keystroke state data for the key that was
3344 @retval TRUE Key be pressed matches a registered key.
3345 @retval FLASE Match failed.
3350 IN EFI_KEY_DATA
*RegsiteredData
,
3351 IN EFI_KEY_DATA
*InputData
3354 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
3356 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
3357 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
3362 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3364 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
3365 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
3368 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
3369 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
3378 // Simple Text Input Ex protocol functions
3383 Reset the input device and optionaly run diagnostics
3385 @param This Protocol instance pointer.
3386 @param ExtendedVerification Driver may perform diagnostics on reset.
3388 @retval EFI_SUCCESS The device was reset.
3389 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3395 ConSplitterTextInResetEx (
3396 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3397 IN BOOLEAN ExtendedVerification
3401 EFI_STATUS ReturnStatus
;
3402 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3405 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3407 Private
->KeyEventSignalState
= FALSE
;
3410 // return the worst status met
3412 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3413 Status
= Private
->TextInExList
[Index
]->Reset (
3414 Private
->TextInExList
[Index
],
3415 ExtendedVerification
3417 if (EFI_ERROR (Status
)) {
3418 ReturnStatus
= Status
;
3422 return ReturnStatus
;
3428 Reads the next keystroke from the input device. The WaitForKey Event can
3429 be used to test for existance of a keystroke via WaitForEvent () call.
3431 @param This Protocol instance pointer.
3432 @param KeyData A pointer to a buffer that is filled in with the
3433 keystroke state data for the key that was
3436 @retval EFI_SUCCESS The keystroke information was returned.
3437 @retval EFI_NOT_READY There was no keystroke data availiable.
3438 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
3440 @retval EFI_INVALID_PARAMETER KeyData is NULL.
3445 ConSplitterTextInReadKeyStrokeEx (
3446 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3447 OUT EFI_KEY_DATA
*KeyData
3450 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3453 EFI_KEY_DATA CurrentKeyData
;
3456 if (KeyData
== NULL
) {
3457 return EFI_INVALID_PARAMETER
;
3460 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3461 if (Private
->PasswordEnabled
) {
3463 // If StdIn Locked return not ready
3465 return EFI_NOT_READY
;
3468 Private
->KeyEventSignalState
= FALSE
;
3470 KeyData
->Key
.UnicodeChar
= 0;
3471 KeyData
->Key
.ScanCode
= SCAN_NULL
;
3474 // if no physical console input device exists, return EFI_NOT_READY;
3475 // if any physical console input device has key input,
3476 // return the key and EFI_SUCCESS.
3478 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3479 Status
= Private
->TextInExList
[Index
]->ReadKeyStrokeEx (
3480 Private
->TextInExList
[Index
],
3483 if (!EFI_ERROR (Status
)) {
3484 CopyMem (KeyData
, &CurrentKeyData
, sizeof (CurrentKeyData
));
3489 return EFI_NOT_READY
;
3494 Set certain state for the input device.
3496 @param This Protocol instance pointer.
3497 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
3498 state for the input device.
3500 @retval EFI_SUCCESS The device state was set successfully.
3501 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3502 could not have the setting adjusted.
3503 @retval EFI_UNSUPPORTED The device does not have the ability to set its
3505 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
3510 ConSplitterTextInSetState (
3511 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3512 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
3515 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3519 if (KeyToggleState
== NULL
) {
3520 return EFI_INVALID_PARAMETER
;
3523 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3526 // if no physical console input device exists, return EFI_SUCCESS;
3527 // otherwise return the status of setting state of physical console input device
3529 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3530 Status
= Private
->TextInExList
[Index
]->SetState (
3531 Private
->TextInExList
[Index
],
3534 if (EFI_ERROR (Status
)) {
3545 Register a notification function for a particular keystroke for the input device.
3547 @param This Protocol instance pointer.
3548 @param KeyData A pointer to a buffer that is filled in with the
3549 keystroke information data for the key that was
3551 @param KeyNotificationFunction Points to the function to be called when the key
3552 sequence is typed specified by KeyData.
3553 @param NotifyHandle Points to the unique handle assigned to the
3554 registered notification.
3556 @retval EFI_SUCCESS The notification function was registered
3558 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
3560 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
3565 ConSplitterTextInRegisterKeyNotify (
3566 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3567 IN EFI_KEY_DATA
*KeyData
,
3568 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
3569 OUT EFI_HANDLE
*NotifyHandle
3572 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3575 TEXT_IN_EX_SPLITTER_NOTIFY
*NewNotify
;
3577 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3580 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
3581 return EFI_INVALID_PARAMETER
;
3584 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3587 // if no physical console input device exists,
3588 // return EFI_SUCCESS directly.
3590 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3595 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3597 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3598 CurrentNotify
= CR (
3600 TEXT_IN_EX_SPLITTER_NOTIFY
,
3602 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
3604 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
3605 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
3606 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
3613 // Allocate resource to save the notification function
3615 NewNotify
= (TEXT_IN_EX_SPLITTER_NOTIFY
*) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY
));
3616 if (NewNotify
== NULL
) {
3617 return EFI_OUT_OF_RESOURCES
;
3619 NewNotify
->NotifyHandleList
= (EFI_HANDLE
*) AllocateZeroPool (sizeof (EFI_HANDLE
) * Private
->CurrentNumberOfExConsoles
);
3620 if (NewNotify
->NotifyHandleList
== NULL
) {
3621 gBS
->FreePool (NewNotify
);
3622 return EFI_OUT_OF_RESOURCES
;
3624 NewNotify
->Signature
= TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
;
3625 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
3626 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
3629 // Return the wrong status of registering key notify of
3630 // physical console input device if meet problems
3632 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3633 Status
= Private
->TextInExList
[Index
]->RegisterKeyNotify (
3634 Private
->TextInExList
[Index
],
3636 KeyNotificationFunction
,
3637 &NewNotify
->NotifyHandleList
[Index
]
3639 if (EFI_ERROR (Status
)) {
3640 gBS
->FreePool (NewNotify
->NotifyHandleList
);
3641 gBS
->FreePool (NewNotify
);
3647 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
3649 Status
= gBS
->InstallMultipleProtocolInterfaces (
3650 &NewNotify
->NotifyHandle
,
3651 &gSimpleTextInExNotifyGuid
,
3655 ASSERT_EFI_ERROR (Status
);
3657 InsertTailList (&mConIn
.NotifyList
, &NewNotify
->NotifyEntry
);
3659 *NotifyHandle
= NewNotify
->NotifyHandle
;
3667 Remove a registered notification function from a particular keystroke.
3669 @param This Protocol instance pointer.
3670 @param NotificationHandle The handle of the notification function being
3673 @retval EFI_SUCCESS The notification function was unregistered
3675 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
3676 @retval EFI_NOT_FOUND Can not find the matching entry in database.
3681 ConSplitterTextInUnregisterKeyNotify (
3682 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
3683 IN EFI_HANDLE NotificationHandle
3686 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3689 TEXT_IN_EX_SPLITTER_NOTIFY
*CurrentNotify
;
3692 if (NotificationHandle
== NULL
) {
3693 return EFI_INVALID_PARAMETER
;
3696 Status
= gBS
->OpenProtocol (
3698 &gSimpleTextInExNotifyGuid
,
3702 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
3704 if (EFI_ERROR (Status
)) {
3705 return EFI_INVALID_PARAMETER
;
3708 Private
= TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
3711 // if no physical console input device exists,
3712 // return EFI_SUCCESS directly.
3714 if (Private
->CurrentNumberOfExConsoles
<= 0) {
3718 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
3719 CurrentNotify
= CR (Link
, TEXT_IN_EX_SPLITTER_NOTIFY
, NotifyEntry
, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE
);
3720 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
3721 for (Index
= 0; Index
< Private
->CurrentNumberOfExConsoles
; Index
++) {
3722 Status
= Private
->TextInExList
[Index
]->UnregisterKeyNotify (
3723 Private
->TextInExList
[Index
],
3724 CurrentNotify
->NotifyHandleList
[Index
]
3726 if (EFI_ERROR (Status
)) {
3730 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
3731 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3732 CurrentNotify
->NotifyHandle
,
3733 &gSimpleTextInExNotifyGuid
,
3737 ASSERT_EFI_ERROR (Status
);
3738 gBS
->FreePool (CurrentNotify
->NotifyHandleList
);
3739 gBS
->FreePool (CurrentNotify
);
3744 return EFI_NOT_FOUND
;
3750 Reset the input device and optionaly run diagnostics
3752 @param This Protocol instance pointer.
3753 @param ExtendedVerification Driver may perform diagnostics on reset.
3755 @retval EFI_SUCCESS The device was reset.
3756 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3762 ConSplitterSimplePointerReset (
3763 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3764 IN BOOLEAN ExtendedVerification
3768 EFI_STATUS ReturnStatus
;
3769 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3772 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3774 Private
->InputEventSignalState
= FALSE
;
3776 if (Private
->CurrentNumberOfPointers
== 0) {
3780 // return the worst status met
3782 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3783 Status
= Private
->PointerList
[Index
]->Reset (
3784 Private
->PointerList
[Index
],
3785 ExtendedVerification
3787 if (EFI_ERROR (Status
)) {
3788 ReturnStatus
= Status
;
3792 return ReturnStatus
;
3797 Reads the next keystroke from the input device. The WaitForKey Event can
3798 be used to test for existance of a keystroke via WaitForEvent () call.
3800 @param This Protocol instance pointer. State -
3802 @retval EFI_SUCCESS The keystroke information was returned.
3803 @retval EFI_NOT_READY There was no keystroke data availiable.
3804 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3810 ConSplitterSimplePointerPrivateGetState (
3811 IN TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
,
3812 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3816 EFI_STATUS ReturnStatus
;
3818 EFI_SIMPLE_POINTER_STATE CurrentState
;
3820 State
->RelativeMovementX
= 0;
3821 State
->RelativeMovementY
= 0;
3822 State
->RelativeMovementZ
= 0;
3823 State
->LeftButton
= FALSE
;
3824 State
->RightButton
= FALSE
;
3827 // if no physical console input device exists, return EFI_NOT_READY;
3828 // if any physical console input device has key input,
3829 // return the key and EFI_SUCCESS.
3831 ReturnStatus
= EFI_NOT_READY
;
3832 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3834 Status
= Private
->PointerList
[Index
]->GetState (
3835 Private
->PointerList
[Index
],
3838 if (!EFI_ERROR (Status
)) {
3839 if (ReturnStatus
== EFI_NOT_READY
) {
3840 ReturnStatus
= EFI_SUCCESS
;
3843 if (CurrentState
.LeftButton
) {
3844 State
->LeftButton
= TRUE
;
3847 if (CurrentState
.RightButton
) {
3848 State
->RightButton
= TRUE
;
3851 if (CurrentState
.RelativeMovementX
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionX
!= 0) {
3852 State
->RelativeMovementX
+= (CurrentState
.RelativeMovementX
* (INT32
) Private
->SimplePointerMode
.ResolutionX
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionX
;
3855 if (CurrentState
.RelativeMovementY
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionY
!= 0) {
3856 State
->RelativeMovementY
+= (CurrentState
.RelativeMovementY
* (INT32
) Private
->SimplePointerMode
.ResolutionY
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionY
;
3859 if (CurrentState
.RelativeMovementZ
!= 0 && Private
->PointerList
[Index
]->Mode
->ResolutionZ
!= 0) {
3860 State
->RelativeMovementZ
+= (CurrentState
.RelativeMovementZ
* (INT32
) Private
->SimplePointerMode
.ResolutionZ
) / (INT32
) Private
->PointerList
[Index
]->Mode
->ResolutionZ
;
3862 } else if (Status
== EFI_DEVICE_ERROR
) {
3863 ReturnStatus
= EFI_DEVICE_ERROR
;
3867 return ReturnStatus
;
3872 Reads the next keystroke from the input device. The WaitForKey Event can
3873 be used to test for existance of a keystroke via WaitForEvent () call.
3874 If the ConIn is password locked make it look like no keystroke is availible
3876 @param This Protocol instance pointer. State -
3878 @retval EFI_SUCCESS The keystroke information was returned.
3879 @retval EFI_NOT_READY There was no keystroke data availiable.
3880 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3886 ConSplitterSimplePointerGetState (
3887 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
3888 IN OUT EFI_SIMPLE_POINTER_STATE
*State
3891 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3893 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This
);
3894 if (Private
->PasswordEnabled
) {
3896 // If StdIn Locked return not ready
3898 return EFI_NOT_READY
;
3901 Private
->InputEventSignalState
= FALSE
;
3903 return ConSplitterSimplePointerPrivateGetState (Private
, State
);
3908 This event agregates all the events of the ConIn devices in the spliter.
3909 If the ConIn is password locked then return.
3910 If any events of physical ConIn devices are signaled, signal the ConIn
3911 spliter event. This will cause the calling code to call
3912 ConSplitterTextInReadKeyStroke ().
3914 @param Event The Event assoicated with callback.
3915 @param Context Context registered when Event was created.
3922 ConSplitterSimplePointerWaitForInput (
3928 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3931 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
3932 if (Private
->PasswordEnabled
) {
3934 // If StdIn Locked return not ready
3940 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3942 if (Private
->InputEventSignalState
) {
3943 gBS
->SignalEvent (Event
);
3947 // if any physical console input device has key input, signal the event.
3949 for (Index
= 0; Index
< Private
->CurrentNumberOfPointers
; Index
++) {
3950 Status
= gBS
->CheckEvent (Private
->PointerList
[Index
]->WaitForInput
);
3951 if (!EFI_ERROR (Status
)) {
3952 gBS
->SignalEvent (Event
);
3953 Private
->InputEventSignalState
= TRUE
;
3959 // Absolute Pointer Protocol functions
3964 Resets the pointer device hardware.
3966 @param This Protocol instance pointer.
3967 @param ExtendedVerification Driver may perform diagnostics on reset.
3969 @retval EFI_SUCCESS The device was reset.
3970 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3976 ConSplitterAbsolutePointerReset (
3977 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
3978 IN BOOLEAN ExtendedVerification
3982 EFI_STATUS ReturnStatus
;
3983 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
3986 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
3988 Private
->AbsoluteInputEventSignalState
= FALSE
;
3990 if (Private
->CurrentNumberOfAbsolutePointers
== 0) {
3994 // return the worst status met
3996 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
3997 Status
= Private
->AbsolutePointerList
[Index
]->Reset (
3998 Private
->AbsolutePointerList
[Index
],
3999 ExtendedVerification
4001 if (EFI_ERROR (Status
)) {
4002 ReturnStatus
= Status
;
4006 return ReturnStatus
;
4011 Retrieves the current state of a pointer device.
4013 @param This Protocol instance pointer.
4014 @param State A pointer to the state information on the
4017 @retval EFI_SUCCESS The state of the pointer device was returned in
4019 @retval EFI_NOT_READY The state of the pointer device has not changed
4020 since the last call to GetState().
4021 @retval EFI_DEVICE_ERROR A device error occurred while attempting to
4022 retrieve the pointer device's current state.
4027 ConSplitterAbsolutePointerGetState (
4028 IN EFI_ABSOLUTE_POINTER_PROTOCOL
*This
,
4029 IN OUT EFI_ABSOLUTE_POINTER_STATE
*State
4032 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4034 EFI_STATUS ReturnStatus
;
4036 EFI_ABSOLUTE_POINTER_STATE CurrentState
;
4039 Private
= TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This
);
4040 if (Private
->PasswordEnabled
) {
4042 // If StdIn Locked return not ready
4044 return EFI_NOT_READY
;
4047 Private
->AbsoluteInputEventSignalState
= FALSE
;
4049 State
->CurrentX
= 0;
4050 State
->CurrentY
= 0;
4051 State
->CurrentZ
= 0;
4052 State
->ActiveButtons
= 0;
4055 // if no physical pointer device exists, return EFI_NOT_READY;
4056 // if any physical pointer device has changed state,
4057 // return the state and EFI_SUCCESS.
4059 ReturnStatus
= EFI_NOT_READY
;
4060 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4062 Status
= Private
->AbsolutePointerList
[Index
]->GetState (
4063 Private
->AbsolutePointerList
[Index
],
4066 if (!EFI_ERROR (Status
)) {
4067 if (ReturnStatus
== EFI_NOT_READY
) {
4068 ReturnStatus
= EFI_SUCCESS
;
4071 State
->ActiveButtons
= CurrentState
.ActiveButtons
;
4073 if (!(Private
->AbsolutePointerMode
.AbsoluteMinX
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxX
== 0)) {
4074 State
->CurrentX
= CurrentState
.CurrentX
;
4076 if (!(Private
->AbsolutePointerMode
.AbsoluteMinY
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxY
== 0)) {
4077 State
->CurrentY
= CurrentState
.CurrentY
;
4079 if (!(Private
->AbsolutePointerMode
.AbsoluteMinZ
== 0 && Private
->AbsolutePointerMode
.AbsoluteMaxZ
== 0)) {
4080 State
->CurrentZ
= CurrentState
.CurrentZ
;
4083 } else if (Status
== EFI_DEVICE_ERROR
) {
4084 ReturnStatus
= EFI_DEVICE_ERROR
;
4088 return ReturnStatus
;
4093 This event agregates all the events of the pointer devices in the splitter.
4094 If the ConIn is password locked then return.
4095 If any events of physical pointer devices are signaled, signal the pointer
4096 splitter event. This will cause the calling code to call
4097 ConSplitterAbsolutePointerGetState ().
4099 @param Event The Event assoicated with callback.
4100 @param Context Context registered when Event was created.
4107 ConSplitterAbsolutePointerWaitForInput (
4113 TEXT_IN_SPLITTER_PRIVATE_DATA
*Private
;
4116 Private
= (TEXT_IN_SPLITTER_PRIVATE_DATA
*) Context
;
4117 if (Private
->PasswordEnabled
) {
4119 // If StdIn Locked return not ready
4125 // if AbsoluteInputEventSignalState is flagged before,
4126 // and not cleared by Reset() or GetState(), signal it
4128 if (Private
->AbsoluteInputEventSignalState
) {
4129 gBS
->SignalEvent (Event
);
4133 // if any physical console input device has key input, signal the event.
4135 for (Index
= 0; Index
< Private
->CurrentNumberOfAbsolutePointers
; Index
++) {
4136 Status
= gBS
->CheckEvent (Private
->AbsolutePointerList
[Index
]->WaitForInput
);
4137 if (!EFI_ERROR (Status
)) {
4138 gBS
->SignalEvent (Event
);
4139 Private
->AbsoluteInputEventSignalState
= TRUE
;
4146 Reset the text output device hardware and optionaly run diagnostics
4148 @param This Protocol instance pointer.
4149 @param ExtendedVerification Driver may perform more exhaustive verfication
4150 operation of the device during reset.
4152 @retval EFI_SUCCESS The text output device was reset.
4153 @retval EFI_DEVICE_ERROR The text output device is not functioning
4154 correctly and could not be reset.
4159 ConSplitterTextOutReset (
4160 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4161 IN BOOLEAN ExtendedVerification
4165 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4167 EFI_STATUS ReturnStatus
;
4169 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4172 // return the worst status met
4174 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4176 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4178 Status
= Private
->TextOutList
[Index
].TextOut
->Reset (
4179 Private
->TextOutList
[Index
].TextOut
,
4180 ExtendedVerification
4182 if (EFI_ERROR (Status
)) {
4183 ReturnStatus
= Status
;
4188 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BLACK
));
4190 Status
= DevNullTextOutSetMode (Private
, 0);
4191 if (EFI_ERROR (Status
)) {
4192 ReturnStatus
= Status
;
4195 return ReturnStatus
;
4200 Write a Unicode string to the output device.
4202 @param This Protocol instance pointer.
4203 @param String The NULL-terminated Unicode string to be
4204 displayed on the output device(s). All output
4205 devices must also support the Unicode drawing
4206 defined in this file.
4208 @retval EFI_SUCCESS The string was output to the device.
4209 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
4211 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
4213 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
4214 characters in the Unicode string could not be
4215 rendered and were skipped.
4220 ConSplitterTextOutOutputString (
4221 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4226 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4228 UINTN BackSpaceCount
;
4229 EFI_STATUS ReturnStatus
;
4230 CHAR16
*TargetString
;
4232 This
->SetAttribute (This
, This
->Mode
->Attribute
);
4234 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4237 for (TargetString
= WString
; *TargetString
!= L
'\0'; TargetString
++) {
4238 if (*TargetString
== CHAR_BACKSPACE
) {
4244 if (BackSpaceCount
== 0) {
4245 TargetString
= WString
;
4247 TargetString
= AllocatePool (sizeof (CHAR16
) * (StrLen (WString
) + BackSpaceCount
+ 1));
4248 StrCpy (TargetString
, WString
);
4251 // return the worst status met
4253 Status
= DevNullTextOutOutputString (Private
, TargetString
);
4254 if (EFI_ERROR (Status
)) {
4255 ReturnStatus
= Status
;
4258 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4260 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4261 Status
= Private
->TextOutList
[Index
].TextOut
->OutputString (
4262 Private
->TextOutList
[Index
].TextOut
,
4265 if (EFI_ERROR (Status
)) {
4266 ReturnStatus
= Status
;
4271 if (BackSpaceCount
> 0) {
4272 FreePool (TargetString
);
4275 return ReturnStatus
;
4280 Verifies that all characters in a Unicode string can be output to the
4283 @param This Protocol instance pointer.
4284 @param String The NULL-terminated Unicode string to be
4285 examined for the output device(s).
4287 @retval EFI_SUCCESS The device(s) are capable of rendering the
4289 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string
4290 cannot be rendered by one or more of the output
4291 devices mapped by the EFI handle.
4296 ConSplitterTextOutTestString (
4297 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4302 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4304 EFI_STATUS ReturnStatus
;
4306 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4309 // return the worst status met
4311 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4312 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4313 Status
= Private
->TextOutList
[Index
].TextOut
->TestString (
4314 Private
->TextOutList
[Index
].TextOut
,
4317 if (EFI_ERROR (Status
)) {
4318 ReturnStatus
= Status
;
4323 // There is no DevNullTextOutTestString () since a Unicode buffer would
4324 // always return EFI_SUCCESS.
4325 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4327 return ReturnStatus
;
4332 Returns information for an available text mode that the output device(s)
4335 @param This Protocol instance pointer.
4336 @param ModeNumber The mode number to return information on.
4337 @param Rows Returns the geometry of the text output device
4338 for the requested ModeNumber.
4340 @retval EFI_SUCCESS The requested mode information was returned.
4341 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4343 @retval EFI_UNSUPPORTED The mode number was not valid.
4348 ConSplitterTextOutQueryMode (
4349 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4350 IN UINTN ModeNumber
,
4355 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4357 INT32
*TextOutModeMap
;
4359 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4362 // Check whether param ModeNumber is valid.
4363 // ModeNumber should be within range 0 ~ MaxMode - 1.
4365 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4366 return EFI_UNSUPPORTED
;
4369 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4370 return EFI_UNSUPPORTED
;
4374 // We get the available mode from mode intersection map if it's available
4376 if (Private
->TextOutModeMap
!= NULL
) {
4377 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4378 CurrentMode
= (UINTN
)(*TextOutModeMap
);
4379 *Columns
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4380 *Rows
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4382 *Columns
= Private
->TextOutQueryData
[ModeNumber
].Columns
;
4383 *Rows
= Private
->TextOutQueryData
[ModeNumber
].Rows
;
4386 if (*Columns
<= 0 && *Rows
<= 0) {
4387 return EFI_UNSUPPORTED
;
4396 Sets the output device(s) to a specified mode.
4398 @param This Protocol instance pointer.
4399 @param ModeNumber The mode number to set.
4401 @retval EFI_SUCCESS The requested text mode was set.
4402 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4404 @retval EFI_UNSUPPORTED The mode number was not valid.
4409 ConSplitterTextOutSetMode (
4410 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4415 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4417 INT32
*TextOutModeMap
;
4418 EFI_STATUS ReturnStatus
;
4420 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4423 // Check whether param ModeNumber is valid.
4424 // ModeNumber should be within range 0 ~ MaxMode - 1.
4426 if ( (ModeNumber
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4427 return EFI_UNSUPPORTED
;
4430 if ((INT32
) ModeNumber
>= This
->Mode
->MaxMode
) {
4431 return EFI_UNSUPPORTED
;
4434 // If the mode is being set to the curent mode, then just clear the screen and return.
4436 if (Private
->TextOutMode
.Mode
== (INT32
) ModeNumber
) {
4437 return ConSplitterTextOutClearScreen (This
);
4440 // return the worst status met
4442 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4443 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4445 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4446 Status
= Private
->TextOutList
[Index
].TextOut
->SetMode (
4447 Private
->TextOutList
[Index
].TextOut
,
4448 TextOutModeMap
[Index
]
4451 // If this console device is based on a GOP or UGA device, then sync up the bitmap from
4452 // the GOP/UGA splitter and reclear the text portion of the display in the new mode.
4454 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
4455 Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4458 if (EFI_ERROR (Status
)) {
4459 ReturnStatus
= Status
;
4464 // The DevNull Console will support any possible mode as it allocates memory
4466 Status
= DevNullTextOutSetMode (Private
, ModeNumber
);
4467 if (EFI_ERROR (Status
)) {
4468 ReturnStatus
= Status
;
4471 return ReturnStatus
;
4476 Sets the background and foreground colors for the OutputString () and
4477 ClearScreen () functions.
4479 @param This Protocol instance pointer.
4480 @param Attribute The attribute to set. Bits 0..3 are the
4481 foreground color, and bits 4..6 are the
4482 background color. All other bits are undefined
4483 and must be zero. The valid Attributes are
4484 defined in this file.
4486 @retval EFI_SUCCESS The attribute was set.
4487 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4489 @retval EFI_UNSUPPORTED The attribute requested is not defined.
4494 ConSplitterTextOutSetAttribute (
4495 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4500 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4502 EFI_STATUS ReturnStatus
;
4504 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4507 // Check whether param Attribute is valid.
4509 if ( (Attribute
> (UINTN
)(((UINT32
)-1)>>1)) ) {
4510 return EFI_UNSUPPORTED
;
4514 // return the worst status met
4516 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4518 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4519 Status
= Private
->TextOutList
[Index
].TextOut
->SetAttribute (
4520 Private
->TextOutList
[Index
].TextOut
,
4523 if (EFI_ERROR (Status
)) {
4524 ReturnStatus
= Status
;
4529 Private
->TextOutMode
.Attribute
= (INT32
) Attribute
;
4531 return ReturnStatus
;
4536 Clears the output device(s) display to the currently selected background
4539 @param This Protocol instance pointer.
4541 @retval EFI_SUCCESS The operation completed successfully.
4542 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4544 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4549 ConSplitterTextOutClearScreen (
4550 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
4554 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4556 EFI_STATUS ReturnStatus
;
4558 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4561 // return the worst status met
4563 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4565 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4566 Status
= Private
->TextOutList
[Index
].TextOut
->ClearScreen (Private
->TextOutList
[Index
].TextOut
);
4567 if (EFI_ERROR (Status
)) {
4568 ReturnStatus
= Status
;
4573 Status
= DevNullTextOutClearScreen (Private
);
4574 if (EFI_ERROR (Status
)) {
4575 ReturnStatus
= Status
;
4578 return ReturnStatus
;
4583 Sets the current coordinates of the cursor position
4585 @param This Protocol instance pointer.
4586 @param Row the position to set the cursor to. Must be
4587 greater than or equal to zero and less than the
4588 number of columns and rows by QueryMode ().
4590 @retval EFI_SUCCESS The operation completed successfully.
4591 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4593 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,
4594 or the cursor position is invalid for the
4600 ConSplitterTextOutSetCursorPosition (
4601 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4607 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4609 EFI_STATUS ReturnStatus
;
4612 INT32
*TextOutModeMap
;
4616 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4617 TextOutModeMap
= NULL
;
4618 ModeNumber
= Private
->TextOutMode
.Mode
;
4621 // Get current MaxColumn and MaxRow from intersection map
4623 if (Private
->TextOutModeMap
!= NULL
) {
4624 TextOutModeMap
= Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
;
4625 CurrentMode
= *TextOutModeMap
;
4627 CurrentMode
= ModeNumber
;
4630 MaxColumn
= Private
->TextOutQueryData
[CurrentMode
].Columns
;
4631 MaxRow
= Private
->TextOutQueryData
[CurrentMode
].Rows
;
4633 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
4634 return EFI_UNSUPPORTED
;
4637 // return the worst status met
4639 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4641 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4642 Status
= Private
->TextOutList
[Index
].TextOut
->SetCursorPosition (
4643 Private
->TextOutList
[Index
].TextOut
,
4647 if (EFI_ERROR (Status
)) {
4648 ReturnStatus
= Status
;
4653 DevNullTextOutSetCursorPosition (Private
, Column
, Row
);
4655 return ReturnStatus
;
4660 Makes the cursor visible or invisible
4662 @param This Protocol instance pointer.
4663 @param Visible If TRUE, the cursor is set to be visible. If
4664 FALSE, the cursor is set to be invisible.
4666 @retval EFI_SUCCESS The operation completed successfully.
4667 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4668 the request, or the device does not support
4669 changing the cursor mode.
4670 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4675 ConSplitterTextOutEnableCursor (
4676 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
4681 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
4683 EFI_STATUS ReturnStatus
;
4685 Private
= TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
4688 // return the worst status met
4690 for (Index
= 0, ReturnStatus
= EFI_SUCCESS
; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
4692 if (Private
->TextOutList
[Index
].TextOutEnabled
) {
4693 Status
= Private
->TextOutList
[Index
].TextOut
->EnableCursor (
4694 Private
->TextOutList
[Index
].TextOut
,
4697 if (EFI_ERROR (Status
)) {
4698 ReturnStatus
= Status
;
4703 DevNullTextOutEnableCursor (Private
, Visible
);
4705 return ReturnStatus
;