1 /** @file
2 Console Splitter Driver. Any Handle that attatched console I/O protocols
3 (Console In device, Console Out device, Console Error device, Simple Pointer
4 protocol, Absolute Pointer protocol) can be bound by this driver.
5
6 So far it works like any other driver by opening a SimpleTextIn and/or
7 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
8 difference is this driver does not layer a protocol on the passed in
9 handle, or construct a child handle like a standard device or bus driver.
10 This driver produces three virtual handles as children, one for console input
11 splitter, one for console output splitter and one for error output splitter.
12 These 3 virtual handles would be installed on gST.
13
14 Each virtual handle, that supports the Console I/O protocol, will be produced
15 in the driver entry point. The virtual handle are added on driver entry and
16 never removed. Such design ensures sytem function well during none console
17 device situation.
18
19 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
20 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
21 This program and the accompanying materials
22 are licensed and made available under the terms and conditions of the BSD License
23 which accompanies this distribution. The full text of the license may be found at
24 http://opensource.org/licenses/bsd-license.php
25
26 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
27 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28
29 **/
30
31 #include "ConSplitter.h"
32
33 //
34 // Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.
35 // default not connect
36 //
37 BOOLEAN mConInIsConnect = FALSE;
38
39 //
40 // Text In Splitter Private Data template
41 //
42 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {
43 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE,
44 (EFI_HANDLE) NULL,
45
46 {
47 ConSplitterTextInReset,
48 ConSplitterTextInReadKeyStroke,
49 (EFI_EVENT) NULL
50 },
51 0,
52 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,
53 0,
54
55 {
56 ConSplitterTextInResetEx,
57 ConSplitterTextInReadKeyStrokeEx,
58 (EFI_EVENT) NULL,
59 ConSplitterTextInSetState,
60 ConSplitterTextInRegisterKeyNotify,
61 ConSplitterTextInUnregisterKeyNotify
62 },
63 0,
64 (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,
65 0,
66 {
67 (LIST_ENTRY *) NULL,
68 (LIST_ENTRY *) NULL
69 },
70 0,
71 FALSE,
72
73 {
74 ConSplitterSimplePointerReset,
75 ConSplitterSimplePointerGetState,
76 (EFI_EVENT) NULL,
77 (EFI_SIMPLE_POINTER_MODE *) NULL
78 },
79 {
80 0x10000,
81 0x10000,
82 0x10000,
83 TRUE,
84 TRUE
85 },
86 0,
87 (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,
88 0,
89
90 {
91 ConSplitterAbsolutePointerReset,
92 ConSplitterAbsolutePointerGetState,
93 (EFI_EVENT) NULL,
94 (EFI_ABSOLUTE_POINTER_MODE *) NULL
95 },
96 {
97 0, // AbsoluteMinX
98 0, // AbsoluteMinY
99 0, // AbsoluteMinZ
100 0x10000, // AbsoluteMaxX
101 0x10000, // AbsoluteMaxY
102 0x10000, // AbsoluteMaxZ
103 0 // Attributes
104 },
105 0,
106 (EFI_ABSOLUTE_POINTER_PROTOCOL **) NULL,
107 0,
108 FALSE,
109
110 FALSE,
111 FALSE
112 };
113
114
115 //
116 // Uga Draw Protocol Private Data template
117 //
118 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL mUgaDrawProtocolTemplate = {
119 ConSplitterUgaDrawGetMode,
120 ConSplitterUgaDrawSetMode,
121 ConSplitterUgaDrawBlt
122 };
123
124 //
125 // Graphics Output Protocol Private Data template
126 //
127 GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL mGraphicsOutputProtocolTemplate = {
128 ConSplitterGraphicsOutputQueryMode,
129 ConSplitterGraphicsOutputSetMode,
130 ConSplitterGraphicsOutputBlt,
131 NULL
132 };
133
134
135 //
136 // Text Out Splitter Private Data template
137 //
138 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
139 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
140 (EFI_HANDLE) NULL,
141 {
142 ConSplitterTextOutReset,
143 ConSplitterTextOutOutputString,
144 ConSplitterTextOutTestString,
145 ConSplitterTextOutQueryMode,
146 ConSplitterTextOutSetMode,
147 ConSplitterTextOutSetAttribute,
148 ConSplitterTextOutClearScreen,
149 ConSplitterTextOutSetCursorPosition,
150 ConSplitterTextOutEnableCursor,
151 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
152 },
153 {
154 1,
155 0,
156 0,
157 0,
158 0,
159 FALSE,
160 },
161
162 {
163 NULL,
164 NULL,
165 NULL
166 },
167 0,
168 0,
169 0,
170 0,
171
172 {
173 NULL,
174 NULL,
175 NULL,
176 NULL
177 },
178 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,
179 0,
180 0,
181
182 0,
183 (TEXT_OUT_AND_GOP_DATA *) NULL,
184 0,
185 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
186 0,
187 (INT32 *) NULL
188 };
189
190 //
191 // Standard Error Text Out Splitter Data Template
192 //
193 GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
194 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
195 (EFI_HANDLE) NULL,
196 {
197 ConSplitterTextOutReset,
198 ConSplitterTextOutOutputString,
199 ConSplitterTextOutTestString,
200 ConSplitterTextOutQueryMode,
201 ConSplitterTextOutSetMode,
202 ConSplitterTextOutSetAttribute,
203 ConSplitterTextOutClearScreen,
204 ConSplitterTextOutSetCursorPosition,
205 ConSplitterTextOutEnableCursor,
206 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
207 },
208 {
209 1,
210 0,
211 0,
212 0,
213 0,
214 FALSE,
215 },
216
217 {
218 NULL,
219 NULL,
220 NULL
221 },
222 0,
223 0,
224 0,
225 0,
226
227 {
228 NULL,
229 NULL,
230 NULL,
231 NULL
232 },
233 (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,
234 0,
235 0,
236
237 0,
238 (TEXT_OUT_AND_GOP_DATA *) NULL,
239 0,
240 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
241 0,
242 (INT32 *) NULL
243 };
244
245 //
246 // Driver binding instance for Console Input Device
247 //
248 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = {
249 ConSplitterConInDriverBindingSupported,
250 ConSplitterConInDriverBindingStart,
251 ConSplitterConInDriverBindingStop,
252 0xa,
253 NULL,
254 NULL
255 };
256
257 //
258 // Driver binding instance for Console Out device
259 //
260 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = {
261 ConSplitterConOutDriverBindingSupported,
262 ConSplitterConOutDriverBindingStart,
263 ConSplitterConOutDriverBindingStop,
264 0xa,
265 NULL,
266 NULL
267 };
268
269 //
270 // Driver binding instance for Standard Error device
271 //
272 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = {
273 ConSplitterStdErrDriverBindingSupported,
274 ConSplitterStdErrDriverBindingStart,
275 ConSplitterStdErrDriverBindingStop,
276 0xa,
277 NULL,
278 NULL
279 };
280
281 //
282 // Driver binding instance for Simple Pointer protocol
283 //
284 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = {
285 ConSplitterSimplePointerDriverBindingSupported,
286 ConSplitterSimplePointerDriverBindingStart,
287 ConSplitterSimplePointerDriverBindingStop,
288 0xa,
289 NULL,
290 NULL
291 };
292
293 //
294 // Driver binding instance for Absolute Pointer protocol
295 //
296 EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding = {
297 ConSplitterAbsolutePointerDriverBindingSupported,
298 ConSplitterAbsolutePointerDriverBindingStart,
299 ConSplitterAbsolutePointerDriverBindingStop,
300 0xa,
301 NULL,
302 NULL
303 };
304
305 /**
306 Key notify for toggle state sync.
307
308 @param KeyData A pointer to a buffer that is filled in with
309 the keystroke information for the key that was
310 pressed.
311
312 @retval EFI_SUCCESS Toggle state sync successfully.
313
314 **/
315 EFI_STATUS
316 EFIAPI
ToggleStateSyncKeyNotify(IN EFI_KEY_DATA * KeyData)317 ToggleStateSyncKeyNotify (
318 IN EFI_KEY_DATA *KeyData
319 )
320 {
321 UINTN Index;
322
323 if (((KeyData->KeyState.KeyToggleState & KEY_STATE_VALID_EXPOSED) == KEY_STATE_VALID_EXPOSED) &&
324 (KeyData->KeyState.KeyToggleState != mConIn.PhysicalKeyToggleState)) {
325 //
326 // There is toggle state change, sync to other console input devices.
327 //
328 for (Index = 0; Index < mConIn.CurrentNumberOfExConsoles; Index++) {
329 mConIn.TextInExList[Index]->SetState (
330 mConIn.TextInExList[Index],
331 &KeyData->KeyState.KeyToggleState
332 );
333 }
334 mConIn.PhysicalKeyToggleState = KeyData->KeyState.KeyToggleState;
335 DEBUG ((EFI_D_INFO, "Current toggle state is 0x%02x\n", mConIn.PhysicalKeyToggleState));
336 }
337
338 return EFI_SUCCESS;
339 }
340
341 /**
342 Initialization for toggle state sync.
343
344 @param Private Text In Splitter pointer.
345
346 **/
347 VOID
ToggleStateSyncInitialization(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private)348 ToggleStateSyncInitialization (
349 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private
350 )
351 {
352 EFI_KEY_DATA KeyData;
353 VOID *NotifyHandle;
354
355 //
356 // Initialize PhysicalKeyToggleState that will be synced to new console
357 // input device to turn on physical TextInEx partial key report for
358 // toggle state sync.
359 //
360 Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;
361
362 //
363 // Initialize VirtualKeyStateExported to let the virtual TextInEx not report
364 // the partial key even though the physical TextInEx turns on the partial
365 // key report. The virtual TextInEx will report the partial key after it is
366 // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
367 //
368 Private->VirtualKeyStateExported = FALSE;
369
370 //
371 // Register key notify for toggle state sync.
372 //
373 KeyData.Key.ScanCode = SCAN_NULL;
374 KeyData.Key.UnicodeChar = CHAR_NULL;
375 KeyData.KeyState.KeyShiftState = 0;
376 KeyData.KeyState.KeyToggleState = 0;
377 Private->TextInEx.RegisterKeyNotify (
378 &Private->TextInEx,
379 &KeyData,
380 ToggleStateSyncKeyNotify,
381 &NotifyHandle
382 );
383 }
384
385 /**
386 Reinitialization for toggle state sync.
387
388 @param Private Text In Splitter pointer.
389
390 **/
391 VOID
ToggleStateSyncReInitialization(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private)392 ToggleStateSyncReInitialization (
393 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private
394 )
395 {
396 UINTN Index;
397
398 //
399 // Reinitialize PhysicalKeyToggleState that will be synced to new console
400 // input device to turn on physical TextInEx partial key report for
401 // toggle state sync.
402 //
403 Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;
404
405 //
406 // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report
407 // the partial key even though the physical TextInEx turns on the partial
408 // key report. The virtual TextInEx will report the partial key after it is
409 // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.
410 //
411 Private->VirtualKeyStateExported = FALSE;
412
413 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
414 Private->TextInExList[Index]->SetState (
415 Private->TextInExList[Index],
416 &Private->PhysicalKeyToggleState
417 );
418 }
419 }
420
421 /**
422 The Entry Point for module ConSplitter. The user code starts with this function.
423
424 Installs driver module protocols and. Creates virtual device handles for ConIn,
425 ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
426 Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
427 Installs Graphics Output protocol and/or UGA Draw protocol if needed.
428
429 @param[in] ImageHandle The firmware allocated handle for the EFI image.
430 @param[in] SystemTable A pointer to the EFI System Table.
431
432 @retval EFI_SUCCESS The entry point is executed successfully.
433 @retval other Some error occurs when executing this entry point.
434
435 **/
436 EFI_STATUS
437 EFIAPI
ConSplitterDriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)438 ConSplitterDriverEntry(
439 IN EFI_HANDLE ImageHandle,
440 IN EFI_SYSTEM_TABLE *SystemTable
441 )
442 {
443 EFI_STATUS Status;
444
445 //
446 // Install driver model protocol(s).
447 //
448 Status = EfiLibInstallDriverBindingComponentName2 (
449 ImageHandle,
450 SystemTable,
451 &gConSplitterConInDriverBinding,
452 ImageHandle,
453 &gConSplitterConInComponentName,
454 &gConSplitterConInComponentName2
455 );
456 ASSERT_EFI_ERROR (Status);
457
458 Status = EfiLibInstallDriverBindingComponentName2 (
459 ImageHandle,
460 SystemTable,
461 &gConSplitterSimplePointerDriverBinding,
462 NULL,
463 &gConSplitterSimplePointerComponentName,
464 &gConSplitterSimplePointerComponentName2
465 );
466 ASSERT_EFI_ERROR (Status);
467
468 Status = EfiLibInstallDriverBindingComponentName2 (
469 ImageHandle,
470 SystemTable,
471 &gConSplitterAbsolutePointerDriverBinding,
472 NULL,
473 &gConSplitterAbsolutePointerComponentName,
474 &gConSplitterAbsolutePointerComponentName2
475 );
476 ASSERT_EFI_ERROR (Status);
477
478 Status = EfiLibInstallDriverBindingComponentName2 (
479 ImageHandle,
480 SystemTable,
481 &gConSplitterConOutDriverBinding,
482 NULL,
483 &gConSplitterConOutComponentName,
484 &gConSplitterConOutComponentName2
485 );
486 ASSERT_EFI_ERROR (Status);
487
488 Status = EfiLibInstallDriverBindingComponentName2 (
489 ImageHandle,
490 SystemTable,
491 &gConSplitterStdErrDriverBinding,
492 NULL,
493 &gConSplitterStdErrComponentName,
494 &gConSplitterStdErrComponentName2
495 );
496 ASSERT_EFI_ERROR (Status);
497
498 //
499 // Either Graphics Output protocol or UGA Draw protocol must be supported.
500 //
501 ASSERT (FeaturePcdGet (PcdConOutGopSupport) ||
502 FeaturePcdGet (PcdConOutUgaSupport));
503
504 //
505 // The driver creates virtual handles for ConIn, ConOut, StdErr.
506 // The virtual handles will always exist even if no console exist in the
507 // system. This is need to support hotplug devices like USB.
508 //
509 //
510 // Create virtual device handle for ConIn Splitter
511 //
512 Status = ConSplitterTextInConstructor (&mConIn);
513 if (!EFI_ERROR (Status)) {
514 Status = gBS->InstallMultipleProtocolInterfaces (
515 &mConIn.VirtualHandle,
516 &gEfiSimpleTextInProtocolGuid,
517 &mConIn.TextIn,
518 &gEfiSimpleTextInputExProtocolGuid,
519 &mConIn.TextInEx,
520 &gEfiSimplePointerProtocolGuid,
521 &mConIn.SimplePointer,
522 &gEfiAbsolutePointerProtocolGuid,
523 &mConIn.AbsolutePointer,
524 NULL
525 );
526 if (!EFI_ERROR (Status)) {
527 //
528 // Update the EFI System Table with new virtual console
529 // and update the pointer to Simple Text Input protocol.
530 //
531 gST->ConsoleInHandle = mConIn.VirtualHandle;
532 gST->ConIn = &mConIn.TextIn;
533 }
534 }
535 //
536 // Create virtual device handle for ConOut Splitter
537 //
538 Status = ConSplitterTextOutConstructor (&mConOut);
539 if (!EFI_ERROR (Status)) {
540 Status = gBS->InstallMultipleProtocolInterfaces (
541 &mConOut.VirtualHandle,
542 &gEfiSimpleTextOutProtocolGuid,
543 &mConOut.TextOut,
544 NULL
545 );
546 if (!EFI_ERROR (Status)) {
547 //
548 // Update the EFI System Table with new virtual console
549 // and Update the pointer to Text Output protocol.
550 //
551 gST->ConsoleOutHandle = mConOut.VirtualHandle;
552 gST->ConOut = &mConOut.TextOut;
553 }
554
555 }
556
557 //
558 // Create virtual device handle for StdErr Splitter
559 //
560 Status = ConSplitterTextOutConstructor (&mStdErr);
561 if (!EFI_ERROR (Status)) {
562 Status = gBS->InstallMultipleProtocolInterfaces (
563 &mStdErr.VirtualHandle,
564 &gEfiSimpleTextOutProtocolGuid,
565 &mStdErr.TextOut,
566 NULL
567 );
568 if (!EFI_ERROR (Status)) {
569 //
570 // Update the EFI System Table with new virtual console
571 // and update the pointer to Text Output protocol.
572 //
573 gST->StandardErrorHandle = mStdErr.VirtualHandle;
574 gST->StdErr = &mStdErr.TextOut;
575 }
576 }
577
578 //
579 // Update the CRC32 in the EFI System Table header
580 //
581 gST->Hdr.CRC32 = 0;
582 gBS->CalculateCrc32 (
583 (UINT8 *) &gST->Hdr,
584 gST->Hdr.HeaderSize,
585 &gST->Hdr.CRC32
586 );
587
588 return EFI_SUCCESS;
589
590 }
591
592 /**
593 Construct console input devices' private data.
594
595 @param ConInPrivate A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA
596 structure.
597
598 @retval EFI_OUT_OF_RESOURCES Out of resources.
599 @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.
600 @retval other Failed to construct private data.
601
602 **/
603 EFI_STATUS
ConSplitterTextInConstructor(TEXT_IN_SPLITTER_PRIVATE_DATA * ConInPrivate)604 ConSplitterTextInConstructor (
605 TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate
606 )
607 {
608 EFI_STATUS Status;
609
610 //
611 // Allocate buffer for Simple Text Input device
612 //
613 Status = ConSplitterGrowBuffer (
614 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),
615 &ConInPrivate->TextInListCount,
616 (VOID **) &ConInPrivate->TextInList
617 );
618 if (EFI_ERROR (Status)) {
619 return EFI_OUT_OF_RESOURCES;
620 }
621
622 //
623 // Create Event to wait for a key
624 //
625 Status = gBS->CreateEvent (
626 EVT_NOTIFY_WAIT,
627 TPL_NOTIFY,
628 ConSplitterTextInWaitForKey,
629 ConInPrivate,
630 &ConInPrivate->TextIn.WaitForKey
631 );
632 ASSERT_EFI_ERROR (Status);
633
634 //
635 // Allocate buffer for Simple Text Input Ex device
636 //
637 Status = ConSplitterGrowBuffer (
638 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),
639 &ConInPrivate->TextInExListCount,
640 (VOID **) &ConInPrivate->TextInExList
641 );
642 if (EFI_ERROR (Status)) {
643 return EFI_OUT_OF_RESOURCES;
644 }
645 //
646 // Create Event to wait for a key Ex
647 //
648 Status = gBS->CreateEvent (
649 EVT_NOTIFY_WAIT,
650 TPL_NOTIFY,
651 ConSplitterTextInWaitForKey,
652 ConInPrivate,
653 &ConInPrivate->TextInEx.WaitForKeyEx
654 );
655 ASSERT_EFI_ERROR (Status);
656
657 InitializeListHead (&ConInPrivate->NotifyList);
658
659 ToggleStateSyncInitialization (ConInPrivate);
660
661 ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;
662 //
663 // Allocate buffer for Absolute Pointer device
664 //
665 Status = ConSplitterGrowBuffer (
666 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),
667 &ConInPrivate->AbsolutePointerListCount,
668 (VOID **) &ConInPrivate->AbsolutePointerList
669 );
670 if (EFI_ERROR (Status)) {
671 return EFI_OUT_OF_RESOURCES;
672 }
673 //
674 // Create Event to wait for device input for Absolute pointer device
675 //
676 Status = gBS->CreateEvent (
677 EVT_NOTIFY_WAIT,
678 TPL_NOTIFY,
679 ConSplitterAbsolutePointerWaitForInput,
680 ConInPrivate,
681 &ConInPrivate->AbsolutePointer.WaitForInput
682 );
683 ASSERT_EFI_ERROR (Status);
684
685 ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;
686 //
687 // Allocate buffer for Simple Pointer device
688 //
689 Status = ConSplitterGrowBuffer (
690 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
691 &ConInPrivate->PointerListCount,
692 (VOID **) &ConInPrivate->PointerList
693 );
694 if (EFI_ERROR (Status)) {
695 return EFI_OUT_OF_RESOURCES;
696 }
697 //
698 // Create Event to wait for device input for Simple pointer device
699 //
700 Status = gBS->CreateEvent (
701 EVT_NOTIFY_WAIT,
702 TPL_NOTIFY,
703 ConSplitterSimplePointerWaitForInput,
704 ConInPrivate,
705 &ConInPrivate->SimplePointer.WaitForInput
706 );
707 ASSERT_EFI_ERROR (Status);
708 //
709 // Create Event to signal ConIn connection request
710 //
711 Status = gBS->CreateEventEx (
712 EVT_NOTIFY_SIGNAL,
713 TPL_CALLBACK,
714 ConSplitterEmptyCallbackFunction,
715 NULL,
716 &gConnectConInEventGuid,
717 &ConInPrivate->ConnectConInEvent
718 );
719
720 return Status;
721 }
722
723 /**
724 Construct console output devices' private data.
725
726 @param ConOutPrivate A pointer to the TEXT_OUT_SPLITTER_PRIVATE_DATA
727 structure.
728
729 @retval EFI_OUT_OF_RESOURCES Out of resources.
730 @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.
731
732 **/
733 EFI_STATUS
ConSplitterTextOutConstructor(TEXT_OUT_SPLITTER_PRIVATE_DATA * ConOutPrivate)734 ConSplitterTextOutConstructor (
735 TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate
736 )
737 {
738 EFI_STATUS Status;
739 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
740
741 //
742 // Copy protocols template
743 //
744 if (FeaturePcdGet (PcdConOutUgaSupport)) {
745 CopyMem (&ConOutPrivate->UgaDraw, &mUgaDrawProtocolTemplate, sizeof (EFI_UGA_DRAW_PROTOCOL));
746 }
747 if (FeaturePcdGet (PcdConOutGopSupport)) {
748 CopyMem (&ConOutPrivate->GraphicsOutput, &mGraphicsOutputProtocolTemplate, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL));
749 }
750
751 //
752 // Initilize console output splitter's private data.
753 //
754 ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;
755
756 //
757 // When new console device is added, the new mode will be set later,
758 // so put current mode back to init state.
759 //
760 ConOutPrivate->TextOutMode.Mode = 0xFF;
761 //
762 // Allocate buffer for Console Out device
763 //
764 Status = ConSplitterGrowBuffer (
765 sizeof (TEXT_OUT_AND_GOP_DATA),
766 &ConOutPrivate->TextOutListCount,
767 (VOID **) &ConOutPrivate->TextOutList
768 );
769 if (EFI_ERROR (Status)) {
770 return EFI_OUT_OF_RESOURCES;
771 }
772 //
773 // Allocate buffer for Text Out query data
774 //
775 Status = ConSplitterGrowBuffer (
776 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
777 &ConOutPrivate->TextOutQueryDataCount,
778 (VOID **) &ConOutPrivate->TextOutQueryData
779 );
780 if (EFI_ERROR (Status)) {
781 return EFI_OUT_OF_RESOURCES;
782 }
783
784 //
785 // Setup the default console to 80 x 25 and mode to 0
786 //
787 ConOutPrivate->TextOutQueryData[0].Columns = 80;
788 ConOutPrivate->TextOutQueryData[0].Rows = 25;
789 TextOutSetMode (ConOutPrivate, 0);
790
791
792 if (FeaturePcdGet (PcdConOutUgaSupport)) {
793 //
794 // Setup the UgaDraw to 800 x 600 x 32 bits per pixel, 60Hz.
795 //
796 ConSplitterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);
797 }
798 if (FeaturePcdGet (PcdConOutGopSupport)) {
799 //
800 // Setup resource for mode information in Graphics Output Protocol interface
801 //
802 if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {
803 return EFI_OUT_OF_RESOURCES;
804 }
805 if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {
806 return EFI_OUT_OF_RESOURCES;
807 }
808 //
809 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
810 // DevNull will be updated to user-defined mode after driver has started.
811 //
812 if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {
813 return EFI_OUT_OF_RESOURCES;
814 }
815 Info = &ConOutPrivate->GraphicsOutputModeBuffer[0];
816 Info->Version = 0;
817 Info->HorizontalResolution = 800;
818 Info->VerticalResolution = 600;
819 Info->PixelFormat = PixelBltOnly;
820 Info->PixelsPerScanLine = 800;
821 CopyMem (ConOutPrivate->GraphicsOutput.Mode->Info, Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
822 ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
823
824 //
825 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
826 // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
827 //
828 ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
829 ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;
830
831 ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;
832 //
833 // Initial current mode to unknown state, and then set to mode 0
834 //
835 ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;
836 ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);
837 }
838
839 return EFI_SUCCESS;
840 }
841
842
843 /**
844 Test to see if the specified protocol could be supported on the specified device.
845
846 @param This Driver Binding protocol pointer.
847 @param ControllerHandle Handle of device to test.
848 @param Guid The specified protocol.
849
850 @retval EFI_SUCCESS The specified protocol is supported on this device.
851 @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtul handle.
852 @retval other Failed to open specified protocol on this device.
853
854 **/
855 EFI_STATUS
ConSplitterSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_GUID * Guid)856 ConSplitterSupported (
857 IN EFI_DRIVER_BINDING_PROTOCOL *This,
858 IN EFI_HANDLE ControllerHandle,
859 IN EFI_GUID *Guid
860 )
861 {
862 EFI_STATUS Status;
863 VOID *Instance;
864
865 //
866 // Make sure the Console Splitter does not attempt to attach to itself
867 //
868 if (ControllerHandle == mConIn.VirtualHandle ||
869 ControllerHandle == mConOut.VirtualHandle ||
870 ControllerHandle == mStdErr.VirtualHandle
871 ) {
872 return EFI_UNSUPPORTED;
873 }
874
875 //
876 // Check to see whether the specific protocol could be opened BY_DRIVER
877 //
878 Status = gBS->OpenProtocol (
879 ControllerHandle,
880 Guid,
881 &Instance,
882 This->DriverBindingHandle,
883 ControllerHandle,
884 EFI_OPEN_PROTOCOL_BY_DRIVER
885 );
886
887 if (EFI_ERROR (Status)) {
888 return Status;
889 }
890
891 gBS->CloseProtocol (
892 ControllerHandle,
893 Guid,
894 This->DriverBindingHandle,
895 ControllerHandle
896 );
897
898 return EFI_SUCCESS;
899 }
900
901 /**
902 Test to see if Console In Device could be supported on the Controller.
903
904 @param This Driver Binding protocol instance pointer.
905 @param ControllerHandle Handle of device to test.
906 @param RemainingDevicePath Optional parameter use to pick a specific child
907 device to start.
908
909 @retval EFI_SUCCESS This driver supports this device.
910 @retval other This driver does not support this device.
911
912 **/
913 EFI_STATUS
914 EFIAPI
ConSplitterConInDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)915 ConSplitterConInDriverBindingSupported (
916 IN EFI_DRIVER_BINDING_PROTOCOL *This,
917 IN EFI_HANDLE ControllerHandle,
918 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
919 )
920 {
921 return ConSplitterSupported (
922 This,
923 ControllerHandle,
924 &gEfiConsoleInDeviceGuid
925 );
926 }
927
928 /**
929 Test to see if Simple Pointer protocol could be supported on the Controller.
930
931 @param This Driver Binding protocol instance pointer.
932 @param ControllerHandle Handle of device to test.
933 @param RemainingDevicePath Optional parameter use to pick a specific child
934 device to start.
935
936 @retval EFI_SUCCESS This driver supports this device.
937 @retval other This driver does not support this device.
938
939 **/
940 EFI_STATUS
941 EFIAPI
ConSplitterSimplePointerDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)942 ConSplitterSimplePointerDriverBindingSupported (
943 IN EFI_DRIVER_BINDING_PROTOCOL *This,
944 IN EFI_HANDLE ControllerHandle,
945 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
946 )
947 {
948 return ConSplitterSupported (
949 This,
950 ControllerHandle,
951 &gEfiSimplePointerProtocolGuid
952 );
953 }
954
955 /**
956 Test to see if Absolute Pointer protocol could be supported on the Controller.
957
958 @param This Driver Binding protocol instance pointer.
959 @param ControllerHandle Handle of device to test.
960 @param RemainingDevicePath Optional parameter use to pick a specific child
961 device to start.
962
963 @retval EFI_SUCCESS This driver supports this device.
964 @retval other This driver does not support this device.
965
966 **/
967 EFI_STATUS
968 EFIAPI
ConSplitterAbsolutePointerDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)969 ConSplitterAbsolutePointerDriverBindingSupported (
970 IN EFI_DRIVER_BINDING_PROTOCOL *This,
971 IN EFI_HANDLE ControllerHandle,
972 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
973 )
974 {
975 return ConSplitterSupported (
976 This,
977 ControllerHandle,
978 &gEfiAbsolutePointerProtocolGuid
979 );
980 }
981
982
983 /**
984 Test to see if Console Out Device could be supported on the Controller.
985
986 @param This Driver Binding protocol instance pointer.
987 @param ControllerHandle Handle of device to test.
988 @param RemainingDevicePath Optional parameter use to pick a specific child
989 device to start.
990
991 @retval EFI_SUCCESS This driver supports this device.
992 @retval other This driver does not support this device.
993
994 **/
995 EFI_STATUS
996 EFIAPI
ConSplitterConOutDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)997 ConSplitterConOutDriverBindingSupported (
998 IN EFI_DRIVER_BINDING_PROTOCOL *This,
999 IN EFI_HANDLE ControllerHandle,
1000 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1001 )
1002 {
1003 return ConSplitterSupported (
1004 This,
1005 ControllerHandle,
1006 &gEfiConsoleOutDeviceGuid
1007 );
1008 }
1009
1010 /**
1011 Test to see if Standard Error Device could be supported on the Controller.
1012
1013 @param This Driver Binding protocol instance pointer.
1014 @param ControllerHandle Handle of device to test.
1015 @param RemainingDevicePath Optional parameter use to pick a specific child
1016 device to start.
1017
1018 @retval EFI_SUCCESS This driver supports this device.
1019 @retval other This driver does not support this device.
1020
1021 **/
1022 EFI_STATUS
1023 EFIAPI
ConSplitterStdErrDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1024 ConSplitterStdErrDriverBindingSupported (
1025 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1026 IN EFI_HANDLE ControllerHandle,
1027 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1028 )
1029 {
1030 return ConSplitterSupported (
1031 This,
1032 ControllerHandle,
1033 &gEfiStandardErrorDeviceGuid
1034 );
1035 }
1036
1037
1038 /**
1039 Start ConSplitter on devcie handle by opening Console Device Guid on device handle
1040 and the console virtual handle. And Get the console interface on controller handle.
1041
1042 @param This Driver Binding protocol instance pointer.
1043 @param ControllerHandle Handle of device.
1044 @param ConSplitterVirtualHandle Console virtual Handle.
1045 @param DeviceGuid The specified Console Device, such as ConInDev,
1046 ConOutDev.
1047 @param InterfaceGuid The specified protocol to be opened.
1048 @param Interface Protocol interface returned.
1049
1050 @retval EFI_SUCCESS This driver supports this device.
1051 @retval other Failed to open the specified Console Device Guid
1052 or specified protocol.
1053
1054 **/
1055 EFI_STATUS
ConSplitterStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE ConSplitterVirtualHandle,IN EFI_GUID * DeviceGuid,IN EFI_GUID * InterfaceGuid,OUT VOID ** Interface)1056 ConSplitterStart (
1057 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1058 IN EFI_HANDLE ControllerHandle,
1059 IN EFI_HANDLE ConSplitterVirtualHandle,
1060 IN EFI_GUID *DeviceGuid,
1061 IN EFI_GUID *InterfaceGuid,
1062 OUT VOID **Interface
1063 )
1064 {
1065 EFI_STATUS Status;
1066 VOID *Instance;
1067
1068 //
1069 // Check to see whether the ControllerHandle has the DeviceGuid on it.
1070 //
1071 Status = gBS->OpenProtocol (
1072 ControllerHandle,
1073 DeviceGuid,
1074 &Instance,
1075 This->DriverBindingHandle,
1076 ControllerHandle,
1077 EFI_OPEN_PROTOCOL_BY_DRIVER
1078 );
1079 if (EFI_ERROR (Status)) {
1080 return Status;
1081 }
1082
1083 //
1084 // Open the Parent Handle for the child.
1085 //
1086 Status = gBS->OpenProtocol (
1087 ControllerHandle,
1088 DeviceGuid,
1089 &Instance,
1090 This->DriverBindingHandle,
1091 ConSplitterVirtualHandle,
1092 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1093 );
1094 if (EFI_ERROR (Status)) {
1095 goto Err;
1096 }
1097
1098 //
1099 // Open InterfaceGuid on the virtul handle.
1100 //
1101 Status = gBS->OpenProtocol (
1102 ControllerHandle,
1103 InterfaceGuid,
1104 Interface,
1105 This->DriverBindingHandle,
1106 ConSplitterVirtualHandle,
1107 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1108 );
1109
1110 if (!EFI_ERROR (Status)) {
1111 return EFI_SUCCESS;
1112 }
1113
1114 //
1115 // close the DeviceGuid on ConSplitter VirtualHandle.
1116 //
1117 gBS->CloseProtocol (
1118 ControllerHandle,
1119 DeviceGuid,
1120 This->DriverBindingHandle,
1121 ConSplitterVirtualHandle
1122 );
1123
1124 Err:
1125 //
1126 // close the DeviceGuid on ControllerHandle.
1127 //
1128 gBS->CloseProtocol (
1129 ControllerHandle,
1130 DeviceGuid,
1131 This->DriverBindingHandle,
1132 ControllerHandle
1133 );
1134
1135 return Status;
1136 }
1137
1138
1139 /**
1140 Start Console In Consplitter on device handle.
1141
1142 @param This Driver Binding protocol instance pointer.
1143 @param ControllerHandle Handle of device to bind driver to.
1144 @param RemainingDevicePath Optional parameter use to pick a specific child
1145 device to start.
1146
1147 @retval EFI_SUCCESS Console In Consplitter is added to ControllerHandle.
1148 @retval other Console In Consplitter does not support this device.
1149
1150 **/
1151 EFI_STATUS
1152 EFIAPI
ConSplitterConInDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1153 ConSplitterConInDriverBindingStart (
1154 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1155 IN EFI_HANDLE ControllerHandle,
1156 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1157 )
1158 {
1159 EFI_STATUS Status;
1160 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;
1161 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;
1162
1163 //
1164 // Start ConSplitter on ControllerHandle, and create the virtual
1165 // agrogated console device on first call Start for a SimpleTextIn handle.
1166 //
1167 Status = ConSplitterStart (
1168 This,
1169 ControllerHandle,
1170 mConIn.VirtualHandle,
1171 &gEfiConsoleInDeviceGuid,
1172 &gEfiSimpleTextInProtocolGuid,
1173 (VOID **) &TextIn
1174 );
1175 if (EFI_ERROR (Status)) {
1176 return Status;
1177 }
1178
1179 //
1180 // Add this device into Text In devices list.
1181 //
1182 Status = ConSplitterTextInAddDevice (&mConIn, TextIn);
1183 if (EFI_ERROR (Status)) {
1184 return Status;
1185 }
1186
1187 Status = gBS->OpenProtocol (
1188 ControllerHandle,
1189 &gEfiSimpleTextInputExProtocolGuid,
1190 (VOID **) &TextInEx,
1191 This->DriverBindingHandle,
1192 mConIn.VirtualHandle,
1193 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1194 );
1195 if (!EFI_ERROR (Status)) {
1196 //
1197 // If Simple Text Input Ex protocol exists,
1198 // add this device into Text In Ex devices list.
1199 //
1200 Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);
1201 }
1202
1203 return Status;
1204 }
1205
1206
1207 /**
1208 Start Simple Pointer Consplitter on device handle.
1209
1210 @param This Driver Binding protocol instance pointer.
1211 @param ControllerHandle Handle of device to bind driver to.
1212 @param RemainingDevicePath Optional parameter use to pick a specific child
1213 device to start.
1214
1215 @retval EFI_SUCCESS Simple Pointer Consplitter is added to ControllerHandle.
1216 @retval other Simple Pointer Consplitter does not support this device.
1217
1218 **/
1219 EFI_STATUS
1220 EFIAPI
ConSplitterSimplePointerDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1221 ConSplitterSimplePointerDriverBindingStart (
1222 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1223 IN EFI_HANDLE ControllerHandle,
1224 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1225 )
1226 {
1227 EFI_STATUS Status;
1228 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
1229
1230 //
1231 // Start ConSplitter on ControllerHandle, and create the virtual
1232 // agrogated console device on first call Start for a SimplePointer handle.
1233 //
1234 Status = ConSplitterStart (
1235 This,
1236 ControllerHandle,
1237 mConIn.VirtualHandle,
1238 &gEfiSimplePointerProtocolGuid,
1239 &gEfiSimplePointerProtocolGuid,
1240 (VOID **) &SimplePointer
1241 );
1242 if (EFI_ERROR (Status)) {
1243 return Status;
1244 }
1245
1246 //
1247 // Add this devcie into Simple Pointer devices list.
1248 //
1249 return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);
1250 }
1251
1252
1253 /**
1254 Start Absolute Pointer Consplitter on device handle.
1255
1256 @param This Driver Binding protocol instance pointer.
1257 @param ControllerHandle Handle of device to bind driver to.
1258 @param RemainingDevicePath Optional parameter use to pick a specific child
1259 device to start.
1260
1261 @retval EFI_SUCCESS Absolute Pointer Consplitter is added to ControllerHandle.
1262 @retval other Absolute Pointer Consplitter does not support this device.
1263
1264 **/
1265 EFI_STATUS
1266 EFIAPI
ConSplitterAbsolutePointerDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1267 ConSplitterAbsolutePointerDriverBindingStart (
1268 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1269 IN EFI_HANDLE ControllerHandle,
1270 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1271 )
1272 {
1273 EFI_STATUS Status;
1274 EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
1275
1276 //
1277 // Start ConSplitter on ControllerHandle, and create the virtual
1278 // agrogated console device on first call Start for a AbsolutePointer handle.
1279 //
1280 Status = ConSplitterStart (
1281 This,
1282 ControllerHandle,
1283 mConIn.VirtualHandle,
1284 &gEfiAbsolutePointerProtocolGuid,
1285 &gEfiAbsolutePointerProtocolGuid,
1286 (VOID **) &AbsolutePointer
1287 );
1288
1289 if (EFI_ERROR (Status)) {
1290 return Status;
1291 }
1292
1293 //
1294 // Add this devcie into Absolute Pointer devices list.
1295 //
1296 return ConSplitterAbsolutePointerAddDevice (&mConIn, AbsolutePointer);
1297 }
1298
1299
1300 /**
1301 Start Console Out Consplitter on device handle.
1302
1303 @param This Driver Binding protocol instance pointer.
1304 @param ControllerHandle Handle of device to bind driver to.
1305 @param RemainingDevicePath Optional parameter use to pick a specific child
1306 device to start.
1307
1308 @retval EFI_SUCCESS Console Out Consplitter is added to ControllerHandle.
1309 @retval other Console Out Consplitter does not support this device.
1310
1311 **/
1312 EFI_STATUS
1313 EFIAPI
ConSplitterConOutDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1314 ConSplitterConOutDriverBindingStart (
1315 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1316 IN EFI_HANDLE ControllerHandle,
1317 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1318 )
1319 {
1320 EFI_STATUS Status;
1321 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1322 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1323 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
1324 UINTN SizeOfInfo;
1325 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
1326
1327 //
1328 // Start ConSplitter on ControllerHandle, and create the virtual
1329 // agrogated console device on first call Start for a ConsoleOut handle.
1330 //
1331 Status = ConSplitterStart (
1332 This,
1333 ControllerHandle,
1334 mConOut.VirtualHandle,
1335 &gEfiConsoleOutDeviceGuid,
1336 &gEfiSimpleTextOutProtocolGuid,
1337 (VOID **) &TextOut
1338 );
1339 if (EFI_ERROR (Status)) {
1340 return Status;
1341 }
1342
1343 GraphicsOutput = NULL;
1344 UgaDraw = NULL;
1345 //
1346 // Try to Open Graphics Output protocol
1347 //
1348 Status = gBS->OpenProtocol (
1349 ControllerHandle,
1350 &gEfiGraphicsOutputProtocolGuid,
1351 (VOID **) &GraphicsOutput,
1352 This->DriverBindingHandle,
1353 mConOut.VirtualHandle,
1354 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1355 );
1356
1357 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
1358 //
1359 // Open UGA DRAW protocol
1360 //
1361 gBS->OpenProtocol (
1362 ControllerHandle,
1363 &gEfiUgaDrawProtocolGuid,
1364 (VOID **) &UgaDraw,
1365 This->DriverBindingHandle,
1366 mConOut.VirtualHandle,
1367 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1368 );
1369 }
1370
1371 //
1372 // When new console device is added, the new mode will be set later,
1373 // so put current mode back to init state.
1374 //
1375 mConOut.TextOutMode.Mode = 0xFF;
1376
1377 //
1378 // If both ConOut and StdErr incorporate the same Text Out device,
1379 // their MaxMode and QueryData should be the intersection of both.
1380 //
1381 Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);
1382 ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
1383
1384 if (FeaturePcdGet (PcdConOutUgaSupport)) {
1385 //
1386 // Get the UGA mode data of ConOut from the current mode
1387 //
1388 if (GraphicsOutput != NULL) {
1389 Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
1390 if (EFI_ERROR (Status)) {
1391 return Status;
1392 }
1393 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
1394
1395 mConOut.UgaHorizontalResolution = Info->HorizontalResolution;
1396 mConOut.UgaVerticalResolution = Info->VerticalResolution;
1397 mConOut.UgaColorDepth = 32;
1398 mConOut.UgaRefreshRate = 60;
1399
1400 FreePool (Info);
1401
1402 } else if (UgaDraw != NULL) {
1403 Status = UgaDraw->GetMode (
1404 UgaDraw,
1405 &mConOut.UgaHorizontalResolution,
1406 &mConOut.UgaVerticalResolution,
1407 &mConOut.UgaColorDepth,
1408 &mConOut.UgaRefreshRate
1409 );
1410 }
1411 }
1412
1413 return Status;
1414 }
1415
1416
1417 /**
1418 Start Standard Error Consplitter on device handle.
1419
1420 @param This Driver Binding protocol instance pointer.
1421 @param ControllerHandle Handle of device to bind driver to.
1422 @param RemainingDevicePath Optional parameter use to pick a specific child
1423 device to start.
1424
1425 @retval EFI_SUCCESS Standard Error Consplitter is added to ControllerHandle.
1426 @retval other Standard Error Consplitter does not support this device.
1427
1428 **/
1429 EFI_STATUS
1430 EFIAPI
ConSplitterStdErrDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1431 ConSplitterStdErrDriverBindingStart (
1432 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1433 IN EFI_HANDLE ControllerHandle,
1434 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1435 )
1436 {
1437 EFI_STATUS Status;
1438 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1439
1440 //
1441 // Start ConSplitter on ControllerHandle, and create the virtual
1442 // agrogated console device on first call Start for a StandardError handle.
1443 //
1444 Status = ConSplitterStart (
1445 This,
1446 ControllerHandle,
1447 mStdErr.VirtualHandle,
1448 &gEfiStandardErrorDeviceGuid,
1449 &gEfiSimpleTextOutProtocolGuid,
1450 (VOID **) &TextOut
1451 );
1452 if (EFI_ERROR (Status)) {
1453 return Status;
1454 }
1455
1456 //
1457 // When new console device is added, the new mode will be set later,
1458 // so put current mode back to init state.
1459 //
1460 mStdErr.TextOutMode.Mode = 0xFF;
1461
1462 //
1463 // If both ConOut and StdErr incorporate the same Text Out device,
1464 // their MaxMode and QueryData should be the intersection of both.
1465 //
1466 Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
1467 ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
1468 if (EFI_ERROR (Status)) {
1469 return Status;
1470 }
1471
1472 return Status;
1473 }
1474
1475
1476 /**
1477 Stop ConSplitter on device handle by closing Console Device Guid on device handle
1478 and the console virtual handle.
1479
1480 @param This Protocol instance pointer.
1481 @param ControllerHandle Handle of device.
1482 @param ConSplitterVirtualHandle Console virtual Handle.
1483 @param DeviceGuid The specified Console Device, such as ConInDev,
1484 ConOutDev.
1485 @param InterfaceGuid The specified protocol to be opened.
1486 @param Interface Protocol interface returned.
1487
1488 @retval EFI_SUCCESS Stop ConSplitter on ControllerHandle successfully.
1489 @retval other Failed to Stop ConSplitter on ControllerHandle.
1490
1491 **/
1492 EFI_STATUS
ConSplitterStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE ConSplitterVirtualHandle,IN EFI_GUID * DeviceGuid,IN EFI_GUID * InterfaceGuid,IN VOID ** Interface)1493 ConSplitterStop (
1494 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1495 IN EFI_HANDLE ControllerHandle,
1496 IN EFI_HANDLE ConSplitterVirtualHandle,
1497 IN EFI_GUID *DeviceGuid,
1498 IN EFI_GUID *InterfaceGuid,
1499 IN VOID **Interface
1500 )
1501 {
1502 EFI_STATUS Status;
1503
1504 Status = gBS->OpenProtocol (
1505 ControllerHandle,
1506 InterfaceGuid,
1507 Interface,
1508 This->DriverBindingHandle,
1509 ControllerHandle,
1510 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1511 );
1512 if (EFI_ERROR (Status)) {
1513 return Status;
1514 }
1515 //
1516 // close the protocol refered.
1517 //
1518 gBS->CloseProtocol (
1519 ControllerHandle,
1520 DeviceGuid,
1521 This->DriverBindingHandle,
1522 ConSplitterVirtualHandle
1523 );
1524
1525 gBS->CloseProtocol (
1526 ControllerHandle,
1527 DeviceGuid,
1528 This->DriverBindingHandle,
1529 ControllerHandle
1530 );
1531
1532 return EFI_SUCCESS;
1533 }
1534
1535
1536 /**
1537 Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID.
1538
1539 @param This Driver Binding protocol instance pointer.
1540 @param ControllerHandle Handle of device to stop driver on
1541 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1542 children is zero stop the entire bus driver.
1543 @param ChildHandleBuffer List of Child Handles to Stop.
1544
1545 @retval EFI_SUCCESS This driver is removed ControllerHandle
1546 @retval other This driver was not removed from this device
1547
1548 **/
1549 EFI_STATUS
1550 EFIAPI
ConSplitterConInDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1551 ConSplitterConInDriverBindingStop (
1552 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1553 IN EFI_HANDLE ControllerHandle,
1554 IN UINTN NumberOfChildren,
1555 IN EFI_HANDLE *ChildHandleBuffer
1556 )
1557 {
1558 EFI_STATUS Status;
1559 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;
1560 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;
1561
1562 if (NumberOfChildren == 0) {
1563 return EFI_SUCCESS;
1564 }
1565
1566 Status = gBS->OpenProtocol (
1567 ControllerHandle,
1568 &gEfiSimpleTextInputExProtocolGuid,
1569 (VOID **) &TextInEx,
1570 This->DriverBindingHandle,
1571 ControllerHandle,
1572 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1573 );
1574 if (!EFI_ERROR (Status)) {
1575 //
1576 // If Simple Text Input Ex protocol exists,
1577 // remove device from Text Input Ex devices list.
1578 //
1579 Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);
1580 if (EFI_ERROR (Status)) {
1581 return Status;
1582 }
1583 }
1584
1585 //
1586 // Close Simple Text In protocol on controller handle and virtual handle.
1587 //
1588 Status = ConSplitterStop (
1589 This,
1590 ControllerHandle,
1591 mConIn.VirtualHandle,
1592 &gEfiConsoleInDeviceGuid,
1593 &gEfiSimpleTextInProtocolGuid,
1594 (VOID **) &TextIn
1595 );
1596 if (EFI_ERROR (Status)) {
1597 return Status;
1598 }
1599
1600 //
1601 // Remove device from Text Input devices list.
1602 //
1603 return ConSplitterTextInDeleteDevice (&mConIn, TextIn);
1604 }
1605
1606
1607 /**
1608 Stop Simple Pointer protocol ConSplitter on ControllerHandle by closing
1609 Simple Pointer protocol.
1610
1611 @param This Driver Binding protocol instance pointer.
1612 @param ControllerHandle Handle of device to stop driver on
1613 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1614 children is zero stop the entire bus driver.
1615 @param ChildHandleBuffer List of Child Handles to Stop.
1616
1617 @retval EFI_SUCCESS This driver is removed ControllerHandle
1618 @retval other This driver was not removed from this device
1619
1620 **/
1621 EFI_STATUS
1622 EFIAPI
ConSplitterSimplePointerDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1623 ConSplitterSimplePointerDriverBindingStop (
1624 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1625 IN EFI_HANDLE ControllerHandle,
1626 IN UINTN NumberOfChildren,
1627 IN EFI_HANDLE *ChildHandleBuffer
1628 )
1629 {
1630 EFI_STATUS Status;
1631 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
1632
1633 if (NumberOfChildren == 0) {
1634 return EFI_SUCCESS;
1635 }
1636
1637 //
1638 // Close Simple Pointer protocol on controller handle and virtual handle.
1639 //
1640 Status = ConSplitterStop (
1641 This,
1642 ControllerHandle,
1643 mConIn.VirtualHandle,
1644 &gEfiSimplePointerProtocolGuid,
1645 &gEfiSimplePointerProtocolGuid,
1646 (VOID **) &SimplePointer
1647 );
1648 if (EFI_ERROR (Status)) {
1649 return Status;
1650 }
1651
1652 //
1653 // Remove this device from Simple Pointer device list.
1654 //
1655 return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);
1656 }
1657
1658
1659 /**
1660 Stop Absolute Pointer protocol ConSplitter on ControllerHandle by closing
1661 Absolute Pointer protocol.
1662
1663 @param This Driver Binding protocol instance pointer.
1664 @param ControllerHandle Handle of device to stop driver on
1665 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1666 children is zero stop the entire bus driver.
1667 @param ChildHandleBuffer List of Child Handles to Stop.
1668
1669 @retval EFI_SUCCESS This driver is removed ControllerHandle
1670 @retval other This driver was not removed from this device
1671
1672 **/
1673 EFI_STATUS
1674 EFIAPI
ConSplitterAbsolutePointerDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1675 ConSplitterAbsolutePointerDriverBindingStop (
1676 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1677 IN EFI_HANDLE ControllerHandle,
1678 IN UINTN NumberOfChildren,
1679 IN EFI_HANDLE *ChildHandleBuffer
1680 )
1681 {
1682 EFI_STATUS Status;
1683 EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
1684
1685 if (NumberOfChildren == 0) {
1686 return EFI_SUCCESS;
1687 }
1688
1689 //
1690 // Close Absolute Pointer protocol on controller handle and virtual handle.
1691 //
1692 Status = ConSplitterStop (
1693 This,
1694 ControllerHandle,
1695 mConIn.VirtualHandle,
1696 &gEfiAbsolutePointerProtocolGuid,
1697 &gEfiAbsolutePointerProtocolGuid,
1698 (VOID **) &AbsolutePointer
1699 );
1700 if (EFI_ERROR (Status)) {
1701 return Status;
1702 }
1703
1704 //
1705 // Remove this device from Absolute Pointer device list.
1706 //
1707 return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer);
1708 }
1709
1710
1711 /**
1712 Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID.
1713
1714 @param This Driver Binding protocol instance pointer.
1715 @param ControllerHandle Handle of device to stop driver on
1716 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1717 children is zero stop the entire bus driver.
1718 @param ChildHandleBuffer List of Child Handles to Stop.
1719
1720 @retval EFI_SUCCESS This driver is removed ControllerHandle
1721 @retval other This driver was not removed from this device
1722
1723 **/
1724 EFI_STATUS
1725 EFIAPI
ConSplitterConOutDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1726 ConSplitterConOutDriverBindingStop (
1727 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1728 IN EFI_HANDLE ControllerHandle,
1729 IN UINTN NumberOfChildren,
1730 IN EFI_HANDLE *ChildHandleBuffer
1731 )
1732 {
1733 EFI_STATUS Status;
1734 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1735
1736 if (NumberOfChildren == 0) {
1737 return EFI_SUCCESS;
1738 }
1739
1740 //
1741 // Close Absolute Pointer protocol on controller handle and virtual handle.
1742 //
1743 Status = ConSplitterStop (
1744 This,
1745 ControllerHandle,
1746 mConOut.VirtualHandle,
1747 &gEfiConsoleOutDeviceGuid,
1748 &gEfiSimpleTextOutProtocolGuid,
1749 (VOID **) &TextOut
1750 );
1751 if (EFI_ERROR (Status)) {
1752 return Status;
1753 }
1754
1755 //
1756 // Remove this device from Text Out device list.
1757 //
1758 return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);
1759 }
1760
1761
1762 /**
1763 Stop Standard Error ConSplitter on ControllerHandle by closing Standard Error GUID.
1764
1765 @param This Driver Binding protocol instance pointer.
1766 @param ControllerHandle Handle of device to stop driver on
1767 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1768 children is zero stop the entire bus driver.
1769 @param ChildHandleBuffer List of Child Handles to Stop.
1770
1771 @retval EFI_SUCCESS This driver is removed ControllerHandle
1772 @retval other This driver was not removed from this device
1773
1774 **/
1775 EFI_STATUS
1776 EFIAPI
ConSplitterStdErrDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1777 ConSplitterStdErrDriverBindingStop (
1778 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1779 IN EFI_HANDLE ControllerHandle,
1780 IN UINTN NumberOfChildren,
1781 IN EFI_HANDLE *ChildHandleBuffer
1782 )
1783 {
1784 EFI_STATUS Status;
1785 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1786
1787 if (NumberOfChildren == 0) {
1788 return EFI_SUCCESS;
1789 }
1790
1791 //
1792 // Close Standard Error Device on controller handle and virtual handle.
1793 //
1794 Status = ConSplitterStop (
1795 This,
1796 ControllerHandle,
1797 mStdErr.VirtualHandle,
1798 &gEfiStandardErrorDeviceGuid,
1799 &gEfiSimpleTextOutProtocolGuid,
1800 (VOID **) &TextOut
1801 );
1802 if (EFI_ERROR (Status)) {
1803 return Status;
1804 }
1805 //
1806 // Delete this console error out device's data structures.
1807 //
1808 return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
1809 }
1810
1811
1812 /**
1813 Take the passed in Buffer of size ElementSize and grow the buffer
1814 by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.
1815 Copy the current data in Buffer to the new version of Buffer and
1816 free the old version of buffer.
1817
1818 @param ElementSize Size of element in array.
1819 @param Count Current number of elements in array.
1820 @param Buffer Bigger version of passed in Buffer with all the
1821 data.
1822
1823 @retval EFI_SUCCESS Buffer size has grown.
1824 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1825
1826 **/
1827 EFI_STATUS
ConSplitterGrowBuffer(IN UINTN ElementSize,IN OUT UINTN * Count,IN OUT VOID ** Buffer)1828 ConSplitterGrowBuffer (
1829 IN UINTN ElementSize,
1830 IN OUT UINTN *Count,
1831 IN OUT VOID **Buffer
1832 )
1833 {
1834 VOID *Ptr;
1835
1836 //
1837 // grow the buffer to new buffer size,
1838 // copy the old buffer's content to the new-size buffer,
1839 // then free the old buffer.
1840 //
1841 Ptr = ReallocatePool (
1842 ElementSize * (*Count),
1843 ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT),
1844 *Buffer
1845 );
1846 if (Ptr == NULL) {
1847 return EFI_OUT_OF_RESOURCES;
1848 }
1849 *Count += CONSOLE_SPLITTER_ALLOC_UNIT;
1850 *Buffer = Ptr;
1851 return EFI_SUCCESS;
1852 }
1853
1854
1855 /**
1856 Add Text Input Device in Consplitter Text Input list.
1857
1858 @param Private Text In Splitter pointer.
1859 @param TextIn Simple Text Input protocol pointer.
1860
1861 @retval EFI_SUCCESS Text Input Device added successfully.
1862 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1863
1864 **/
1865 EFI_STATUS
ConSplitterTextInAddDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * TextIn)1866 ConSplitterTextInAddDevice (
1867 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1868 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn
1869 )
1870 {
1871 EFI_STATUS Status;
1872
1873 //
1874 // If the Text In List is full, enlarge it by calling ConSplitterGrowBuffer().
1875 //
1876 if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {
1877 Status = ConSplitterGrowBuffer (
1878 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),
1879 &Private->TextInListCount,
1880 (VOID **) &Private->TextInList
1881 );
1882 if (EFI_ERROR (Status)) {
1883 return EFI_OUT_OF_RESOURCES;
1884 }
1885 }
1886 //
1887 // Add the new text-in device data structure into the Text In List.
1888 //
1889 Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;
1890 Private->CurrentNumberOfConsoles++;
1891
1892 //
1893 // Extra CheckEvent added to reduce the double CheckEvent().
1894 //
1895 gBS->CheckEvent (TextIn->WaitForKey);
1896
1897 return EFI_SUCCESS;
1898 }
1899
1900
1901 /**
1902 Remove Text Input Device from Consplitter Text Input list.
1903
1904 @param Private Text In Splitter pointer.
1905 @param TextIn Simple Text protocol pointer.
1906
1907 @retval EFI_SUCCESS Simple Text Device removed successfully.
1908 @retval EFI_NOT_FOUND No Simple Text Device found.
1909
1910 **/
1911 EFI_STATUS
ConSplitterTextInDeleteDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * TextIn)1912 ConSplitterTextInDeleteDevice (
1913 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1914 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn
1915 )
1916 {
1917 UINTN Index;
1918 //
1919 // Remove the specified text-in device data structure from the Text In List,
1920 // and rearrange the remaining data structures in the Text In List.
1921 //
1922 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
1923 if (Private->TextInList[Index] == TextIn) {
1924 for (; Index < Private->CurrentNumberOfConsoles - 1; Index++) {
1925 Private->TextInList[Index] = Private->TextInList[Index + 1];
1926 }
1927
1928 Private->CurrentNumberOfConsoles--;
1929 return EFI_SUCCESS;
1930 }
1931 }
1932
1933 return EFI_NOT_FOUND;
1934 }
1935
1936 /**
1937 Add Text Input Ex Device in Consplitter Text Input Ex list.
1938
1939 @param Private Text In Splitter pointer.
1940 @param TextInEx Simple Text Input Ex Input protocol pointer.
1941
1942 @retval EFI_SUCCESS Text Input Ex Device added successfully.
1943 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1944
1945 **/
1946 EFI_STATUS
ConSplitterTextInExAddDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * TextInEx)1947 ConSplitterTextInExAddDevice (
1948 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1949 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
1950 )
1951 {
1952 EFI_STATUS Status;
1953 LIST_ENTRY *Link;
1954 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
1955 UINTN TextInExListCount;
1956
1957 //
1958 // Enlarge the NotifyHandleList and the TextInExList
1959 //
1960 if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {
1961 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
1962 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1963 TextInExListCount = Private->TextInExListCount;
1964
1965 Status = ConSplitterGrowBuffer (
1966 sizeof (EFI_HANDLE),
1967 &TextInExListCount,
1968 (VOID **) &CurrentNotify->NotifyHandleList
1969 );
1970 if (EFI_ERROR (Status)) {
1971 return EFI_OUT_OF_RESOURCES;
1972 }
1973 }
1974 Status = ConSplitterGrowBuffer (
1975 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),
1976 &Private->TextInExListCount,
1977 (VOID **) &Private->TextInExList
1978 );
1979 if (EFI_ERROR (Status)) {
1980 return EFI_OUT_OF_RESOURCES;
1981 }
1982 }
1983
1984 //
1985 // Register the key notify in the new text-in device
1986 //
1987 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
1988 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1989 Status = TextInEx->RegisterKeyNotify (
1990 TextInEx,
1991 &CurrentNotify->KeyData,
1992 CurrentNotify->KeyNotificationFn,
1993 &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
1994 );
1995 if (EFI_ERROR (Status)) {
1996 for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) {
1997 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1998 TextInEx->UnregisterKeyNotify (
1999 TextInEx,
2000 CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
2001 );
2002 }
2003 return Status;
2004 }
2005 }
2006
2007 //
2008 // Add the new text-in device data structure into the Text Input Ex List.
2009 //
2010 Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;
2011 Private->CurrentNumberOfExConsoles++;
2012
2013 //
2014 // Sync current toggle state to this new console input device.
2015 //
2016 TextInEx->SetState (TextInEx, &Private->PhysicalKeyToggleState);
2017
2018 //
2019 // Extra CheckEvent added to reduce the double CheckEvent().
2020 //
2021 gBS->CheckEvent (TextInEx->WaitForKeyEx);
2022
2023 return EFI_SUCCESS;
2024 }
2025
2026 /**
2027 Remove Text Ex Device from Consplitter Text Input Ex list.
2028
2029 @param Private Text In Splitter pointer.
2030 @param TextInEx Simple Text Ex protocol pointer.
2031
2032 @retval EFI_SUCCESS Simple Text Input Ex Device removed successfully.
2033 @retval EFI_NOT_FOUND No Simple Text Input Ex Device found.
2034
2035 **/
2036 EFI_STATUS
ConSplitterTextInExDeleteDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * TextInEx)2037 ConSplitterTextInExDeleteDevice (
2038 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2039 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
2040 )
2041 {
2042 UINTN Index;
2043 //
2044 // Remove the specified text-in device data structure from the Text Input Ex List,
2045 // and rearrange the remaining data structures in the Text In List.
2046 //
2047 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
2048 if (Private->TextInExList[Index] == TextInEx) {
2049 for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {
2050 Private->TextInExList[Index] = Private->TextInExList[Index + 1];
2051 }
2052
2053 Private->CurrentNumberOfExConsoles--;
2054 return EFI_SUCCESS;
2055 }
2056 }
2057
2058 return EFI_NOT_FOUND;
2059 }
2060
2061
2062 /**
2063 Add Simple Pointer Device in Consplitter Simple Pointer list.
2064
2065 @param Private Text In Splitter pointer.
2066 @param SimplePointer Simple Pointer protocol pointer.
2067
2068 @retval EFI_SUCCESS Simple Pointer Device added successfully.
2069 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2070
2071 **/
2072 EFI_STATUS
ConSplitterSimplePointerAddDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_POINTER_PROTOCOL * SimplePointer)2073 ConSplitterSimplePointerAddDevice (
2074 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2075 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
2076 )
2077 {
2078 EFI_STATUS Status;
2079
2080 //
2081 // If the Simple Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
2082 //
2083 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {
2084 Status = ConSplitterGrowBuffer (
2085 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
2086 &Private->PointerListCount,
2087 (VOID **) &Private->PointerList
2088 );
2089 if (EFI_ERROR (Status)) {
2090 return EFI_OUT_OF_RESOURCES;
2091 }
2092 }
2093 //
2094 // Add the new text-in device data structure into the Simple Pointer List.
2095 //
2096 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;
2097 Private->CurrentNumberOfPointers++;
2098
2099 return EFI_SUCCESS;
2100 }
2101
2102
2103 /**
2104 Remove Simple Pointer Device from Consplitter Simple Pointer list.
2105
2106 @param Private Text In Splitter pointer.
2107 @param SimplePointer Simple Pointer protocol pointer.
2108
2109 @retval EFI_SUCCESS Simple Pointer Device removed successfully.
2110 @retval EFI_NOT_FOUND No Simple Pointer Device found.
2111
2112 **/
2113 EFI_STATUS
ConSplitterSimplePointerDeleteDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_POINTER_PROTOCOL * SimplePointer)2114 ConSplitterSimplePointerDeleteDevice (
2115 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2116 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
2117 )
2118 {
2119 UINTN Index;
2120 //
2121 // Remove the specified text-in device data structure from the Simple Pointer List,
2122 // and rearrange the remaining data structures in the Text In List.
2123 //
2124 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
2125 if (Private->PointerList[Index] == SimplePointer) {
2126 for (; Index < Private->CurrentNumberOfPointers - 1; Index++) {
2127 Private->PointerList[Index] = Private->PointerList[Index + 1];
2128 }
2129
2130 Private->CurrentNumberOfPointers--;
2131 return EFI_SUCCESS;
2132 }
2133 }
2134
2135 return EFI_NOT_FOUND;
2136 }
2137
2138
2139 /**
2140 Add Absolute Pointer Device in Consplitter Absolute Pointer list.
2141
2142 @param Private Text In Splitter pointer.
2143 @param AbsolutePointer Absolute Pointer protocol pointer.
2144
2145 @retval EFI_SUCCESS Absolute Pointer Device added successfully.
2146 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2147
2148 **/
2149 EFI_STATUS
ConSplitterAbsolutePointerAddDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_ABSOLUTE_POINTER_PROTOCOL * AbsolutePointer)2150 ConSplitterAbsolutePointerAddDevice (
2151 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2152 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer
2153 )
2154 {
2155 EFI_STATUS Status;
2156
2157 //
2158 // If the Absolute Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
2159 //
2160 if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {
2161 Status = ConSplitterGrowBuffer (
2162 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),
2163 &Private->AbsolutePointerListCount,
2164 (VOID **) &Private->AbsolutePointerList
2165 );
2166 if (EFI_ERROR (Status)) {
2167 return EFI_OUT_OF_RESOURCES;
2168 }
2169 }
2170 //
2171 // Add the new text-in device data structure into the Absolute Pointer List.
2172 //
2173 Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;
2174 Private->CurrentNumberOfAbsolutePointers++;
2175
2176 return EFI_SUCCESS;
2177 }
2178
2179
2180 /**
2181 Remove Absolute Pointer Device from Consplitter Absolute Pointer list.
2182
2183 @param Private Text In Splitter pointer.
2184 @param AbsolutePointer Absolute Pointer protocol pointer.
2185
2186 @retval EFI_SUCCESS Absolute Pointer Device removed successfully.
2187 @retval EFI_NOT_FOUND No Absolute Pointer Device found.
2188
2189 **/
2190 EFI_STATUS
ConSplitterAbsolutePointerDeleteDevice(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN EFI_ABSOLUTE_POINTER_PROTOCOL * AbsolutePointer)2191 ConSplitterAbsolutePointerDeleteDevice (
2192 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2193 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer
2194 )
2195 {
2196 UINTN Index;
2197 //
2198 // Remove the specified text-in device data structure from the Absolute Pointer List,
2199 // and rearrange the remaining data structures from the Absolute Pointer List.
2200 //
2201 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
2202 if (Private->AbsolutePointerList[Index] == AbsolutePointer) {
2203 for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {
2204 Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];
2205 }
2206
2207 Private->CurrentNumberOfAbsolutePointers--;
2208 return EFI_SUCCESS;
2209 }
2210 }
2211
2212 return EFI_NOT_FOUND;
2213 }
2214
2215 /**
2216 Reallocate Text Out mode map.
2217
2218 Allocate new buffer and copy original buffer into the new buffer.
2219
2220 @param Private Consplitter Text Out pointer.
2221
2222 @retval EFI_SUCCESS Buffer size has grown
2223 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2224
2225 **/
2226 EFI_STATUS
ConSplitterGrowMapTable(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private)2227 ConSplitterGrowMapTable (
2228 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
2229 )
2230 {
2231 UINTN Size;
2232 UINTN NewSize;
2233 UINTN TotalSize;
2234 INT32 *TextOutModeMap;
2235 INT32 *OldTextOutModeMap;
2236 INT32 *SrcAddress;
2237 INT32 Index;
2238 UINTN OldStepSize;
2239 UINTN NewStepSize;
2240
2241 NewSize = Private->TextOutListCount * sizeof (INT32);
2242 OldTextOutModeMap = Private->TextOutModeMap;
2243 TotalSize = NewSize * (Private->TextOutQueryDataCount);
2244
2245 //
2246 // Allocate new buffer for Text Out List.
2247 //
2248 TextOutModeMap = AllocatePool (TotalSize);
2249 if (TextOutModeMap == NULL) {
2250 return EFI_OUT_OF_RESOURCES;
2251 }
2252
2253 SetMem (TextOutModeMap, TotalSize, 0xFF);
2254 Private->TextOutModeMap = TextOutModeMap;
2255
2256 //
2257 // If TextOutList has been enlarged, need to realloc the mode map table
2258 // The mode map table is regarded as a two dimension array.
2259 //
2260 // Old New
2261 // 0 ---------> TextOutListCount ----> TextOutListCount
2262 // | -------------------------------------------
2263 // | | | |
2264 // | | | |
2265 // | | | |
2266 // | | | |
2267 // | | | |
2268 // \/ | | |
2269 // -------------------------------------------
2270 // QueryDataCount
2271 //
2272 if (OldTextOutModeMap != NULL) {
2273
2274 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);
2275 Index = 0;
2276 SrcAddress = OldTextOutModeMap;
2277 NewStepSize = NewSize / sizeof(INT32);
2278 // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap
2279 // is not NULL, it indicates that the original TextOutModeMap is not enough
2280 // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns.
2281 //
2282 OldStepSize = NewStepSize - CONSOLE_SPLITTER_ALLOC_UNIT;
2283
2284 //
2285 // Copy the old data to the new one
2286 //
2287 while (Index < Private->TextOutMode.MaxMode) {
2288 CopyMem (TextOutModeMap, SrcAddress, Size);
2289 //
2290 // Go to next row of new TextOutModeMap.
2291 //
2292 TextOutModeMap += NewStepSize;
2293 //
2294 // Go to next row of old TextOutModeMap.
2295 //
2296 SrcAddress += OldStepSize;
2297 Index++;
2298 }
2299 //
2300 // Free the old buffer
2301 //
2302 FreePool (OldTextOutModeMap);
2303 }
2304
2305 return EFI_SUCCESS;
2306 }
2307
2308
2309 /**
2310 Add new device's output mode to console splitter's mode list.
2311
2312 @param Private Text Out Splitter pointer
2313 @param TextOut Simple Text Output protocol pointer.
2314
2315 @retval EFI_SUCCESS Device added successfully.
2316 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2317
2318 **/
2319 EFI_STATUS
ConSplitterAddOutputMode(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * TextOut)2320 ConSplitterAddOutputMode (
2321 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2322 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
2323 )
2324 {
2325 EFI_STATUS Status;
2326 INT32 MaxMode;
2327 INT32 Mode;
2328 UINTN Index;
2329
2330 MaxMode = TextOut->Mode->MaxMode;
2331 Private->TextOutMode.MaxMode = MaxMode;
2332
2333 //
2334 // Grow the buffer if query data buffer is not large enough to
2335 // hold all the mode supported by the first console.
2336 //
2337 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {
2338 Status = ConSplitterGrowBuffer (
2339 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
2340 &Private->TextOutQueryDataCount,
2341 (VOID **) &Private->TextOutQueryData
2342 );
2343 if (EFI_ERROR (Status)) {
2344 return EFI_OUT_OF_RESOURCES;
2345 }
2346 }
2347 //
2348 // Allocate buffer for the output mode map
2349 //
2350 Status = ConSplitterGrowMapTable (Private);
2351 if (EFI_ERROR (Status)) {
2352 return EFI_OUT_OF_RESOURCES;
2353 }
2354 //
2355 // As the first textout device, directly add the mode in to QueryData
2356 // and at the same time record the mapping between QueryData and TextOut.
2357 //
2358 Mode = 0;
2359 Index = 0;
2360 while (Mode < MaxMode) {
2361 Status = TextOut->QueryMode (
2362 TextOut,
2363 Mode,
2364 &Private->TextOutQueryData[Mode].Columns,
2365 &Private->TextOutQueryData[Mode].Rows
2366 );
2367 //
2368 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2369 // is clear to 0x0.
2370 //
2371 if ((EFI_ERROR(Status)) && (Mode == 1)) {
2372 Private->TextOutQueryData[Mode].Columns = 0;
2373 Private->TextOutQueryData[Mode].Rows = 0;
2374 }
2375 Private->TextOutModeMap[Index] = Mode;
2376 Mode++;
2377 Index += Private->TextOutListCount;
2378 }
2379
2380 return EFI_SUCCESS;
2381 }
2382
2383 /**
2384 Reconstruct TextOutModeMap to get intersection of modes.
2385
2386 This routine reconstruct TextOutModeMap to get the intersection
2387 of modes for all console out devices. Because EFI/UEFI spec require
2388 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2389 intersection for mode 0 and mode 1.
2390
2391 @param TextOutModeMap Current text out mode map, begin with the mode 80x25
2392 @param NewlyAddedMap New text out mode map, begin with the mode 80x25
2393 @param MapStepSize Mode step size for one console device
2394 @param NewMapStepSize New Mode step size for one console device
2395 @param MaxMode IN: Current max text mode, OUT: Updated max text mode.
2396 @param CurrentMode IN: Current text mode, OUT: Updated current text mode.
2397
2398 **/
2399 VOID
ConSplitterGetIntersection(IN INT32 * TextOutModeMap,IN INT32 * NewlyAddedMap,IN UINTN MapStepSize,IN UINTN NewMapStepSize,IN OUT INT32 * MaxMode,IN OUT INT32 * CurrentMode)2400 ConSplitterGetIntersection (
2401 IN INT32 *TextOutModeMap,
2402 IN INT32 *NewlyAddedMap,
2403 IN UINTN MapStepSize,
2404 IN UINTN NewMapStepSize,
2405 IN OUT INT32 *MaxMode,
2406 IN OUT INT32 *CurrentMode
2407 )
2408 {
2409 INT32 Index;
2410 INT32 *CurrentMapEntry;
2411 INT32 *NextMapEntry;
2412 INT32 *NewMapEntry;
2413 INT32 CurrentMaxMode;
2414 INT32 Mode;
2415
2416 //
2417 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2418 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2419 // for mode 0 and mode 1, mode number starts from 2.
2420 //
2421 Index = 2;
2422 CurrentMapEntry = &TextOutModeMap[MapStepSize * 2];
2423 NextMapEntry = CurrentMapEntry;
2424 NewMapEntry = &NewlyAddedMap[NewMapStepSize * 2];
2425
2426 CurrentMaxMode = *MaxMode;
2427 Mode = *CurrentMode;
2428
2429 while (Index < CurrentMaxMode) {
2430 if (*NewMapEntry == -1) {
2431 //
2432 // This mode is not supported any more. Remove it. Special care
2433 // must be taken as this remove will also affect current mode;
2434 //
2435 if (Index == *CurrentMode) {
2436 Mode = -1;
2437 } else if (Index < *CurrentMode) {
2438 Mode--;
2439 }
2440 (*MaxMode)--;
2441 } else {
2442 if (CurrentMapEntry != NextMapEntry) {
2443 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));
2444 }
2445
2446 NextMapEntry += MapStepSize;
2447 }
2448
2449 CurrentMapEntry += MapStepSize;
2450 NewMapEntry += NewMapStepSize;
2451 Index++;
2452 }
2453
2454 *CurrentMode = Mode;
2455
2456 return ;
2457 }
2458
2459 /**
2460 Sync the device's output mode to console splitter's mode list.
2461
2462 @param Private Text Out Splitter pointer.
2463 @param TextOut Simple Text Output protocol pointer.
2464
2465 **/
2466 VOID
ConSplitterSyncOutputMode(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * TextOut)2467 ConSplitterSyncOutputMode (
2468 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2469 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
2470 )
2471 {
2472 INT32 CurrentMaxMode;
2473 INT32 Mode;
2474 INT32 Index;
2475 INT32 *TextOutModeMap;
2476 INT32 *MapTable;
2477 INT32 QueryMode;
2478 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;
2479 UINTN Rows;
2480 UINTN Columns;
2481 UINTN StepSize;
2482 EFI_STATUS Status;
2483
2484 //
2485 // Must make sure that current mode won't change even if mode number changes
2486 //
2487 CurrentMaxMode = Private->TextOutMode.MaxMode;
2488 TextOutModeMap = Private->TextOutModeMap;
2489 StepSize = Private->TextOutListCount;
2490 TextOutQueryData = Private->TextOutQueryData;
2491
2492 //
2493 // Query all the mode that the newly added TextOut supports
2494 //
2495 Mode = 0;
2496 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;
2497 while (Mode < TextOut->Mode->MaxMode) {
2498 Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);
2499
2500 if (EFI_ERROR(Status)) {
2501 if (Mode == 1) {
2502 //
2503 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2504 // is clear to 0x0.
2505 //
2506 MapTable[StepSize] = Mode;
2507 TextOutQueryData[Mode].Columns = 0;
2508 TextOutQueryData[Mode].Rows = 0;
2509 }
2510 Mode++;
2511 continue;
2512 }
2513 //
2514 // Search the intersection map and QueryData database to see if they intersects
2515 //
2516 Index = 0;
2517 while (Index < CurrentMaxMode) {
2518 QueryMode = *(TextOutModeMap + Index * StepSize);
2519 if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) {
2520 MapTable[Index * StepSize] = Mode;
2521 break;
2522 }
2523 Index++;
2524 }
2525 Mode++;
2526 }
2527 //
2528 // Now search the TextOutModeMap table to find the intersection of supported
2529 // mode between ConSplitter and the newly added device.
2530 //
2531 ConSplitterGetIntersection (
2532 TextOutModeMap,
2533 MapTable,
2534 StepSize,
2535 StepSize,
2536 &Private->TextOutMode.MaxMode,
2537 &Private->TextOutMode.Mode
2538 );
2539
2540 return ;
2541 }
2542
2543
2544 /**
2545 Sync output device between ConOut and StdErr output.
2546
2547 @retval EFI_SUCCESS Sync implemented successfully.
2548 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2549
2550 **/
2551 EFI_STATUS
ConSplitterGetIntersectionBetweenConOutAndStrErr(VOID)2552 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2553 VOID
2554 )
2555 {
2556 UINTN ConOutNumOfConsoles;
2557 UINTN StdErrNumOfConsoles;
2558 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;
2559 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;
2560 UINTN Indexi;
2561 UINTN Indexj;
2562 UINTN ConOutRows;
2563 UINTN ConOutColumns;
2564 UINTN StdErrRows;
2565 UINTN StdErrColumns;
2566 INT32 ConOutMaxMode;
2567 INT32 StdErrMaxMode;
2568 INT32 ConOutMode;
2569 INT32 StdErrMode;
2570 INT32 Mode;
2571 INT32 Index;
2572 INT32 *ConOutModeMap;
2573 INT32 *StdErrModeMap;
2574 INT32 *ConOutMapTable;
2575 INT32 *StdErrMapTable;
2576 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;
2577 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;
2578 UINTN ConOutStepSize;
2579 UINTN StdErrStepSize;
2580 BOOLEAN FoundTheSameTextOut;
2581 UINTN ConOutMapTableSize;
2582 UINTN StdErrMapTableSize;
2583
2584 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;
2585 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;
2586 ConOutTextOutList = mConOut.TextOutList;
2587 StdErrTextOutList = mStdErr.TextOutList;
2588
2589 Indexi = 0;
2590 FoundTheSameTextOut = FALSE;
2591 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {
2592 Indexj = 0;
2593 while (Indexj < StdErrNumOfConsoles) {
2594 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {
2595 FoundTheSameTextOut = TRUE;
2596 break;
2597 }
2598
2599 Indexj++;
2600 StdErrTextOutList++;
2601 }
2602
2603 Indexi++;
2604 ConOutTextOutList++;
2605 }
2606
2607 if (!FoundTheSameTextOut) {
2608 return EFI_SUCCESS;
2609 }
2610 //
2611 // Must make sure that current mode won't change even if mode number changes
2612 //
2613 ConOutMaxMode = mConOut.TextOutMode.MaxMode;
2614 ConOutModeMap = mConOut.TextOutModeMap;
2615 ConOutStepSize = mConOut.TextOutListCount;
2616 ConOutQueryData = mConOut.TextOutQueryData;
2617
2618 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;
2619 StdErrModeMap = mStdErr.TextOutModeMap;
2620 StdErrStepSize = mStdErr.TextOutListCount;
2621 StdErrQueryData = mStdErr.TextOutQueryData;
2622
2623 //
2624 // Allocate the map table and set the map table's index to -1.
2625 //
2626 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);
2627 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);
2628 if (ConOutMapTable == NULL) {
2629 return EFI_OUT_OF_RESOURCES;
2630 }
2631
2632 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);
2633
2634 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);
2635 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);
2636 if (StdErrMapTable == NULL) {
2637 return EFI_OUT_OF_RESOURCES;
2638 }
2639
2640 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);
2641
2642 //
2643 // Find the intersection of the two set of modes. If they actually intersect, the
2644 // corresponding entry in the map table is set to 1.
2645 //
2646 Mode = 0;
2647 while (Mode < ConOutMaxMode) {
2648 //
2649 // Search the intersection map and QueryData database to see if they intersect
2650 //
2651 Index = 0;
2652 ConOutMode = *(ConOutModeMap + Mode * ConOutStepSize);
2653 ConOutRows = ConOutQueryData[ConOutMode].Rows;
2654 ConOutColumns = ConOutQueryData[ConOutMode].Columns;
2655 while (Index < StdErrMaxMode) {
2656 StdErrMode = *(StdErrModeMap + Index * StdErrStepSize);
2657 StdErrRows = StdErrQueryData[StdErrMode].Rows;
2658 StdErrColumns = StdErrQueryData[StdErrMode].Columns;
2659 if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) {
2660 ConOutMapTable[Mode] = 1;
2661 StdErrMapTable[Index] = 1;
2662 break;
2663 }
2664
2665 Index++;
2666 }
2667
2668 Mode++;
2669 }
2670 //
2671 // Now search the TextOutModeMap table to find the intersection of supported
2672 // mode between ConSplitter and the newly added device.
2673 //
2674 ConSplitterGetIntersection (
2675 ConOutModeMap,
2676 ConOutMapTable,
2677 mConOut.TextOutListCount,
2678 1,
2679 &(mConOut.TextOutMode.MaxMode),
2680 &(mConOut.TextOutMode.Mode)
2681 );
2682
2683 if (mConOut.TextOutMode.Mode < 0) {
2684 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);
2685 }
2686
2687 ConSplitterGetIntersection (
2688 StdErrModeMap,
2689 StdErrMapTable,
2690 mStdErr.TextOutListCount,
2691 1,
2692 &(mStdErr.TextOutMode.MaxMode),
2693 &(mStdErr.TextOutMode.Mode)
2694 );
2695
2696 if (mStdErr.TextOutMode.Mode < 0) {
2697 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);
2698 }
2699
2700 FreePool (ConOutMapTable);
2701 FreePool (StdErrMapTable);
2702
2703 return EFI_SUCCESS;
2704 }
2705
2706
2707 /**
2708 Add Grahpics Output modes into Consplitter Text Out list.
2709
2710 @param Private Text Out Splitter pointer.
2711 @param GraphicsOutput Graphics Output protocol pointer.
2712 @param UgaDraw UGA Draw protocol pointer.
2713
2714 @retval EFI_SUCCESS Output mode added successfully.
2715 @retval other Failed to add output mode.
2716
2717 **/
2718 EFI_STATUS
ConSplitterAddGraphicsOutputMode(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN EFI_GRAPHICS_OUTPUT_PROTOCOL * GraphicsOutput,IN EFI_UGA_DRAW_PROTOCOL * UgaDraw)2719 ConSplitterAddGraphicsOutputMode (
2720 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2721 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2722 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2723 )
2724 {
2725 EFI_STATUS Status;
2726 UINTN Index;
2727 UINTN CurrentIndex;
2728 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
2729 UINTN SizeOfInfo;
2730 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
2731 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;
2732 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;
2733 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;
2734 UINTN NumberIndex;
2735 BOOLEAN Match;
2736 BOOLEAN AlreadyExist;
2737 UINT32 UgaHorizontalResolution;
2738 UINT32 UgaVerticalResolution;
2739 UINT32 UgaColorDepth;
2740 UINT32 UgaRefreshRate;
2741
2742 ASSERT (GraphicsOutput != NULL || UgaDraw != NULL);
2743
2744 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;
2745
2746 Index = 0;
2747 CurrentIndex = 0;
2748 Status = EFI_SUCCESS;
2749
2750 if (Private->CurrentNumberOfUgaDraw != 0) {
2751 //
2752 // If any UGA device has already been added, then there is no need to
2753 // calculate intersection of display mode of different GOP/UGA device,
2754 // since only one display mode will be exported (i.e. user-defined mode)
2755 //
2756 goto Done;
2757 }
2758
2759 if (GraphicsOutput != NULL) {
2760 if (Private->CurrentNumberOfGraphicsOutput == 0) {
2761 //
2762 // This is the first Graphics Output device added
2763 //
2764 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;
2765 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;
2766 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);
2767 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;
2768 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;
2769 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;
2770
2771 //
2772 // Allocate resource for the private mode buffer
2773 //
2774 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * GraphicsOutput->Mode->MaxMode);
2775 if (ModeBuffer == NULL) {
2776 return EFI_OUT_OF_RESOURCES;
2777 }
2778 FreePool (Private->GraphicsOutputModeBuffer);
2779 Private->GraphicsOutputModeBuffer = ModeBuffer;
2780
2781 //
2782 // Store all supported display modes to the private mode buffer
2783 //
2784 Mode = ModeBuffer;
2785 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {
2786 //
2787 // The Info buffer would be allocated by callee
2788 //
2789 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);
2790 if (EFI_ERROR (Status)) {
2791 return Status;
2792 }
2793 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2794 CopyMem (Mode, Info, SizeOfInfo);
2795 Mode++;
2796 FreePool (Info);
2797 }
2798 } else {
2799 //
2800 // Check intersection of display mode
2801 //
2802 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);
2803 if (ModeBuffer == NULL) {
2804 return EFI_OUT_OF_RESOURCES;
2805 }
2806
2807 MatchedMode = ModeBuffer;
2808 Mode = &Private->GraphicsOutputModeBuffer[0];
2809 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2810 Match = FALSE;
2811
2812 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {
2813 //
2814 // The Info buffer would be allocated by callee
2815 //
2816 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
2817 if (EFI_ERROR (Status)) {
2818 return Status;
2819 }
2820 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
2821 (Info->VerticalResolution == Mode->VerticalResolution)) {
2822 //
2823 // If GOP device supports one mode in current mode buffer,
2824 // it will be added into matched mode buffer
2825 //
2826 Match = TRUE;
2827 FreePool (Info);
2828 break;
2829 }
2830 FreePool (Info);
2831 }
2832
2833 if (Match) {
2834 AlreadyExist = FALSE;
2835
2836 //
2837 // Check if GOP mode has been in the mode buffer, ModeBuffer = MatchedMode at begin.
2838 //
2839 for (Info = ModeBuffer; Info < MatchedMode; Info++) {
2840 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
2841 (Info->VerticalResolution == Mode->VerticalResolution)) {
2842 AlreadyExist = TRUE;
2843 break;
2844 }
2845 }
2846
2847 if (!AlreadyExist) {
2848 CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2849
2850 //
2851 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2852 //
2853 MatchedMode->Version = 0;
2854 MatchedMode->PixelFormat = PixelBltOnly;
2855 ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
2856
2857 MatchedMode++;
2858 }
2859 }
2860
2861 Mode++;
2862 }
2863
2864 //
2865 // Drop the old mode buffer, assign it to a new one
2866 //
2867 FreePool (Private->GraphicsOutputModeBuffer);
2868 Private->GraphicsOutputModeBuffer = ModeBuffer;
2869
2870 //
2871 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2872 //
2873 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2874 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
2875 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
2876 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2877 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
2878 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2879 }
2880
2881 //
2882 // Graphics console driver can ensure the same mode for all GOP devices
2883 //
2884 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2885 Mode = &Private->GraphicsOutputModeBuffer[Index];
2886 if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) &&
2887 (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) {
2888 CurrentIndex = Index;
2889 break;
2890 }
2891 }
2892 if (Index >= CurrentGraphicsOutputMode->MaxMode) {
2893 //
2894 // if user defined mode is not found, set to default mode 800x600
2895 //
2896 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2897 Mode = &Private->GraphicsOutputModeBuffer[Index];
2898 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {
2899 CurrentIndex = Index;
2900 break;
2901 }
2902 }
2903 }
2904 } else if (UgaDraw != NULL) {
2905 //
2906 // Graphics console driver can ensure the same mode for all GOP devices
2907 // so we can get the current mode from this video device
2908 //
2909 UgaDraw->GetMode (
2910 UgaDraw,
2911 &UgaHorizontalResolution,
2912 &UgaVerticalResolution,
2913 &UgaColorDepth,
2914 &UgaRefreshRate
2915 );
2916
2917 CurrentGraphicsOutputMode->MaxMode = 1;
2918 Info = CurrentGraphicsOutputMode->Info;
2919 Info->Version = 0;
2920 Info->HorizontalResolution = UgaHorizontalResolution;
2921 Info->VerticalResolution = UgaVerticalResolution;
2922 Info->PixelFormat = PixelBltOnly;
2923 Info->PixelsPerScanLine = UgaHorizontalResolution;
2924 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2925 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
2926 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2927
2928 //
2929 // Update the private mode buffer
2930 //
2931 CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2932
2933 //
2934 // Only mode 0 is available to be set
2935 //
2936 CurrentIndex = 0;
2937 }
2938
2939 Done:
2940
2941 if (GraphicsOutput != NULL) {
2942 Private->CurrentNumberOfGraphicsOutput++;
2943 }
2944 if (UgaDraw != NULL) {
2945 Private->CurrentNumberOfUgaDraw++;
2946 }
2947
2948 //
2949 // Force GraphicsOutput mode to be set,
2950 //
2951
2952 Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];
2953 if ((GraphicsOutput != NULL) &&
2954 (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&
2955 (Mode->VerticalResolution == CurrentGraphicsOutputMode->Info->VerticalResolution)) {
2956 CurrentGraphicsOutputMode->Mode = (UINT32) CurrentIndex;
2957 if ((Mode->HorizontalResolution != GraphicsOutput->Mode->Info->HorizontalResolution) ||
2958 (Mode->VerticalResolution != GraphicsOutput->Mode->Info->VerticalResolution)) {
2959 //
2960 // If all existing video device has been set to common mode, only set new GOP device to
2961 // the common mode
2962 //
2963 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
2964 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
2965 if (EFI_ERROR (Status)) {
2966 return Status;
2967 }
2968 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
2969 FreePool (Info);
2970 break;
2971 }
2972 FreePool (Info);
2973 }
2974 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
2975 }
2976 } else {
2977 //
2978 // Current mode number may need update now, so set it to an invalid mode number
2979 //
2980 CurrentGraphicsOutputMode->Mode = 0xffff;
2981 //
2982 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2983 //
2984 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);
2985 if (EFI_ERROR(Status)) {
2986 //
2987 // If user defined mode is not valid for display device, set to the default mode 800x600.
2988 //
2989 (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;
2990 (Private->GraphicsOutputModeBuffer[0]).VerticalResolution = 600;
2991 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);
2992 }
2993 }
2994
2995 return Status;
2996 }
2997
2998 /**
2999 Set the current console out mode.
3000
3001 This routine will get the current console mode information (column, row)
3002 from ConsoleOutMode variable and set it; if the variable does not exist,
3003 set to user defined console mode.
3004
3005 @param Private Consplitter Text Out pointer.
3006
3007 **/
3008 VOID
ConsplitterSetConsoleOutMode(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private)3009 ConsplitterSetConsoleOutMode (
3010 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
3011 )
3012 {
3013 UINTN Col;
3014 UINTN Row;
3015 UINTN Mode;
3016 UINTN PreferMode;
3017 UINTN BaseMode;
3018 UINTN MaxMode;
3019 EFI_STATUS Status;
3020 CONSOLE_OUT_MODE ModeInfo;
3021 CONSOLE_OUT_MODE MaxModeInfo;
3022 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
3023
3024 PreferMode = 0xFF;
3025 BaseMode = 0xFF;
3026 TextOut = &Private->TextOut;
3027 MaxMode = (UINTN) (TextOut->Mode->MaxMode);
3028
3029 MaxModeInfo.Column = 0;
3030 MaxModeInfo.Row = 0;
3031 ModeInfo.Column = PcdGet32 (PcdConOutColumn);
3032 ModeInfo.Row = PcdGet32 (PcdConOutRow);
3033
3034 //
3035 // To find the prefer mode and basic mode from Text Out mode list
3036 //
3037 for (Mode = 0; Mode < MaxMode; Mode++) {
3038 Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);
3039 if (!EFI_ERROR(Status)) {
3040 if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {
3041 //
3042 // Use user defined column and row
3043 //
3044 if (Col == ModeInfo.Column && Row == ModeInfo.Row) {
3045 PreferMode = Mode;
3046 }
3047 } else {
3048 //
3049 // If user sets PcdConOutColumn or PcdConOutRow to 0,
3050 // find and set the highest text mode.
3051 //
3052 if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {
3053 MaxModeInfo.Column = Col;
3054 MaxModeInfo.Row = Row;
3055 PreferMode = Mode;
3056 }
3057 }
3058 if (Col == 80 && Row == 25) {
3059 BaseMode = Mode;
3060 }
3061 }
3062 }
3063
3064 //
3065 // Set prefer mode to Text Out devices.
3066 //
3067 Status = TextOut->SetMode (TextOut, PreferMode);
3068 if (EFI_ERROR(Status)) {
3069 //
3070 // if current mode setting is failed, default 80x25 mode will be set.
3071 //
3072 Status = TextOut->SetMode (TextOut, BaseMode);
3073 ASSERT(!EFI_ERROR(Status));
3074
3075 Status = PcdSet32S (PcdConOutColumn, 80);
3076 ASSERT(!EFI_ERROR(Status));
3077 Status = PcdSet32S (PcdConOutRow, 25);
3078 ASSERT(!EFI_ERROR(Status));
3079 }
3080
3081 return ;
3082 }
3083
3084
3085 /**
3086 Add Text Output Device in Consplitter Text Output list.
3087
3088 @param Private Text Out Splitter pointer.
3089 @param TextOut Simple Text Output protocol pointer.
3090 @param GraphicsOutput Graphics Output protocol pointer.
3091 @param UgaDraw UGA Draw protocol pointer.
3092
3093 @retval EFI_SUCCESS Text Output Device added successfully.
3094 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
3095
3096 **/
3097 EFI_STATUS
ConSplitterTextOutAddDevice(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * TextOut,IN EFI_GRAPHICS_OUTPUT_PROTOCOL * GraphicsOutput,IN EFI_UGA_DRAW_PROTOCOL * UgaDraw)3098 ConSplitterTextOutAddDevice (
3099 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
3100 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
3101 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
3102 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
3103 )
3104 {
3105 EFI_STATUS Status;
3106 UINTN CurrentNumOfConsoles;
3107 INT32 MaxMode;
3108 UINT32 UgaHorizontalResolution;
3109 UINT32 UgaVerticalResolution;
3110 UINT32 UgaColorDepth;
3111 UINT32 UgaRefreshRate;
3112 TEXT_OUT_AND_GOP_DATA *TextAndGop;
3113 UINTN SizeOfInfo;
3114 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
3115 EFI_STATUS DeviceStatus;
3116
3117 Status = EFI_SUCCESS;
3118 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
3119
3120 //
3121 // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().
3122 //
3123 while (CurrentNumOfConsoles >= Private->TextOutListCount) {
3124 Status = ConSplitterGrowBuffer (
3125 sizeof (TEXT_OUT_AND_GOP_DATA),
3126 &Private->TextOutListCount,
3127 (VOID **) &Private->TextOutList
3128 );
3129 if (EFI_ERROR (Status)) {
3130 return EFI_OUT_OF_RESOURCES;
3131 }
3132 //
3133 // Also need to reallocate the TextOutModeMap table
3134 //
3135 Status = ConSplitterGrowMapTable (Private);
3136 if (EFI_ERROR (Status)) {
3137 return EFI_OUT_OF_RESOURCES;
3138 }
3139 }
3140
3141 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];
3142
3143 TextAndGop->TextOut = TextOut;
3144 TextAndGop->GraphicsOutput = GraphicsOutput;
3145 TextAndGop->UgaDraw = UgaDraw;
3146
3147 if (CurrentNumOfConsoles == 0) {
3148 //
3149 // Add the first device's output mode to console splitter's mode list
3150 //
3151 Status = ConSplitterAddOutputMode (Private, TextOut);
3152 } else {
3153 ConSplitterSyncOutputMode (Private, TextOut);
3154 }
3155
3156 Private->CurrentNumberOfConsoles++;
3157
3158 //
3159 // Scan both TextOutList, for the intersection TextOut device
3160 // maybe both ConOut and StdErr incorporate the same Text Out
3161 // device in them, thus the output of both should be synced.
3162 //
3163 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3164
3165 MaxMode = Private->TextOutMode.MaxMode;
3166 ASSERT (MaxMode >= 1);
3167
3168 DeviceStatus = EFI_DEVICE_ERROR;
3169 Status = EFI_DEVICE_ERROR;
3170
3171 //
3172 // This device display mode will be added into Graphics Ouput modes.
3173 //
3174 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {
3175 DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
3176 }
3177
3178 if (FeaturePcdGet (PcdConOutUgaSupport)) {
3179 //
3180 // If UGA is produced by Consplitter
3181 //
3182 if (GraphicsOutput != NULL) {
3183 Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
3184 if (EFI_ERROR (Status)) {
3185 return Status;
3186 }
3187 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
3188
3189 UgaHorizontalResolution = Info->HorizontalResolution;
3190 UgaVerticalResolution = Info->VerticalResolution;
3191
3192 FreePool (Info);
3193
3194 } else if (UgaDraw != NULL) {
3195 Status = UgaDraw->GetMode (
3196 UgaDraw,
3197 &UgaHorizontalResolution,
3198 &UgaVerticalResolution,
3199 &UgaColorDepth,
3200 &UgaRefreshRate
3201 );
3202 if (!EFI_ERROR (Status) && EFI_ERROR (DeviceStatus)) {
3203 //
3204 // if GetMode is successfully and UGA device hasn't been set, set it
3205 //
3206 Status = ConSplitterUgaDrawSetMode (
3207 &Private->UgaDraw,
3208 UgaHorizontalResolution,
3209 UgaVerticalResolution,
3210 UgaColorDepth,
3211 UgaRefreshRate
3212 );
3213 }
3214 //
3215 // If GetMode/SetMode is failed, set to 800x600 mode
3216 //
3217 if(EFI_ERROR (Status)) {
3218 Status = ConSplitterUgaDrawSetMode (
3219 &Private->UgaDraw,
3220 800,
3221 600,
3222 32,
3223 60
3224 );
3225 }
3226 }
3227 }
3228
3229 if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) &&
3230 ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1)) {
3231 if (!FeaturePcdGet (PcdConOutGopSupport)) {
3232 //
3233 // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed
3234 // on the virtual handle.
3235 //
3236 Status = gBS->InstallMultipleProtocolInterfaces (
3237 &mConOut.VirtualHandle,
3238 &gEfiUgaDrawProtocolGuid,
3239 &mConOut.UgaDraw,
3240 NULL
3241 );
3242 } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
3243 //
3244 // If UGA Draw protocol not supported, Graphics Output Protocol is installed
3245 // on virtual handle.
3246 //
3247 Status = gBS->InstallMultipleProtocolInterfaces (
3248 &mConOut.VirtualHandle,
3249 &gEfiGraphicsOutputProtocolGuid,
3250 &mConOut.GraphicsOutput,
3251 NULL
3252 );
3253 } else {
3254 //
3255 // Boot Graphics Output protocol and UGA Draw protocol are supported,
3256 // both they will be installed on virtual handle.
3257 //
3258 Status = gBS->InstallMultipleProtocolInterfaces (
3259 &mConOut.VirtualHandle,
3260 &gEfiGraphicsOutputProtocolGuid,
3261 &mConOut.GraphicsOutput,
3262 &gEfiUgaDrawProtocolGuid,
3263 &mConOut.UgaDraw,
3264 NULL
3265 );
3266 }
3267 }
3268
3269 //
3270 // After adding new console device, all existing console devices should be
3271 // synced to the current shared mode.
3272 //
3273 ConsplitterSetConsoleOutMode (Private);
3274
3275 return Status;
3276 }
3277
3278
3279 /**
3280 Remove Text Out Device in Consplitter Text Out list.
3281
3282 @param Private Text Out Splitter pointer.
3283 @param TextOut Simple Text Output Pointer protocol pointer.
3284
3285 @retval EFI_SUCCESS Text Out Device removed successfully.
3286 @retval EFI_NOT_FOUND No Text Out Device found.
3287
3288 **/
3289 EFI_STATUS
ConSplitterTextOutDeleteDevice(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * TextOut)3290 ConSplitterTextOutDeleteDevice (
3291 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
3292 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
3293 )
3294 {
3295 INT32 Index;
3296 UINTN CurrentNumOfConsoles;
3297 TEXT_OUT_AND_GOP_DATA *TextOutList;
3298 EFI_STATUS Status;
3299
3300 //
3301 // Remove the specified text-out device data structure from the Text out List,
3302 // and rearrange the remaining data structures in the Text out List.
3303 //
3304 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
3305 Index = (INT32) CurrentNumOfConsoles - 1;
3306 TextOutList = Private->TextOutList;
3307 while (Index >= 0) {
3308 if (TextOutList->TextOut == TextOut) {
3309 if (TextOutList->UgaDraw != NULL) {
3310 Private->CurrentNumberOfUgaDraw--;
3311 }
3312 if (TextOutList->GraphicsOutput != NULL) {
3313 Private->CurrentNumberOfGraphicsOutput--;
3314 }
3315 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
3316 CurrentNumOfConsoles--;
3317 break;
3318 }
3319
3320 Index--;
3321 TextOutList++;
3322 }
3323 //
3324 // The specified TextOut is not managed by the ConSplitter driver
3325 //
3326 if (Index < 0) {
3327 return EFI_NOT_FOUND;
3328 }
3329
3330 if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) {
3331 //
3332 // If there is not any physical GOP and UGA device in system,
3333 // Consplitter GOP or UGA protocol will be uninstalled
3334 //
3335 if (!FeaturePcdGet (PcdConOutGopSupport)) {
3336 Status = gBS->UninstallProtocolInterface (
3337 Private->VirtualHandle,
3338 &gEfiUgaDrawProtocolGuid,
3339 &Private->UgaDraw
3340 );
3341 } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
3342 Status = gBS->UninstallProtocolInterface (
3343 Private->VirtualHandle,
3344 &gEfiGraphicsOutputProtocolGuid,
3345 &Private->GraphicsOutput
3346 );
3347 } else {
3348 Status = gBS->UninstallMultipleProtocolInterfaces (
3349 Private->VirtualHandle,
3350 &gEfiUgaDrawProtocolGuid,
3351 &Private->UgaDraw,
3352 &gEfiGraphicsOutputProtocolGuid,
3353 &Private->GraphicsOutput,
3354 NULL
3355 );
3356 }
3357 }
3358
3359 if (CurrentNumOfConsoles == 0) {
3360 //
3361 // If the number of consoles is zero, reset all parameters
3362 //
3363 Private->CurrentNumberOfConsoles = 0;
3364 Private->TextOutMode.MaxMode = 1;
3365 Private->TextOutQueryData[0].Columns = 80;
3366 Private->TextOutQueryData[0].Rows = 25;
3367 TextOutSetMode (Private, 0);
3368
3369 return EFI_SUCCESS;
3370 }
3371 //
3372 // Max Mode is realy an intersection of the QueryMode command to all
3373 // devices. So we must copy the QueryMode of the first device to
3374 // QueryData.
3375 //
3376 ZeroMem (
3377 Private->TextOutQueryData,
3378 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)
3379 );
3380
3381 FreePool (Private->TextOutModeMap);
3382 Private->TextOutModeMap = NULL;
3383 TextOutList = Private->TextOutList;
3384
3385 //
3386 // Add the first TextOut to the QueryData array and ModeMap table
3387 //
3388 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);
3389
3390 //
3391 // Now add one by one
3392 //
3393 Index = 1;
3394 Private->CurrentNumberOfConsoles = 1;
3395 TextOutList++;
3396 while ((UINTN) Index < CurrentNumOfConsoles) {
3397 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);
3398 Index++;
3399 Private->CurrentNumberOfConsoles++;
3400 TextOutList++;
3401 }
3402
3403 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3404
3405 return Status;
3406 }
3407
3408
3409 /**
3410 Reset the input device and optionaly run diagnostics
3411
3412 @param This Protocol instance pointer.
3413 @param ExtendedVerification Driver may perform diagnostics on reset.
3414
3415 @retval EFI_SUCCESS The device was reset.
3416 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3417 not be reset.
3418
3419 **/
3420 EFI_STATUS
3421 EFIAPI
ConSplitterTextInReset(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)3422 ConSplitterTextInReset (
3423 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3424 IN BOOLEAN ExtendedVerification
3425 )
3426 {
3427 EFI_STATUS Status;
3428 EFI_STATUS ReturnStatus;
3429 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3430 UINTN Index;
3431
3432 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3433
3434 Private->KeyEventSignalState = FALSE;
3435
3436 //
3437 // return the worst status met
3438 //
3439 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3440 Status = Private->TextInList[Index]->Reset (
3441 Private->TextInList[Index],
3442 ExtendedVerification
3443 );
3444 if (EFI_ERROR (Status)) {
3445 ReturnStatus = Status;
3446 }
3447 }
3448
3449 if (!EFI_ERROR (ReturnStatus)) {
3450 ToggleStateSyncReInitialization (Private);
3451 }
3452
3453 return ReturnStatus;
3454 }
3455
3456
3457 /**
3458 Reads the next keystroke from the input device. The WaitForKey Event can
3459 be used to test for existance of a keystroke via WaitForEvent () call.
3460
3461 @param Private Protocol instance pointer.
3462 @param Key Driver may perform diagnostics on reset.
3463
3464 @retval EFI_SUCCESS The keystroke information was returned.
3465 @retval EFI_NOT_READY There was no keystroke data availiable.
3466 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3467 to hardware errors.
3468
3469 **/
3470 EFI_STATUS
3471 EFIAPI
ConSplitterTextInPrivateReadKeyStroke(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,OUT EFI_INPUT_KEY * Key)3472 ConSplitterTextInPrivateReadKeyStroke (
3473 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
3474 OUT EFI_INPUT_KEY *Key
3475 )
3476 {
3477 EFI_STATUS Status;
3478 UINTN Index;
3479 EFI_INPUT_KEY CurrentKey;
3480
3481 Key->UnicodeChar = 0;
3482 Key->ScanCode = SCAN_NULL;
3483
3484 //
3485 // if no physical console input device exists, return EFI_NOT_READY;
3486 // if any physical console input device has key input,
3487 // return the key and EFI_SUCCESS.
3488 //
3489 for (Index = 0; Index < Private->CurrentNumberOfConsoles;) {
3490 Status = Private->TextInList[Index]->ReadKeyStroke (
3491 Private->TextInList[Index],
3492 &CurrentKey
3493 );
3494 if (!EFI_ERROR (Status)) {
3495 //
3496 // If it is not partial keystorke, return the key. Otherwise, continue
3497 // to read key from THIS physical console input device.
3498 //
3499 if ((CurrentKey.ScanCode != CHAR_NULL) || (CurrentKey.UnicodeChar != SCAN_NULL)) {
3500 *Key = CurrentKey;
3501 return Status;
3502 }
3503 } else {
3504 //
3505 // Continue to read key from NEXT physical console input device.
3506 //
3507 Index++;
3508 }
3509 }
3510
3511 return EFI_NOT_READY;
3512 }
3513
3514
3515
3516 /**
3517 Reads the next keystroke from the input device. The WaitForKey Event can
3518 be used to test for existance of a keystroke via WaitForEvent () call.
3519
3520 @param This Protocol instance pointer.
3521 @param Key Driver may perform diagnostics on reset.
3522
3523 @retval EFI_SUCCESS The keystroke information was returned.
3524 @retval EFI_NOT_READY There was no keystroke data availiable.
3525 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3526 to hardware errors.
3527
3528 **/
3529 EFI_STATUS
3530 EFIAPI
ConSplitterTextInReadKeyStroke(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This,OUT EFI_INPUT_KEY * Key)3531 ConSplitterTextInReadKeyStroke (
3532 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3533 OUT EFI_INPUT_KEY *Key
3534 )
3535 {
3536 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3537
3538 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3539
3540 Private->KeyEventSignalState = FALSE;
3541
3542 //
3543 // Signal ConnectConIn event on first call in Lazy ConIn mode
3544 //
3545 if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
3546 DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
3547 gBS->SignalEvent (Private->ConnectConInEvent);
3548 mConInIsConnect = TRUE;
3549 }
3550
3551 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
3552 }
3553
3554
3555 /**
3556 This event aggregates all the events of the ConIn devices in the spliter.
3557
3558 If any events of physical ConIn devices are signaled, signal the ConIn
3559 spliter event. This will cause the calling code to call
3560 ConSplitterTextInReadKeyStroke ().
3561
3562 @param Event The Event assoicated with callback.
3563 @param Context Context registered when Event was created.
3564
3565 **/
3566 VOID
3567 EFIAPI
ConSplitterTextInWaitForKey(IN EFI_EVENT Event,IN VOID * Context)3568 ConSplitterTextInWaitForKey (
3569 IN EFI_EVENT Event,
3570 IN VOID *Context
3571 )
3572 {
3573 EFI_STATUS Status;
3574 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3575 UINTN Index;
3576
3577 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
3578
3579 if (Private->KeyEventSignalState) {
3580 //
3581 // If KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3582 //
3583 gBS->SignalEvent (Event);
3584 return ;
3585 }
3586
3587 //
3588 // If any physical console input device has key input, signal the event.
3589 //
3590 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
3591 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);
3592 if (!EFI_ERROR (Status)) {
3593 gBS->SignalEvent (Event);
3594 Private->KeyEventSignalState = TRUE;
3595 }
3596 }
3597 }
3598
3599
3600
3601 /**
3602 Test if the key has been registered on input device.
3603
3604 @param RegsiteredData A pointer to a buffer that is filled in with the
3605 keystroke state data for the key that was
3606 registered.
3607 @param InputData A pointer to a buffer that is filled in with the
3608 keystroke state data for the key that was
3609 pressed.
3610
3611 @retval TRUE Key be pressed matches a registered key.
3612 @retval FLASE Match failed.
3613
3614 **/
3615 BOOLEAN
IsKeyRegistered(IN EFI_KEY_DATA * RegsiteredData,IN EFI_KEY_DATA * InputData)3616 IsKeyRegistered (
3617 IN EFI_KEY_DATA *RegsiteredData,
3618 IN EFI_KEY_DATA *InputData
3619 )
3620 {
3621 ASSERT (RegsiteredData != NULL && InputData != NULL);
3622
3623 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
3624 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
3625 return FALSE;
3626 }
3627
3628 //
3629 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3630 //
3631 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
3632 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
3633 return FALSE;
3634 }
3635 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
3636 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
3637 return FALSE;
3638 }
3639
3640 return TRUE;
3641
3642 }
3643
3644
3645 /**
3646 Reset the input device and optionaly run diagnostics
3647
3648 @param This Protocol instance pointer.
3649 @param ExtendedVerification Driver may perform diagnostics on reset.
3650
3651 @retval EFI_SUCCESS The device was reset.
3652 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3653 not be reset.
3654
3655 **/
3656 EFI_STATUS
3657 EFIAPI
ConSplitterTextInResetEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This,IN BOOLEAN ExtendedVerification)3658 ConSplitterTextInResetEx (
3659 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3660 IN BOOLEAN ExtendedVerification
3661 )
3662 {
3663 EFI_STATUS Status;
3664 EFI_STATUS ReturnStatus;
3665 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3666 UINTN Index;
3667
3668 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3669
3670 Private->KeyEventSignalState = FALSE;
3671
3672 //
3673 // return the worst status met
3674 //
3675 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {
3676 Status = Private->TextInExList[Index]->Reset (
3677 Private->TextInExList[Index],
3678 ExtendedVerification
3679 );
3680 if (EFI_ERROR (Status)) {
3681 ReturnStatus = Status;
3682 }
3683 }
3684
3685 if (!EFI_ERROR (ReturnStatus)) {
3686 ToggleStateSyncReInitialization (Private);
3687 }
3688
3689 return ReturnStatus;
3690
3691 }
3692
3693
3694 /**
3695 Reads the next keystroke from the input device. The WaitForKey Event can
3696 be used to test for existance of a keystroke via WaitForEvent () call.
3697
3698 @param This Protocol instance pointer.
3699 @param KeyData A pointer to a buffer that is filled in with the
3700 keystroke state data for the key that was
3701 pressed.
3702
3703 @retval EFI_SUCCESS The keystroke information was returned.
3704 @retval EFI_NOT_READY There was no keystroke data availiable.
3705 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
3706 to hardware errors.
3707 @retval EFI_INVALID_PARAMETER KeyData is NULL.
3708
3709 **/
3710 EFI_STATUS
3711 EFIAPI
ConSplitterTextInReadKeyStrokeEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This,OUT EFI_KEY_DATA * KeyData)3712 ConSplitterTextInReadKeyStrokeEx (
3713 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3714 OUT EFI_KEY_DATA *KeyData
3715 )
3716 {
3717 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3718 EFI_STATUS Status;
3719 UINTN Index;
3720 EFI_KEY_DATA CurrentKeyData;
3721
3722
3723 if (KeyData == NULL) {
3724 return EFI_INVALID_PARAMETER;
3725 }
3726
3727 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3728
3729 Private->KeyEventSignalState = FALSE;
3730
3731 KeyData->Key.UnicodeChar = 0;
3732 KeyData->Key.ScanCode = SCAN_NULL;
3733
3734 //
3735 // Signal ConnectConIn event on first call in Lazy ConIn mode
3736 //
3737 if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {
3738 DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));
3739 gBS->SignalEvent (Private->ConnectConInEvent);
3740 mConInIsConnect = TRUE;
3741 }
3742
3743 //
3744 // if no physical console input device exists, return EFI_NOT_READY;
3745 // if any physical console input device has key input,
3746 // return the key and EFI_SUCCESS.
3747 //
3748 for (Index = 0; Index < Private->CurrentNumberOfExConsoles;) {
3749 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (
3750 Private->TextInExList[Index],
3751 &CurrentKeyData
3752 );
3753 if (!EFI_ERROR (Status)) {
3754 //
3755 // If virtual KeyState has been required to be exposed, or it is not
3756 // partial keystorke, return the key. Otherwise, continue to read key
3757 // from THIS physical console input device.
3758 //
3759 if ((Private->VirtualKeyStateExported) ||
3760 (CurrentKeyData.Key.ScanCode != CHAR_NULL) ||
3761 (CurrentKeyData.Key.UnicodeChar != SCAN_NULL)) {
3762 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));
3763 return Status;
3764 }
3765 } else {
3766 //
3767 // Continue to read key from NEXT physical console input device.
3768 //
3769 Index++;
3770 }
3771 }
3772
3773 return EFI_NOT_READY;
3774 }
3775
3776
3777 /**
3778 Set certain state for the input device.
3779
3780 @param This Protocol instance pointer.
3781 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
3782 state for the input device.
3783
3784 @retval EFI_SUCCESS The device state was set successfully.
3785 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3786 could not have the setting adjusted.
3787 @retval EFI_UNSUPPORTED The device does not have the ability to set its
3788 state.
3789 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
3790
3791 **/
3792 EFI_STATUS
3793 EFIAPI
ConSplitterTextInSetState(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This,IN EFI_KEY_TOGGLE_STATE * KeyToggleState)3794 ConSplitterTextInSetState (
3795 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3796 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
3797 )
3798 {
3799 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3800 EFI_STATUS Status;
3801 UINTN Index;
3802 EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState;
3803
3804 if (KeyToggleState == NULL) {
3805 return EFI_INVALID_PARAMETER;
3806 }
3807
3808 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3809
3810 //
3811 // Always turn on physical TextInEx partial key report for
3812 // toggle state sync.
3813 //
3814 PhysicalKeyToggleState = *KeyToggleState | EFI_KEY_STATE_EXPOSED;
3815
3816 //
3817 // if no physical console input device exists, return EFI_SUCCESS;
3818 // otherwise return the status of setting state of physical console input device
3819 //
3820 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3821 Status = Private->TextInExList[Index]->SetState (
3822 Private->TextInExList[Index],
3823 &PhysicalKeyToggleState
3824 );
3825 if (EFI_ERROR (Status)) {
3826 return Status;
3827 }
3828 }
3829
3830 //
3831 // Record the physical KeyToggleState.
3832 //
3833 Private->PhysicalKeyToggleState = PhysicalKeyToggleState;
3834 //
3835 // Get if virtual KeyState has been required to be exposed.
3836 //
3837 Private->VirtualKeyStateExported = (((*KeyToggleState) & EFI_KEY_STATE_EXPOSED) != 0);
3838
3839 return EFI_SUCCESS;
3840
3841 }
3842
3843
3844 /**
3845 Register a notification function for a particular keystroke for the input device.
3846
3847 @param This Protocol instance pointer.
3848 @param KeyData A pointer to a buffer that is filled in with the
3849 keystroke information data for the key that was
3850 pressed.
3851 @param KeyNotificationFunction Points to the function to be called when the key
3852 sequence is typed specified by KeyData.
3853 @param NotifyHandle Points to the unique handle assigned to the
3854 registered notification.
3855
3856 @retval EFI_SUCCESS The notification function was registered
3857 successfully.
3858 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
3859 structures.
3860 @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.
3861
3862 **/
3863 EFI_STATUS
3864 EFIAPI
ConSplitterTextInRegisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This,IN EFI_KEY_DATA * KeyData,IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,OUT VOID ** NotifyHandle)3865 ConSplitterTextInRegisterKeyNotify (
3866 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3867 IN EFI_KEY_DATA *KeyData,
3868 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
3869 OUT VOID **NotifyHandle
3870 )
3871 {
3872 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3873 EFI_STATUS Status;
3874 UINTN Index;
3875 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;
3876 LIST_ENTRY *Link;
3877 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3878
3879
3880 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
3881 return EFI_INVALID_PARAMETER;
3882 }
3883
3884 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3885
3886 //
3887 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3888 //
3889 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3890 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3891 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
3892 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
3893 *NotifyHandle = CurrentNotify;
3894 return EFI_SUCCESS;
3895 }
3896 }
3897 }
3898
3899 //
3900 // Allocate resource to save the notification function
3901 //
3902 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));
3903 if (NewNotify == NULL) {
3904 return EFI_OUT_OF_RESOURCES;
3905 }
3906 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount);
3907 if (NewNotify->NotifyHandleList == NULL) {
3908 gBS->FreePool (NewNotify);
3909 return EFI_OUT_OF_RESOURCES;
3910 }
3911 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;
3912 NewNotify->KeyNotificationFn = KeyNotificationFunction;
3913 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
3914
3915 //
3916 // Return the wrong status of registering key notify of
3917 // physical console input device if meet problems
3918 //
3919 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3920 Status = Private->TextInExList[Index]->RegisterKeyNotify (
3921 Private->TextInExList[Index],
3922 KeyData,
3923 KeyNotificationFunction,
3924 &NewNotify->NotifyHandleList[Index]
3925 );
3926 if (EFI_ERROR (Status)) {
3927 //
3928 // Un-register the key notify on all physical console input devices
3929 //
3930 while (Index-- != 0) {
3931 Private->TextInExList[Index]->UnregisterKeyNotify (
3932 Private->TextInExList[Index],
3933 NewNotify->NotifyHandleList[Index]
3934 );
3935 }
3936 gBS->FreePool (NewNotify->NotifyHandleList);
3937 gBS->FreePool (NewNotify);
3938 return Status;
3939 }
3940 }
3941
3942 InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);
3943
3944 *NotifyHandle = NewNotify;
3945
3946 return EFI_SUCCESS;
3947
3948 }
3949
3950
3951 /**
3952 Remove a registered notification function from a particular keystroke.
3953
3954 @param This Protocol instance pointer.
3955 @param NotificationHandle The handle of the notification function being
3956 unregistered.
3957
3958 @retval EFI_SUCCESS The notification function was unregistered
3959 successfully.
3960 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
3961
3962 **/
3963 EFI_STATUS
3964 EFIAPI
ConSplitterTextInUnregisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This,IN VOID * NotificationHandle)3965 ConSplitterTextInUnregisterKeyNotify (
3966 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3967 IN VOID *NotificationHandle
3968 )
3969 {
3970 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3971 UINTN Index;
3972 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3973 LIST_ENTRY *Link;
3974
3975 if (NotificationHandle == NULL) {
3976 return EFI_INVALID_PARAMETER;
3977 }
3978
3979 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3980
3981 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3982 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3983 if (CurrentNotify == NotificationHandle) {
3984 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3985 Private->TextInExList[Index]->UnregisterKeyNotify (
3986 Private->TextInExList[Index],
3987 CurrentNotify->NotifyHandleList[Index]
3988 );
3989 }
3990 RemoveEntryList (&CurrentNotify->NotifyEntry);
3991
3992 gBS->FreePool (CurrentNotify->NotifyHandleList);
3993 gBS->FreePool (CurrentNotify);
3994 return EFI_SUCCESS;
3995 }
3996 }
3997
3998 //
3999 // NotificationHandle is not found in database
4000 //
4001 return EFI_INVALID_PARAMETER;
4002 }
4003
4004
4005 /**
4006 Reset the input device and optionaly run diagnostics
4007
4008 @param This Protocol instance pointer.
4009 @param ExtendedVerification Driver may perform diagnostics on reset.
4010
4011 @retval EFI_SUCCESS The device was reset.
4012 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
4013 not be reset.
4014
4015 **/
4016 EFI_STATUS
4017 EFIAPI
ConSplitterSimplePointerReset(IN EFI_SIMPLE_POINTER_PROTOCOL * This,IN BOOLEAN ExtendedVerification)4018 ConSplitterSimplePointerReset (
4019 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
4020 IN BOOLEAN ExtendedVerification
4021 )
4022 {
4023 EFI_STATUS Status;
4024 EFI_STATUS ReturnStatus;
4025 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4026 UINTN Index;
4027
4028 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
4029
4030 Private->InputEventSignalState = FALSE;
4031
4032 if (Private->CurrentNumberOfPointers == 0) {
4033 return EFI_SUCCESS;
4034 }
4035 //
4036 // return the worst status met
4037 //
4038 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {
4039 Status = Private->PointerList[Index]->Reset (
4040 Private->PointerList[Index],
4041 ExtendedVerification
4042 );
4043 if (EFI_ERROR (Status)) {
4044 ReturnStatus = Status;
4045 }
4046 }
4047
4048 return ReturnStatus;
4049 }
4050
4051
4052 /**
4053 Reads the next keystroke from the input device. The WaitForKey Event can
4054 be used to test for existance of a keystroke via WaitForEvent () call.
4055
4056 @param Private Protocol instance pointer.
4057 @param State The state information of simple pointer device.
4058
4059 @retval EFI_SUCCESS The keystroke information was returned.
4060 @retval EFI_NOT_READY There was no keystroke data availiable.
4061 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
4062 to hardware errors.
4063
4064 **/
4065 EFI_STATUS
4066 EFIAPI
ConSplitterSimplePointerPrivateGetState(IN TEXT_IN_SPLITTER_PRIVATE_DATA * Private,IN OUT EFI_SIMPLE_POINTER_STATE * State)4067 ConSplitterSimplePointerPrivateGetState (
4068 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
4069 IN OUT EFI_SIMPLE_POINTER_STATE *State
4070 )
4071 {
4072 EFI_STATUS Status;
4073 EFI_STATUS ReturnStatus;
4074 UINTN Index;
4075 EFI_SIMPLE_POINTER_STATE CurrentState;
4076
4077 State->RelativeMovementX = 0;
4078 State->RelativeMovementY = 0;
4079 State->RelativeMovementZ = 0;
4080 State->LeftButton = FALSE;
4081 State->RightButton = FALSE;
4082
4083 //
4084 // if no physical console input device exists, return EFI_NOT_READY;
4085 // if any physical console input device has key input,
4086 // return the key and EFI_SUCCESS.
4087 //
4088 ReturnStatus = EFI_NOT_READY;
4089 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
4090
4091 Status = Private->PointerList[Index]->GetState (
4092 Private->PointerList[Index],
4093 &CurrentState
4094 );
4095 if (!EFI_ERROR (Status)) {
4096 if (ReturnStatus == EFI_NOT_READY) {
4097 ReturnStatus = EFI_SUCCESS;
4098 }
4099
4100 if (CurrentState.LeftButton) {
4101 State->LeftButton = TRUE;
4102 }
4103
4104 if (CurrentState.RightButton) {
4105 State->RightButton = TRUE;
4106 }
4107
4108 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {
4109 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;
4110 }
4111
4112 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {
4113 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;
4114 }
4115
4116 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {
4117 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;
4118 }
4119 } else if (Status == EFI_DEVICE_ERROR) {
4120 ReturnStatus = EFI_DEVICE_ERROR;
4121 }
4122 }
4123
4124 return ReturnStatus;
4125 }
4126
4127
4128 /**
4129 Reads the next keystroke from the input device. The WaitForKey Event can
4130 be used to test for existance of a keystroke via WaitForEvent () call.
4131
4132 @param This A pointer to protocol instance.
4133 @param State A pointer to state information on the pointer device
4134
4135 @retval EFI_SUCCESS The keystroke information was returned in State.
4136 @retval EFI_NOT_READY There was no keystroke data availiable.
4137 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
4138 to hardware errors.
4139
4140 **/
4141 EFI_STATUS
4142 EFIAPI
ConSplitterSimplePointerGetState(IN EFI_SIMPLE_POINTER_PROTOCOL * This,IN OUT EFI_SIMPLE_POINTER_STATE * State)4143 ConSplitterSimplePointerGetState (
4144 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
4145 IN OUT EFI_SIMPLE_POINTER_STATE *State
4146 )
4147 {
4148 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4149
4150 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
4151
4152 Private->InputEventSignalState = FALSE;
4153
4154 return ConSplitterSimplePointerPrivateGetState (Private, State);
4155 }
4156
4157
4158 /**
4159 This event agregates all the events of the ConIn devices in the spliter.
4160 If any events of physical ConIn devices are signaled, signal the ConIn
4161 spliter event. This will cause the calling code to call
4162 ConSplitterTextInReadKeyStroke ().
4163
4164 @param Event The Event assoicated with callback.
4165 @param Context Context registered when Event was created.
4166
4167 **/
4168 VOID
4169 EFIAPI
ConSplitterSimplePointerWaitForInput(IN EFI_EVENT Event,IN VOID * Context)4170 ConSplitterSimplePointerWaitForInput (
4171 IN EFI_EVENT Event,
4172 IN VOID *Context
4173 )
4174 {
4175 EFI_STATUS Status;
4176 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4177 UINTN Index;
4178
4179 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
4180
4181 //
4182 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
4183 //
4184 if (Private->InputEventSignalState) {
4185 gBS->SignalEvent (Event);
4186 return ;
4187 }
4188 //
4189 // if any physical console input device has key input, signal the event.
4190 //
4191 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
4192 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);
4193 if (!EFI_ERROR (Status)) {
4194 gBS->SignalEvent (Event);
4195 Private->InputEventSignalState = TRUE;
4196 }
4197 }
4198 }
4199
4200 /**
4201 Resets the pointer device hardware.
4202
4203 @param This Protocol instance pointer.
4204 @param ExtendedVerification Driver may perform diagnostics on reset.
4205
4206 @retval EFI_SUCCESS The device was reset.
4207 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
4208 could not be reset.
4209
4210 **/
4211 EFI_STATUS
4212 EFIAPI
ConSplitterAbsolutePointerReset(IN EFI_ABSOLUTE_POINTER_PROTOCOL * This,IN BOOLEAN ExtendedVerification)4213 ConSplitterAbsolutePointerReset (
4214 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
4215 IN BOOLEAN ExtendedVerification
4216 )
4217 {
4218 EFI_STATUS Status;
4219 EFI_STATUS ReturnStatus;
4220 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4221 UINTN Index;
4222
4223 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
4224
4225 Private->AbsoluteInputEventSignalState = FALSE;
4226
4227 if (Private->CurrentNumberOfAbsolutePointers == 0) {
4228 return EFI_SUCCESS;
4229 }
4230 //
4231 // return the worst status met
4232 //
4233 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4234 Status = Private->AbsolutePointerList[Index]->Reset (
4235 Private->AbsolutePointerList[Index],
4236 ExtendedVerification
4237 );
4238 if (EFI_ERROR (Status)) {
4239 ReturnStatus = Status;
4240 }
4241 }
4242
4243 return ReturnStatus;
4244 }
4245
4246
4247 /**
4248 Retrieves the current state of a pointer device.
4249
4250 @param This Protocol instance pointer.
4251 @param State A pointer to the state information on the
4252 pointer device.
4253
4254 @retval EFI_SUCCESS The state of the pointer device was returned in
4255 State..
4256 @retval EFI_NOT_READY The state of the pointer device has not changed
4257 since the last call to GetState().
4258 @retval EFI_DEVICE_ERROR A device error occurred while attempting to
4259 retrieve the pointer device's current state.
4260
4261 **/
4262 EFI_STATUS
4263 EFIAPI
ConSplitterAbsolutePointerGetState(IN EFI_ABSOLUTE_POINTER_PROTOCOL * This,IN OUT EFI_ABSOLUTE_POINTER_STATE * State)4264 ConSplitterAbsolutePointerGetState (
4265 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
4266 IN OUT EFI_ABSOLUTE_POINTER_STATE *State
4267 )
4268 {
4269 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4270 EFI_STATUS Status;
4271 EFI_STATUS ReturnStatus;
4272 UINTN Index;
4273 EFI_ABSOLUTE_POINTER_STATE CurrentState;
4274 UINT64 MinX;
4275 UINT64 MinY;
4276 UINT64 MinZ;
4277 UINT64 MaxX;
4278 UINT64 MaxY;
4279 UINT64 MaxZ;
4280 UINT64 VirtualMinX;
4281 UINT64 VirtualMinY;
4282 UINT64 VirtualMinZ;
4283 UINT64 VirtualMaxX;
4284 UINT64 VirtualMaxY;
4285 UINT64 VirtualMaxZ;
4286
4287 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
4288
4289 Private->AbsoluteInputEventSignalState = FALSE;
4290
4291 State->CurrentX = 0;
4292 State->CurrentY = 0;
4293 State->CurrentZ = 0;
4294 State->ActiveButtons = 0;
4295
4296 VirtualMinX = Private->AbsolutePointerMode.AbsoluteMinX;
4297 VirtualMinY = Private->AbsolutePointerMode.AbsoluteMinY;
4298 VirtualMinZ = Private->AbsolutePointerMode.AbsoluteMinZ;
4299 VirtualMaxX = Private->AbsolutePointerMode.AbsoluteMaxX;
4300 VirtualMaxY = Private->AbsolutePointerMode.AbsoluteMaxY;
4301 VirtualMaxZ = Private->AbsolutePointerMode.AbsoluteMaxZ;
4302
4303 //
4304 // if no physical pointer device exists, return EFI_NOT_READY;
4305 // if any physical pointer device has changed state,
4306 // return the state and EFI_SUCCESS.
4307 //
4308 ReturnStatus = EFI_NOT_READY;
4309 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4310
4311 Status = Private->AbsolutePointerList[Index]->GetState (
4312 Private->AbsolutePointerList[Index],
4313 &CurrentState
4314 );
4315 if (!EFI_ERROR (Status)) {
4316 if (ReturnStatus == EFI_NOT_READY) {
4317 ReturnStatus = EFI_SUCCESS;
4318 }
4319
4320 MinX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinX;
4321 MinY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinY;
4322 MinZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinZ;
4323 MaxX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxX;
4324 MaxY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxY;
4325 MaxZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxZ;
4326
4327 State->ActiveButtons = CurrentState.ActiveButtons;
4328
4329 //
4330 // Rescale to Con Splitter virtual Absolute Pointer's resolution.
4331 //
4332 if (!(MinX == 0 && MaxX == 0)) {
4333 State->CurrentX = VirtualMinX + DivU64x64Remainder (
4334 MultU64x64 (
4335 CurrentState.CurrentX,
4336 VirtualMaxX - VirtualMinX
4337 ),
4338 MaxX - MinX,
4339 NULL
4340 );
4341 }
4342 if (!(MinY == 0 && MaxY == 0)) {
4343 State->CurrentY = VirtualMinY + DivU64x64Remainder (
4344 MultU64x64 (
4345 CurrentState.CurrentY,
4346 VirtualMaxY - VirtualMinY
4347 ),
4348 MaxY - MinY,
4349 NULL
4350 );
4351 }
4352 if (!(MinZ == 0 && MaxZ == 0)) {
4353 State->CurrentZ = VirtualMinZ + DivU64x64Remainder (
4354 MultU64x64 (
4355 CurrentState.CurrentZ,
4356 VirtualMaxZ - VirtualMinZ
4357 ),
4358 MaxZ - MinZ,
4359 NULL
4360 );
4361 }
4362
4363 } else if (Status == EFI_DEVICE_ERROR) {
4364 ReturnStatus = EFI_DEVICE_ERROR;
4365 }
4366 }
4367
4368 return ReturnStatus;
4369 }
4370
4371
4372 /**
4373 This event agregates all the events of the pointer devices in the splitter.
4374 If any events of physical pointer devices are signaled, signal the pointer
4375 splitter event. This will cause the calling code to call
4376 ConSplitterAbsolutePointerGetState ().
4377
4378 @param Event The Event assoicated with callback.
4379 @param Context Context registered when Event was created.
4380
4381 **/
4382 VOID
4383 EFIAPI
ConSplitterAbsolutePointerWaitForInput(IN EFI_EVENT Event,IN VOID * Context)4384 ConSplitterAbsolutePointerWaitForInput (
4385 IN EFI_EVENT Event,
4386 IN VOID *Context
4387 )
4388 {
4389 EFI_STATUS Status;
4390 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4391 UINTN Index;
4392
4393 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
4394
4395 //
4396 // if AbsoluteInputEventSignalState is flagged before,
4397 // and not cleared by Reset() or GetState(), signal it
4398 //
4399 if (Private->AbsoluteInputEventSignalState) {
4400 gBS->SignalEvent (Event);
4401 return ;
4402 }
4403 //
4404 // if any physical console input device has key input, signal the event.
4405 //
4406 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4407 Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);
4408 if (!EFI_ERROR (Status)) {
4409 gBS->SignalEvent (Event);
4410 Private->AbsoluteInputEventSignalState = TRUE;
4411 }
4412 }
4413 }
4414
4415
4416 /**
4417 Reset the text output device hardware and optionaly run diagnostics
4418
4419 @param This Protocol instance pointer.
4420 @param ExtendedVerification Driver may perform more exhaustive verfication
4421 operation of the device during reset.
4422
4423 @retval EFI_SUCCESS The text output device was reset.
4424 @retval EFI_DEVICE_ERROR The text output device is not functioning
4425 correctly and could not be reset.
4426
4427 **/
4428 EFI_STATUS
4429 EFIAPI
ConSplitterTextOutReset(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)4430 ConSplitterTextOutReset (
4431 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4432 IN BOOLEAN ExtendedVerification
4433 )
4434 {
4435 EFI_STATUS Status;
4436 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4437 UINTN Index;
4438 EFI_STATUS ReturnStatus;
4439
4440 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4441
4442 //
4443 // return the worst status met
4444 //
4445 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4446 Status = Private->TextOutList[Index].TextOut->Reset (
4447 Private->TextOutList[Index].TextOut,
4448 ExtendedVerification
4449 );
4450 if (EFI_ERROR (Status)) {
4451 ReturnStatus = Status;
4452 }
4453 }
4454
4455 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));
4456
4457 //
4458 // reset all mode parameters
4459 //
4460 TextOutSetMode (Private, 0);
4461
4462 return ReturnStatus;
4463 }
4464
4465
4466 /**
4467 Write a Unicode string to the output device.
4468
4469 @param This Protocol instance pointer.
4470 @param WString The NULL-terminated Unicode string to be
4471 displayed on the output device(s). All output
4472 devices must also support the Unicode drawing
4473 defined in this file.
4474
4475 @retval EFI_SUCCESS The string was output to the device.
4476 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
4477 output the text.
4478 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
4479 defined text mode.
4480 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
4481 characters in the Unicode string could not be
4482 rendered and were skipped.
4483
4484 **/
4485 EFI_STATUS
4486 EFIAPI
ConSplitterTextOutOutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * WString)4487 ConSplitterTextOutOutputString (
4488 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4489 IN CHAR16 *WString
4490 )
4491 {
4492 EFI_STATUS Status;
4493 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4494 UINTN Index;
4495 EFI_STATUS ReturnStatus;
4496 UINTN MaxColumn;
4497 UINTN MaxRow;
4498
4499 This->SetAttribute (This, This->Mode->Attribute);
4500
4501 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4502
4503 //
4504 // return the worst status met
4505 //
4506 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4507 Status = Private->TextOutList[Index].TextOut->OutputString (
4508 Private->TextOutList[Index].TextOut,
4509 WString
4510 );
4511 if (EFI_ERROR (Status)) {
4512 ReturnStatus = Status;
4513 }
4514 }
4515
4516 if (Private->CurrentNumberOfConsoles > 0) {
4517 Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;
4518 Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;
4519 } else {
4520 //
4521 // When there is no real console devices in system,
4522 // update cursor position for the virtual device in consplitter.
4523 //
4524 Private->TextOut.QueryMode (
4525 &Private->TextOut,
4526 Private->TextOutMode.Mode,
4527 &MaxColumn,
4528 &MaxRow
4529 );
4530 for (; *WString != CHAR_NULL; WString++) {
4531 switch (*WString) {
4532 case CHAR_BACKSPACE:
4533 if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {
4534 Private->TextOutMode.CursorRow--;
4535 Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);
4536 } else if (Private->TextOutMode.CursorColumn > 0) {
4537 Private->TextOutMode.CursorColumn--;
4538 }
4539 break;
4540
4541 case CHAR_LINEFEED:
4542 if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
4543 Private->TextOutMode.CursorRow++;
4544 }
4545 break;
4546
4547 case CHAR_CARRIAGE_RETURN:
4548 Private->TextOutMode.CursorColumn = 0;
4549 break;
4550
4551 default:
4552 if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {
4553 Private->TextOutMode.CursorColumn++;
4554 } else {
4555 Private->TextOutMode.CursorColumn = 0;
4556 if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
4557 Private->TextOutMode.CursorRow++;
4558 }
4559 }
4560 break;
4561 }
4562 }
4563 }
4564
4565 return ReturnStatus;
4566 }
4567
4568
4569 /**
4570 Verifies that all characters in a Unicode string can be output to the
4571 target device.
4572
4573 @param This Protocol instance pointer.
4574 @param WString The NULL-terminated Unicode string to be
4575 examined for the output device(s).
4576
4577 @retval EFI_SUCCESS The device(s) are capable of rendering the
4578 output string.
4579 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string
4580 cannot be rendered by one or more of the output
4581 devices mapped by the EFI handle.
4582
4583 **/
4584 EFI_STATUS
4585 EFIAPI
ConSplitterTextOutTestString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * WString)4586 ConSplitterTextOutTestString (
4587 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4588 IN CHAR16 *WString
4589 )
4590 {
4591 EFI_STATUS Status;
4592 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4593 UINTN Index;
4594 EFI_STATUS ReturnStatus;
4595
4596 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4597
4598 //
4599 // return the worst status met
4600 //
4601 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4602 Status = Private->TextOutList[Index].TextOut->TestString (
4603 Private->TextOutList[Index].TextOut,
4604 WString
4605 );
4606 if (EFI_ERROR (Status)) {
4607 ReturnStatus = Status;
4608 }
4609 }
4610 //
4611 // There is no DevNullTextOutTestString () since a Unicode buffer would
4612 // always return EFI_SUCCESS.
4613 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4614 //
4615 return ReturnStatus;
4616 }
4617
4618
4619 /**
4620 Returns information for an available text mode that the output device(s)
4621 supports.
4622
4623 @param This Protocol instance pointer.
4624 @param ModeNumber The mode number to return information on.
4625 @param Columns Returns the columns of the text output device
4626 for the requested ModeNumber.
4627 @param Rows Returns the rows of the text output device
4628 for the requested ModeNumber.
4629
4630 @retval EFI_SUCCESS The requested mode information was returned.
4631 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4632 the request.
4633 @retval EFI_UNSUPPORTED The mode number was not valid.
4634
4635 **/
4636 EFI_STATUS
4637 EFIAPI
ConSplitterTextOutQueryMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber,OUT UINTN * Columns,OUT UINTN * Rows)4638 ConSplitterTextOutQueryMode (
4639 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4640 IN UINTN ModeNumber,
4641 OUT UINTN *Columns,
4642 OUT UINTN *Rows
4643 )
4644 {
4645 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4646 UINTN CurrentMode;
4647 INT32 *TextOutModeMap;
4648
4649 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4650
4651 //
4652 // Check whether param ModeNumber is valid.
4653 // ModeNumber should be within range 0 ~ MaxMode - 1.
4654 //
4655 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4656 return EFI_UNSUPPORTED;
4657 }
4658
4659 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4660 return EFI_UNSUPPORTED;
4661 }
4662
4663 //
4664 // We get the available mode from mode intersection map if it's available
4665 //
4666 if (Private->TextOutModeMap != NULL) {
4667 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4668 CurrentMode = (UINTN)(*TextOutModeMap);
4669 *Columns = Private->TextOutQueryData[CurrentMode].Columns;
4670 *Rows = Private->TextOutQueryData[CurrentMode].Rows;
4671 } else {
4672 *Columns = Private->TextOutQueryData[ModeNumber].Columns;
4673 *Rows = Private->TextOutQueryData[ModeNumber].Rows;
4674 }
4675
4676 if (*Columns <= 0 && *Rows <= 0) {
4677 return EFI_UNSUPPORTED;
4678
4679 }
4680
4681 return EFI_SUCCESS;
4682 }
4683
4684
4685 /**
4686 Sets the output device(s) to a specified mode.
4687
4688 @param This Protocol instance pointer.
4689 @param ModeNumber The mode number to set.
4690
4691 @retval EFI_SUCCESS The requested text mode was set.
4692 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4693 the request.
4694 @retval EFI_UNSUPPORTED The mode number was not valid.
4695
4696 **/
4697 EFI_STATUS
4698 EFIAPI
ConSplitterTextOutSetMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber)4699 ConSplitterTextOutSetMode (
4700 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4701 IN UINTN ModeNumber
4702 )
4703 {
4704 EFI_STATUS Status;
4705 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4706 UINTN Index;
4707 INT32 *TextOutModeMap;
4708 EFI_STATUS ReturnStatus;
4709
4710 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4711
4712 //
4713 // Check whether param ModeNumber is valid.
4714 // ModeNumber should be within range 0 ~ MaxMode - 1.
4715 //
4716 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4717 return EFI_UNSUPPORTED;
4718 }
4719
4720 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4721 return EFI_UNSUPPORTED;
4722 }
4723 //
4724 // If the mode is being set to the curent mode, then just clear the screen and return.
4725 //
4726 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {
4727 return ConSplitterTextOutClearScreen (This);
4728 }
4729 //
4730 // return the worst status met
4731 //
4732 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4733 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4734 Status = Private->TextOutList[Index].TextOut->SetMode (
4735 Private->TextOutList[Index].TextOut,
4736 TextOutModeMap[Index]
4737 );
4738 if (EFI_ERROR (Status)) {
4739 ReturnStatus = Status;
4740 }
4741 }
4742
4743 //
4744 // Set mode parameter to specified mode number
4745 //
4746 TextOutSetMode (Private, ModeNumber);
4747
4748 return ReturnStatus;
4749 }
4750
4751
4752 /**
4753 Sets the background and foreground colors for the OutputString () and
4754 ClearScreen () functions.
4755
4756 @param This Protocol instance pointer.
4757 @param Attribute The attribute to set. Bits 0..3 are the
4758 foreground color, and bits 4..6 are the
4759 background color. All other bits are undefined
4760 and must be zero. The valid Attributes are
4761 defined in this file.
4762
4763 @retval EFI_SUCCESS The attribute was set.
4764 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4765 the request.
4766 @retval EFI_UNSUPPORTED The attribute requested is not defined.
4767
4768 **/
4769 EFI_STATUS
4770 EFIAPI
ConSplitterTextOutSetAttribute(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Attribute)4771 ConSplitterTextOutSetAttribute (
4772 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4773 IN UINTN Attribute
4774 )
4775 {
4776 EFI_STATUS Status;
4777 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4778 UINTN Index;
4779 EFI_STATUS ReturnStatus;
4780
4781 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4782
4783 //
4784 // Check whether param Attribute is valid.
4785 //
4786 if ((Attribute | 0x7F) != 0x7F) {
4787 return EFI_UNSUPPORTED;
4788 }
4789
4790 //
4791 // return the worst status met
4792 //
4793 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4794 Status = Private->TextOutList[Index].TextOut->SetAttribute (
4795 Private->TextOutList[Index].TextOut,
4796 Attribute
4797 );
4798 if (EFI_ERROR (Status)) {
4799 ReturnStatus = Status;
4800 }
4801 }
4802
4803 Private->TextOutMode.Attribute = (INT32) Attribute;
4804
4805 return ReturnStatus;
4806 }
4807
4808
4809 /**
4810 Clears the output device(s) display to the currently selected background
4811 color.
4812
4813 @param This Protocol instance pointer.
4814
4815 @retval EFI_SUCCESS The operation completed successfully.
4816 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4817 the request.
4818 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4819
4820 **/
4821 EFI_STATUS
4822 EFIAPI
ConSplitterTextOutClearScreen(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This)4823 ConSplitterTextOutClearScreen (
4824 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
4825 )
4826 {
4827 EFI_STATUS Status;
4828 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4829 UINTN Index;
4830 EFI_STATUS ReturnStatus;
4831
4832 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4833
4834 //
4835 // return the worst status met
4836 //
4837 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4838 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);
4839 if (EFI_ERROR (Status)) {
4840 ReturnStatus = Status;
4841 }
4842 }
4843
4844 //
4845 // No need to do extra check here as whether (Column, Row) is valid has
4846 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4847 // always be supported.
4848 //
4849 Private->TextOutMode.CursorColumn = 0;
4850 Private->TextOutMode.CursorRow = 0;
4851 Private->TextOutMode.CursorVisible = TRUE;
4852
4853 return ReturnStatus;
4854 }
4855
4856
4857 /**
4858 Sets the current coordinates of the cursor position
4859
4860 @param This Protocol instance pointer.
4861 @param Column The column position to set the cursor to. Must be
4862 greater than or equal to zero and less than the
4863 number of columns by QueryMode ().
4864 @param Row The row position to set the cursor to. Must be
4865 greater than or equal to zero and less than the
4866 number of rows by QueryMode ().
4867
4868 @retval EFI_SUCCESS The operation completed successfully.
4869 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4870 the request.
4871 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,
4872 or the cursor position is invalid for the
4873 current mode.
4874
4875 **/
4876 EFI_STATUS
4877 EFIAPI
ConSplitterTextOutSetCursorPosition(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Column,IN UINTN Row)4878 ConSplitterTextOutSetCursorPosition (
4879 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4880 IN UINTN Column,
4881 IN UINTN Row
4882 )
4883 {
4884 EFI_STATUS Status;
4885 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4886 UINTN Index;
4887 EFI_STATUS ReturnStatus;
4888 UINTN MaxColumn;
4889 UINTN MaxRow;
4890 INT32 *TextOutModeMap;
4891 INT32 ModeNumber;
4892 INT32 CurrentMode;
4893
4894 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4895 TextOutModeMap = NULL;
4896 ModeNumber = Private->TextOutMode.Mode;
4897
4898 //
4899 // Get current MaxColumn and MaxRow from intersection map
4900 //
4901 if (Private->TextOutModeMap != NULL) {
4902 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4903 CurrentMode = *TextOutModeMap;
4904 } else {
4905 CurrentMode = ModeNumber;
4906 }
4907
4908 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;
4909 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;
4910
4911 if (Column >= MaxColumn || Row >= MaxRow) {
4912 return EFI_UNSUPPORTED;
4913 }
4914 //
4915 // return the worst status met
4916 //
4917 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4918 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (
4919 Private->TextOutList[Index].TextOut,
4920 Column,
4921 Row
4922 );
4923 if (EFI_ERROR (Status)) {
4924 ReturnStatus = Status;
4925 }
4926 }
4927
4928 //
4929 // No need to do extra check here as whether (Column, Row) is valid has
4930 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4931 // always be supported.
4932 //
4933 Private->TextOutMode.CursorColumn = (INT32) Column;
4934 Private->TextOutMode.CursorRow = (INT32) Row;
4935
4936 return ReturnStatus;
4937 }
4938
4939
4940 /**
4941 Makes the cursor visible or invisible
4942
4943 @param This Protocol instance pointer.
4944 @param Visible If TRUE, the cursor is set to be visible. If
4945 FALSE, the cursor is set to be invisible.
4946
4947 @retval EFI_SUCCESS The operation completed successfully.
4948 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4949 the request, or the device does not support
4950 changing the cursor mode.
4951 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4952
4953 **/
4954 EFI_STATUS
4955 EFIAPI
ConSplitterTextOutEnableCursor(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN Visible)4956 ConSplitterTextOutEnableCursor (
4957 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4958 IN BOOLEAN Visible
4959 )
4960 {
4961 EFI_STATUS Status;
4962 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4963 UINTN Index;
4964 EFI_STATUS ReturnStatus;
4965
4966 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4967
4968 //
4969 // return the worst status met
4970 //
4971 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4972 Status = Private->TextOutList[Index].TextOut->EnableCursor (
4973 Private->TextOutList[Index].TextOut,
4974 Visible
4975 );
4976 if (EFI_ERROR (Status)) {
4977 ReturnStatus = Status;
4978 }
4979 }
4980
4981 Private->TextOutMode.CursorVisible = Visible;
4982
4983 return ReturnStatus;
4984 }
4985
4986
4987 /**
4988 An empty function to pass error checking of CreateEventEx ().
4989
4990 @param Event Event whose notification function is being invoked.
4991 @param Context Pointer to the notification function's context,
4992 which is implementation-dependent.
4993
4994 **/
4995 VOID
4996 EFIAPI
ConSplitterEmptyCallbackFunction(IN EFI_EVENT Event,IN VOID * Context)4997 ConSplitterEmptyCallbackFunction (
4998 IN EFI_EVENT Event,
4999 IN VOID *Context
5000 )
5001 {
5002 }
5003