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