]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
Fix the issue that the GOP produced by ConSplitter requires SetMode before GetMode...
[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 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
2905
2906 PreferMode = 0xFF;
2907 BaseMode = 0xFF;
2908 TextOut = &Private->TextOut;
2909 MaxMode = (UINTN) (TextOut->Mode->MaxMode);
2910
2911 ModeInfo.Column = PcdGet32 (PcdConOutColumn);
2912 ModeInfo.Row = PcdGet32 (PcdConOutRow);
2913
2914 //
2915 // To find the prefer mode and basic mode from Text Out mode list
2916 //
2917 for (Mode = 0; Mode < MaxMode; Mode++) {
2918 Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);
2919 if (!EFI_ERROR(Status)) {
2920 if (Col == ModeInfo.Column && Row == ModeInfo.Row) {
2921 PreferMode = Mode;
2922 }
2923 if (Col == 80 && Row == 25) {
2924 BaseMode = Mode;
2925 }
2926 }
2927 }
2928
2929 //
2930 // Set prefer mode to Text Out devices.
2931 //
2932 Status = TextOut->SetMode (TextOut, PreferMode);
2933 if (EFI_ERROR(Status)) {
2934 //
2935 // if current mode setting is failed, default 80x25 mode will be set.
2936 //
2937 Status = TextOut->SetMode (TextOut, BaseMode);
2938 ASSERT(!EFI_ERROR(Status));
2939
2940 PcdSet32 (PcdConOutColumn, 80);
2941 PcdSet32 (PcdConOutRow, 25);
2942 }
2943
2944 return ;
2945 }
2946
2947
2948 /**
2949 Add Text Output Device in Consplitter Text Output list.
2950
2951 @param Private Text Out Splitter pointer.
2952 @param TextOut Simple Text Output protocol pointer.
2953 @param GraphicsOutput Graphics Output protocol pointer.
2954 @param UgaDraw UGA Draw protocol pointer.
2955
2956 @retval EFI_SUCCESS Text Output Device added successfully.
2957 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2958
2959 **/
2960 EFI_STATUS
2961 ConSplitterTextOutAddDevice (
2962 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2963 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
2964 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2965 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2966 )
2967 {
2968 EFI_STATUS Status;
2969 UINTN CurrentNumOfConsoles;
2970 INT32 MaxMode;
2971 UINT32 UgaHorizontalResolution;
2972 UINT32 UgaVerticalResolution;
2973 UINT32 UgaColorDepth;
2974 UINT32 UgaRefreshRate;
2975 TEXT_OUT_AND_GOP_DATA *TextAndGop;
2976 UINTN SizeOfInfo;
2977 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
2978 EFI_STATUS DeviceStatus;
2979
2980 Status = EFI_SUCCESS;
2981 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
2982
2983 //
2984 // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().
2985 //
2986 while (CurrentNumOfConsoles >= Private->TextOutListCount) {
2987 Status = ConSplitterGrowBuffer (
2988 sizeof (TEXT_OUT_AND_GOP_DATA),
2989 &Private->TextOutListCount,
2990 (VOID **) &Private->TextOutList
2991 );
2992 if (EFI_ERROR (Status)) {
2993 return EFI_OUT_OF_RESOURCES;
2994 }
2995 //
2996 // Also need to reallocate the TextOutModeMap table
2997 //
2998 Status = ConSplitterGrowMapTable (Private);
2999 if (EFI_ERROR (Status)) {
3000 return EFI_OUT_OF_RESOURCES;
3001 }
3002 }
3003
3004 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];
3005
3006 TextAndGop->TextOut = TextOut;
3007 TextAndGop->GraphicsOutput = GraphicsOutput;
3008 TextAndGop->UgaDraw = UgaDraw;
3009
3010 if (CurrentNumOfConsoles == 0) {
3011 //
3012 // Add the first device's output mode to console splitter's mode list
3013 //
3014 Status = ConSplitterAddOutputMode (Private, TextOut);
3015 } else {
3016 ConSplitterSyncOutputMode (Private, TextOut);
3017 }
3018
3019 Private->CurrentNumberOfConsoles++;
3020
3021 //
3022 // Scan both TextOutList, for the intersection TextOut device
3023 // maybe both ConOut and StdErr incorporate the same Text Out
3024 // device in them, thus the output of both should be synced.
3025 //
3026 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3027
3028 MaxMode = Private->TextOutMode.MaxMode;
3029 ASSERT (MaxMode >= 1);
3030
3031 DeviceStatus = EFI_DEVICE_ERROR;
3032 if (FeaturePcdGet (PcdConOutGopSupport)) {
3033 //
3034 // If GOP is produced by Consplitter, this device display mode will be added into Graphics Ouput modes.
3035 //
3036 if ((GraphicsOutput != NULL) || (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport))) {
3037 DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
3038 }
3039 }
3040
3041 if (FeaturePcdGet (PcdConOutUgaSupport)) {
3042 //
3043 // If UGA is produced by Consplitter
3044 //
3045 if (GraphicsOutput != NULL) {
3046 Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
3047 if (EFI_ERROR (Status)) {
3048 return Status;
3049 }
3050 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
3051
3052 UgaHorizontalResolution = Info->HorizontalResolution;
3053 UgaVerticalResolution = Info->VerticalResolution;
3054
3055 FreePool (Info);
3056
3057 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
3058 Status = UgaDraw->GetMode (
3059 UgaDraw,
3060 &UgaHorizontalResolution,
3061 &UgaVerticalResolution,
3062 &UgaColorDepth,
3063 &UgaRefreshRate
3064 );
3065 if (!EFI_ERROR (Status) && EFI_ERROR (DeviceStatus)) {
3066 //
3067 // if GetMode is successfully and UGA device hasn't been set, set it
3068 //
3069 Status = ConSplitterUgaDrawSetMode (
3070 &Private->UgaDraw,
3071 UgaHorizontalResolution,
3072 UgaVerticalResolution,
3073 UgaColorDepth,
3074 UgaRefreshRate
3075 );
3076 }
3077 //
3078 // If GetMode/SetMode is failed, set to 800x600 mode
3079 //
3080 if(EFI_ERROR (Status)) {
3081 Status = ConSplitterUgaDrawSetMode (
3082 &Private->UgaDraw,
3083 800,
3084 600,
3085 32,
3086 60
3087 );
3088 }
3089 }
3090 }
3091
3092 //
3093 // After adding new console device, all existing console devices should be
3094 // synced to the current shared mode.
3095 //
3096 ConsplitterSetConsoleOutMode (Private);
3097
3098 return Status;
3099 }
3100
3101
3102 /**
3103 Remove Text Out Device in Consplitter Text Out list.
3104
3105 @param Private Text Out Splitter pointer.
3106 @param TextOut Simple Text Output Pointer protocol pointer.
3107
3108 @retval EFI_SUCCESS Text Out Device removed successfully.
3109 @retval EFI_NOT_FOUND No Text Out Device found.
3110
3111 **/
3112 EFI_STATUS
3113 ConSplitterTextOutDeleteDevice (
3114 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
3115 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
3116 )
3117 {
3118 INT32 Index;
3119 UINTN CurrentNumOfConsoles;
3120 TEXT_OUT_AND_GOP_DATA *TextOutList;
3121 EFI_STATUS Status;
3122
3123 //
3124 // Remove the specified text-out device data structure from the Text out List,
3125 // and rearrange the remaining data structures in the Text out List.
3126 //
3127 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
3128 Index = (INT32) CurrentNumOfConsoles - 1;
3129 TextOutList = Private->TextOutList;
3130 while (Index >= 0) {
3131 if (TextOutList->TextOut == TextOut) {
3132 if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
3133 Private->CurrentNumberOfUgaDraw--;
3134 }
3135 if (TextOutList->GraphicsOutput != NULL) {
3136 Private->CurrentNumberOfGraphicsOutput--;
3137 }
3138 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
3139 CurrentNumOfConsoles--;
3140 break;
3141 }
3142
3143 Index--;
3144 TextOutList++;
3145 }
3146 //
3147 // The specified TextOut is not managed by the ConSplitter driver
3148 //
3149 if (Index < 0) {
3150 return EFI_NOT_FOUND;
3151 }
3152
3153 if (CurrentNumOfConsoles == 0) {
3154 //
3155 // If the number of consoles is zero, reset all parameters
3156 //
3157 Private->CurrentNumberOfConsoles = 0;
3158 Private->TextOutMode.MaxMode = 1;
3159 Private->TextOutQueryData[0].Columns = 80;
3160 Private->TextOutQueryData[0].Rows = 25;
3161 TextOutSetMode (Private, 0);
3162
3163 return EFI_SUCCESS;
3164 }
3165 //
3166 // Max Mode is realy an intersection of the QueryMode command to all
3167 // devices. So we must copy the QueryMode of the first device to
3168 // QueryData.
3169 //
3170 ZeroMem (
3171 Private->TextOutQueryData,
3172 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)
3173 );
3174
3175 FreePool (Private->TextOutModeMap);
3176 Private->TextOutModeMap = NULL;
3177 TextOutList = Private->TextOutList;
3178
3179 //
3180 // Add the first TextOut to the QueryData array and ModeMap table
3181 //
3182 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);
3183
3184 //
3185 // Now add one by one
3186 //
3187 Index = 1;
3188 Private->CurrentNumberOfConsoles = 1;
3189 TextOutList++;
3190 while ((UINTN) Index < CurrentNumOfConsoles) {
3191 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);
3192 Index++;
3193 Private->CurrentNumberOfConsoles++;
3194 TextOutList++;
3195 }
3196
3197 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3198
3199 return Status;
3200 }
3201
3202
3203 /**
3204 Reset the input device and optionaly run diagnostics
3205
3206 @param This Protocol instance pointer.
3207 @param ExtendedVerification Driver may perform diagnostics on reset.
3208
3209 @retval EFI_SUCCESS The device was reset.
3210 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3211 not be reset.
3212
3213 **/
3214 EFI_STATUS
3215 EFIAPI
3216 ConSplitterTextInReset (
3217 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3218 IN BOOLEAN ExtendedVerification
3219 )
3220 {
3221 EFI_STATUS Status;
3222 EFI_STATUS ReturnStatus;
3223 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3224 UINTN Index;
3225
3226 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3227
3228 Private->KeyEventSignalState = FALSE;
3229
3230 //
3231 // return the worst status met
3232 //
3233 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3234 Status = Private->TextInList[Index]->Reset (
3235 Private->TextInList[Index],
3236 ExtendedVerification
3237 );
3238 if (EFI_ERROR (Status)) {
3239 ReturnStatus = Status;
3240 }
3241 }
3242
3243 return ReturnStatus;
3244 }
3245
3246
3247 /**
3248 Reads the next keystroke from the input device. The WaitForKey Event can
3249 be used to test for existance of a keystroke via WaitForEvent () call.
3250
3251 @param Private Protocol instance pointer.
3252 @param Key Driver may perform diagnostics on reset.
3253
3254 @retval EFI_SUCCESS The keystroke information was returned.
3255 @retval EFI_NOT_READY There was no keystroke data availiable.
3256 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3257 to hardware errors.
3258
3259 **/
3260 EFI_STATUS
3261 EFIAPI
3262 ConSplitterTextInPrivateReadKeyStroke (
3263 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
3264 OUT EFI_INPUT_KEY *Key
3265 )
3266 {
3267 EFI_STATUS Status;
3268 UINTN Index;
3269 EFI_INPUT_KEY CurrentKey;
3270
3271 Key->UnicodeChar = 0;
3272 Key->ScanCode = SCAN_NULL;
3273
3274 //
3275 // if no physical console input device exists, return EFI_NOT_READY;
3276 // if any physical console input device has key input,
3277 // return the key and EFI_SUCCESS.
3278 //
3279 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
3280 Status = Private->TextInList[Index]->ReadKeyStroke (
3281 Private->TextInList[Index],
3282 &CurrentKey
3283 );
3284 if (!EFI_ERROR (Status)) {
3285 *Key = CurrentKey;
3286 return Status;
3287 }
3288 }
3289
3290 return EFI_NOT_READY;
3291 }
3292
3293
3294 /**
3295 Reads the next keystroke from the input device. The WaitForKey Event can
3296 be used to test for existance of a keystroke via WaitForEvent () call.
3297
3298 @param This Protocol instance pointer.
3299 @param Key Driver may perform diagnostics on reset.
3300
3301 @retval EFI_SUCCESS The keystroke information was returned.
3302 @retval EFI_NOT_READY There was no keystroke data availiable.
3303 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3304 to hardware errors.
3305
3306 **/
3307 EFI_STATUS
3308 EFIAPI
3309 ConSplitterTextInReadKeyStroke (
3310 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3311 OUT EFI_INPUT_KEY *Key
3312 )
3313 {
3314 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3315
3316 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3317
3318 Private->KeyEventSignalState = FALSE;
3319
3320 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
3321 }
3322
3323
3324 /**
3325 This event aggregates all the events of the ConIn devices in the spliter.
3326
3327 If any events of physical ConIn devices are signaled, signal the ConIn
3328 spliter event. This will cause the calling code to call
3329 ConSplitterTextInReadKeyStroke ().
3330
3331 @param Event The Event assoicated with callback.
3332 @param Context Context registered when Event was created.
3333
3334 **/
3335 VOID
3336 EFIAPI
3337 ConSplitterTextInWaitForKey (
3338 IN EFI_EVENT Event,
3339 IN VOID *Context
3340 )
3341 {
3342 EFI_STATUS Status;
3343 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3344 UINTN Index;
3345
3346 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
3347
3348 if (Private->KeyEventSignalState) {
3349 //
3350 // If KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3351 //
3352 gBS->SignalEvent (Event);
3353 return ;
3354 }
3355
3356 //
3357 // If any physical console input device has key input, signal the event.
3358 //
3359 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
3360 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);
3361 if (!EFI_ERROR (Status)) {
3362 gBS->SignalEvent (Event);
3363 Private->KeyEventSignalState = TRUE;
3364 }
3365 }
3366 }
3367
3368
3369
3370 /**
3371 Test if the key has been registered on input device.
3372
3373 @param RegsiteredData A pointer to a buffer that is filled in with the
3374 keystroke state data for the key that was
3375 registered.
3376 @param InputData A pointer to a buffer that is filled in with the
3377 keystroke state data for the key that was
3378 pressed.
3379
3380 @retval TRUE Key be pressed matches a registered key.
3381 @retval FLASE Match failed.
3382
3383 **/
3384 BOOLEAN
3385 IsKeyRegistered (
3386 IN EFI_KEY_DATA *RegsiteredData,
3387 IN EFI_KEY_DATA *InputData
3388 )
3389 {
3390 ASSERT (RegsiteredData != NULL && InputData != NULL);
3391
3392 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
3393 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
3394 return FALSE;
3395 }
3396
3397 //
3398 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3399 //
3400 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
3401 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
3402 return FALSE;
3403 }
3404 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
3405 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
3406 return FALSE;
3407 }
3408
3409 return TRUE;
3410
3411 }
3412
3413
3414 /**
3415 Reset the input device and optionaly run diagnostics
3416
3417 @param This Protocol instance pointer.
3418 @param ExtendedVerification Driver may perform diagnostics on reset.
3419
3420 @retval EFI_SUCCESS The device was reset.
3421 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3422 not be reset.
3423
3424 **/
3425 EFI_STATUS
3426 EFIAPI
3427 ConSplitterTextInResetEx (
3428 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3429 IN BOOLEAN ExtendedVerification
3430 )
3431 {
3432 EFI_STATUS Status;
3433 EFI_STATUS ReturnStatus;
3434 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3435 UINTN Index;
3436
3437 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3438
3439 Private->KeyEventSignalState = FALSE;
3440
3441 //
3442 // return the worst status met
3443 //
3444 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {
3445 Status = Private->TextInExList[Index]->Reset (
3446 Private->TextInExList[Index],
3447 ExtendedVerification
3448 );
3449 if (EFI_ERROR (Status)) {
3450 ReturnStatus = Status;
3451 }
3452 }
3453
3454 return ReturnStatus;
3455
3456 }
3457
3458
3459 /**
3460 Reads the next keystroke from the input device. The WaitForKey Event can
3461 be used to test for existance of a keystroke via WaitForEvent () call.
3462
3463 @param This Protocol instance pointer.
3464 @param KeyData A pointer to a buffer that is filled in with the
3465 keystroke state data for the key that was
3466 pressed.
3467
3468 @retval EFI_SUCCESS The keystroke information was returned.
3469 @retval EFI_NOT_READY There was no keystroke data availiable.
3470 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
3471 to hardware errors.
3472 @retval EFI_INVALID_PARAMETER KeyData is NULL.
3473
3474 **/
3475 EFI_STATUS
3476 EFIAPI
3477 ConSplitterTextInReadKeyStrokeEx (
3478 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3479 OUT EFI_KEY_DATA *KeyData
3480 )
3481 {
3482 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3483 EFI_STATUS Status;
3484 UINTN Index;
3485 EFI_KEY_DATA CurrentKeyData;
3486
3487
3488 if (KeyData == NULL) {
3489 return EFI_INVALID_PARAMETER;
3490 }
3491
3492 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3493
3494 Private->KeyEventSignalState = FALSE;
3495
3496 KeyData->Key.UnicodeChar = 0;
3497 KeyData->Key.ScanCode = SCAN_NULL;
3498
3499 //
3500 // if no physical console input device exists, return EFI_NOT_READY;
3501 // if any physical console input device has key input,
3502 // return the key and EFI_SUCCESS.
3503 //
3504 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3505 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (
3506 Private->TextInExList[Index],
3507 &CurrentKeyData
3508 );
3509 if (!EFI_ERROR (Status)) {
3510 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));
3511 return Status;
3512 }
3513 }
3514
3515 return EFI_NOT_READY;
3516 }
3517
3518
3519 /**
3520 Set certain state for the input device.
3521
3522 @param This Protocol instance pointer.
3523 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
3524 state for the input device.
3525
3526 @retval EFI_SUCCESS The device state was set successfully.
3527 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3528 could not have the setting adjusted.
3529 @retval EFI_UNSUPPORTED The device does not have the ability to set its
3530 state.
3531 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
3532
3533 **/
3534 EFI_STATUS
3535 EFIAPI
3536 ConSplitterTextInSetState (
3537 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3538 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
3539 )
3540 {
3541 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3542 EFI_STATUS Status;
3543 UINTN Index;
3544
3545 if (KeyToggleState == NULL) {
3546 return EFI_INVALID_PARAMETER;
3547 }
3548
3549 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3550
3551 //
3552 // if no physical console input device exists, return EFI_SUCCESS;
3553 // otherwise return the status of setting state of physical console input device
3554 //
3555 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3556 Status = Private->TextInExList[Index]->SetState (
3557 Private->TextInExList[Index],
3558 KeyToggleState
3559 );
3560 if (EFI_ERROR (Status)) {
3561 return Status;
3562 }
3563 }
3564
3565 return EFI_SUCCESS;
3566
3567 }
3568
3569
3570 /**
3571 Register a notification function for a particular keystroke for the input device.
3572
3573 @param This Protocol instance pointer.
3574 @param KeyData A pointer to a buffer that is filled in with the
3575 keystroke information data for the key that was
3576 pressed.
3577 @param KeyNotificationFunction Points to the function to be called when the key
3578 sequence is typed specified by KeyData.
3579 @param NotifyHandle Points to the unique handle assigned to the
3580 registered notification.
3581
3582 @retval EFI_SUCCESS The notification function was registered
3583 successfully.
3584 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
3585 structures.
3586 @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.
3587
3588 **/
3589 EFI_STATUS
3590 EFIAPI
3591 ConSplitterTextInRegisterKeyNotify (
3592 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3593 IN EFI_KEY_DATA *KeyData,
3594 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
3595 OUT EFI_HANDLE *NotifyHandle
3596 )
3597 {
3598 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3599 EFI_STATUS Status;
3600 UINTN Index;
3601 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;
3602 LIST_ENTRY *Link;
3603 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3604
3605
3606 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
3607 return EFI_INVALID_PARAMETER;
3608 }
3609
3610 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3611
3612 //
3613 // If no physical console input device exists,
3614 // return EFI_SUCCESS directly.
3615 //
3616 if (Private->CurrentNumberOfExConsoles <= 0) {
3617 return EFI_SUCCESS;
3618 }
3619
3620 //
3621 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3622 //
3623 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3624 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3625 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
3626 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
3627 *NotifyHandle = CurrentNotify->NotifyHandle;
3628 return EFI_SUCCESS;
3629 }
3630 }
3631 }
3632
3633 //
3634 // Allocate resource to save the notification function
3635 //
3636 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));
3637 if (NewNotify == NULL) {
3638 return EFI_OUT_OF_RESOURCES;
3639 }
3640 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);
3641 if (NewNotify->NotifyHandleList == NULL) {
3642 gBS->FreePool (NewNotify);
3643 return EFI_OUT_OF_RESOURCES;
3644 }
3645 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;
3646 NewNotify->KeyNotificationFn = KeyNotificationFunction;
3647 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;
3648 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
3649
3650 //
3651 // Return the wrong status of registering key notify of
3652 // physical console input device if meet problems
3653 //
3654 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3655 Status = Private->TextInExList[Index]->RegisterKeyNotify (
3656 Private->TextInExList[Index],
3657 KeyData,
3658 KeyNotificationFunction,
3659 &NewNotify->NotifyHandleList[Index]
3660 );
3661 if (EFI_ERROR (Status)) {
3662 gBS->FreePool (NewNotify->NotifyHandleList);
3663 gBS->FreePool (NewNotify);
3664 return Status;
3665 }
3666 }
3667
3668 InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);
3669
3670 *NotifyHandle = NewNotify->NotifyHandle;
3671
3672 return EFI_SUCCESS;
3673
3674 }
3675
3676
3677 /**
3678 Remove a registered notification function from a particular keystroke.
3679
3680 @param This Protocol instance pointer.
3681 @param NotificationHandle The handle of the notification function being
3682 unregistered.
3683
3684 @retval EFI_SUCCESS The notification function was unregistered
3685 successfully.
3686 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
3687
3688 **/
3689 EFI_STATUS
3690 EFIAPI
3691 ConSplitterTextInUnregisterKeyNotify (
3692 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3693 IN EFI_HANDLE NotificationHandle
3694 )
3695 {
3696 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3697 EFI_STATUS Status;
3698 UINTN Index;
3699 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3700 LIST_ENTRY *Link;
3701
3702 if (NotificationHandle == NULL) {
3703 return EFI_INVALID_PARAMETER;
3704 }
3705
3706 if (((TEXT_IN_EX_SPLITTER_NOTIFY *) NotificationHandle)->Signature != TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE) {
3707 return EFI_INVALID_PARAMETER;
3708 }
3709
3710 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3711
3712 //
3713 // if no physical console input device exists,
3714 // return EFI_SUCCESS directly.
3715 //
3716 if (Private->CurrentNumberOfExConsoles <= 0) {
3717 return EFI_SUCCESS;
3718 }
3719
3720 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3721 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3722 if (CurrentNotify->NotifyHandle == NotificationHandle) {
3723 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3724 Status = Private->TextInExList[Index]->UnregisterKeyNotify (
3725 Private->TextInExList[Index],
3726 CurrentNotify->NotifyHandleList[Index]
3727 );
3728 if (EFI_ERROR (Status)) {
3729 return Status;
3730 }
3731 }
3732 RemoveEntryList (&CurrentNotify->NotifyEntry);
3733
3734 gBS->FreePool (CurrentNotify->NotifyHandleList);
3735 gBS->FreePool (CurrentNotify);
3736 return EFI_SUCCESS;
3737 }
3738 }
3739
3740 //
3741 // NotificationHandle is not found in database
3742 //
3743 return EFI_INVALID_PARAMETER;
3744 }
3745
3746
3747 /**
3748 Reset the input device and optionaly run diagnostics
3749
3750 @param This Protocol instance pointer.
3751 @param ExtendedVerification Driver may perform diagnostics on reset.
3752
3753 @retval EFI_SUCCESS The device was reset.
3754 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3755 not be reset.
3756
3757 **/
3758 EFI_STATUS
3759 EFIAPI
3760 ConSplitterSimplePointerReset (
3761 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
3762 IN BOOLEAN ExtendedVerification
3763 )
3764 {
3765 EFI_STATUS Status;
3766 EFI_STATUS ReturnStatus;
3767 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3768 UINTN Index;
3769
3770 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
3771
3772 Private->InputEventSignalState = FALSE;
3773
3774 if (Private->CurrentNumberOfPointers == 0) {
3775 return EFI_SUCCESS;
3776 }
3777 //
3778 // return the worst status met
3779 //
3780 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {
3781 Status = Private->PointerList[Index]->Reset (
3782 Private->PointerList[Index],
3783 ExtendedVerification
3784 );
3785 if (EFI_ERROR (Status)) {
3786 ReturnStatus = Status;
3787 }
3788 }
3789
3790 return ReturnStatus;
3791 }
3792
3793
3794 /**
3795 Reads the next keystroke from the input device. The WaitForKey Event can
3796 be used to test for existance of a keystroke via WaitForEvent () call.
3797
3798 @param Private Protocol instance pointer.
3799 @param State The state information of simple pointer device.
3800
3801 @retval EFI_SUCCESS The keystroke information was returned.
3802 @retval EFI_NOT_READY There was no keystroke data availiable.
3803 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3804 to hardware errors.
3805
3806 **/
3807 EFI_STATUS
3808 EFIAPI
3809 ConSplitterSimplePointerPrivateGetState (
3810 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
3811 IN OUT EFI_SIMPLE_POINTER_STATE *State
3812 )
3813 {
3814 EFI_STATUS Status;
3815 EFI_STATUS ReturnStatus;
3816 UINTN Index;
3817 EFI_SIMPLE_POINTER_STATE CurrentState;
3818
3819 State->RelativeMovementX = 0;
3820 State->RelativeMovementY = 0;
3821 State->RelativeMovementZ = 0;
3822 State->LeftButton = FALSE;
3823 State->RightButton = FALSE;
3824
3825 //
3826 // if no physical console input device exists, return EFI_NOT_READY;
3827 // if any physical console input device has key input,
3828 // return the key and EFI_SUCCESS.
3829 //
3830 ReturnStatus = EFI_NOT_READY;
3831 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
3832
3833 Status = Private->PointerList[Index]->GetState (
3834 Private->PointerList[Index],
3835 &CurrentState
3836 );
3837 if (!EFI_ERROR (Status)) {
3838 if (ReturnStatus == EFI_NOT_READY) {
3839 ReturnStatus = EFI_SUCCESS;
3840 }
3841
3842 if (CurrentState.LeftButton) {
3843 State->LeftButton = TRUE;
3844 }
3845
3846 if (CurrentState.RightButton) {
3847 State->RightButton = TRUE;
3848 }
3849
3850 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {
3851 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;
3852 }
3853
3854 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {
3855 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;
3856 }
3857
3858 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {
3859 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;
3860 }
3861 } else if (Status == EFI_DEVICE_ERROR) {
3862 ReturnStatus = EFI_DEVICE_ERROR;
3863 }
3864 }
3865
3866 return ReturnStatus;
3867 }
3868
3869
3870 /**
3871 Reads the next keystroke from the input device. The WaitForKey Event can
3872 be used to test for existance of a keystroke via WaitForEvent () call.
3873
3874 @param This A pointer to protocol instance.
3875 @param State A pointer to state information on the pointer device
3876
3877 @retval EFI_SUCCESS The keystroke information was returned in State.
3878 @retval EFI_NOT_READY There was no keystroke data availiable.
3879 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3880 to hardware errors.
3881
3882 **/
3883 EFI_STATUS
3884 EFIAPI
3885 ConSplitterSimplePointerGetState (
3886 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
3887 IN OUT EFI_SIMPLE_POINTER_STATE *State
3888 )
3889 {
3890 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3891
3892 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
3893
3894 Private->InputEventSignalState = FALSE;
3895
3896 return ConSplitterSimplePointerPrivateGetState (Private, State);
3897 }
3898
3899
3900 /**
3901 This event agregates all the events of the ConIn devices in the spliter.
3902 If any events of physical ConIn devices are signaled, signal the ConIn
3903 spliter event. This will cause the calling code to call
3904 ConSplitterTextInReadKeyStroke ().
3905
3906 @param Event The Event assoicated with callback.
3907 @param Context Context registered when Event was created.
3908
3909 **/
3910 VOID
3911 EFIAPI
3912 ConSplitterSimplePointerWaitForInput (
3913 IN EFI_EVENT Event,
3914 IN VOID *Context
3915 )
3916 {
3917 EFI_STATUS Status;
3918 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3919 UINTN Index;
3920
3921 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
3922
3923 //
3924 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3925 //
3926 if (Private->InputEventSignalState) {
3927 gBS->SignalEvent (Event);
3928 return ;
3929 }
3930 //
3931 // if any physical console input device has key input, signal the event.
3932 //
3933 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
3934 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);
3935 if (!EFI_ERROR (Status)) {
3936 gBS->SignalEvent (Event);
3937 Private->InputEventSignalState = TRUE;
3938 }
3939 }
3940 }
3941
3942 /**
3943 Resets the pointer device hardware.
3944
3945 @param This Protocol instance pointer.
3946 @param ExtendedVerification Driver may perform diagnostics on reset.
3947
3948 @retval EFI_SUCCESS The device was reset.
3949 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3950 could not be reset.
3951
3952 **/
3953 EFI_STATUS
3954 EFIAPI
3955 ConSplitterAbsolutePointerReset (
3956 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
3957 IN BOOLEAN ExtendedVerification
3958 )
3959 {
3960 EFI_STATUS Status;
3961 EFI_STATUS ReturnStatus;
3962 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3963 UINTN Index;
3964
3965 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
3966
3967 Private->AbsoluteInputEventSignalState = FALSE;
3968
3969 if (Private->CurrentNumberOfAbsolutePointers == 0) {
3970 return EFI_SUCCESS;
3971 }
3972 //
3973 // return the worst status met
3974 //
3975 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
3976 Status = Private->AbsolutePointerList[Index]->Reset (
3977 Private->AbsolutePointerList[Index],
3978 ExtendedVerification
3979 );
3980 if (EFI_ERROR (Status)) {
3981 ReturnStatus = Status;
3982 }
3983 }
3984
3985 return ReturnStatus;
3986 }
3987
3988
3989 /**
3990 Retrieves the current state of a pointer device.
3991
3992 @param This Protocol instance pointer.
3993 @param State A pointer to the state information on the
3994 pointer device.
3995
3996 @retval EFI_SUCCESS The state of the pointer device was returned in
3997 State..
3998 @retval EFI_NOT_READY The state of the pointer device has not changed
3999 since the last call to GetState().
4000 @retval EFI_DEVICE_ERROR A device error occurred while attempting to
4001 retrieve the pointer device's current state.
4002
4003 **/
4004 EFI_STATUS
4005 EFIAPI
4006 ConSplitterAbsolutePointerGetState (
4007 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
4008 IN OUT EFI_ABSOLUTE_POINTER_STATE *State
4009 )
4010 {
4011 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4012 EFI_STATUS Status;
4013 EFI_STATUS ReturnStatus;
4014 UINTN Index;
4015 EFI_ABSOLUTE_POINTER_STATE CurrentState;
4016
4017
4018 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
4019
4020 Private->AbsoluteInputEventSignalState = FALSE;
4021
4022 State->CurrentX = 0;
4023 State->CurrentY = 0;
4024 State->CurrentZ = 0;
4025 State->ActiveButtons = 0;
4026
4027 //
4028 // if no physical pointer device exists, return EFI_NOT_READY;
4029 // if any physical pointer device has changed state,
4030 // return the state and EFI_SUCCESS.
4031 //
4032 ReturnStatus = EFI_NOT_READY;
4033 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4034
4035 Status = Private->AbsolutePointerList[Index]->GetState (
4036 Private->AbsolutePointerList[Index],
4037 &CurrentState
4038 );
4039 if (!EFI_ERROR (Status)) {
4040 if (ReturnStatus == EFI_NOT_READY) {
4041 ReturnStatus = EFI_SUCCESS;
4042 }
4043
4044 State->ActiveButtons = CurrentState.ActiveButtons;
4045
4046 if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {
4047 State->CurrentX = CurrentState.CurrentX;
4048 }
4049 if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {
4050 State->CurrentY = CurrentState.CurrentY;
4051 }
4052 if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {
4053 State->CurrentZ = CurrentState.CurrentZ;
4054 }
4055
4056 } else if (Status == EFI_DEVICE_ERROR) {
4057 ReturnStatus = EFI_DEVICE_ERROR;
4058 }
4059 }
4060
4061 return ReturnStatus;
4062 }
4063
4064
4065 /**
4066 This event agregates all the events of the pointer devices in the splitter.
4067 If any events of physical pointer devices are signaled, signal the pointer
4068 splitter event. This will cause the calling code to call
4069 ConSplitterAbsolutePointerGetState ().
4070
4071 @param Event The Event assoicated with callback.
4072 @param Context Context registered when Event was created.
4073
4074 **/
4075 VOID
4076 EFIAPI
4077 ConSplitterAbsolutePointerWaitForInput (
4078 IN EFI_EVENT Event,
4079 IN VOID *Context
4080 )
4081 {
4082 EFI_STATUS Status;
4083 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4084 UINTN Index;
4085
4086 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
4087
4088 //
4089 // if AbsoluteInputEventSignalState is flagged before,
4090 // and not cleared by Reset() or GetState(), signal it
4091 //
4092 if (Private->AbsoluteInputEventSignalState) {
4093 gBS->SignalEvent (Event);
4094 return ;
4095 }
4096 //
4097 // if any physical console input device has key input, signal the event.
4098 //
4099 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4100 Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);
4101 if (!EFI_ERROR (Status)) {
4102 gBS->SignalEvent (Event);
4103 Private->AbsoluteInputEventSignalState = TRUE;
4104 }
4105 }
4106 }
4107
4108
4109 /**
4110 Reset the text output device hardware and optionaly run diagnostics
4111
4112 @param This Protocol instance pointer.
4113 @param ExtendedVerification Driver may perform more exhaustive verfication
4114 operation of the device during reset.
4115
4116 @retval EFI_SUCCESS The text output device was reset.
4117 @retval EFI_DEVICE_ERROR The text output device is not functioning
4118 correctly and could not be reset.
4119
4120 **/
4121 EFI_STATUS
4122 EFIAPI
4123 ConSplitterTextOutReset (
4124 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4125 IN BOOLEAN ExtendedVerification
4126 )
4127 {
4128 EFI_STATUS Status;
4129 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4130 UINTN Index;
4131 EFI_STATUS ReturnStatus;
4132
4133 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4134
4135 //
4136 // return the worst status met
4137 //
4138 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4139 Status = Private->TextOutList[Index].TextOut->Reset (
4140 Private->TextOutList[Index].TextOut,
4141 ExtendedVerification
4142 );
4143 if (EFI_ERROR (Status)) {
4144 ReturnStatus = Status;
4145 }
4146 }
4147
4148 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));
4149
4150 //
4151 // reset all mode parameters
4152 //
4153 TextOutSetMode (Private, 0);
4154
4155 return ReturnStatus;
4156 }
4157
4158
4159 /**
4160 Write a Unicode string to the output device.
4161
4162 @param This Protocol instance pointer.
4163 @param WString The NULL-terminated Unicode string to be
4164 displayed on the output device(s). All output
4165 devices must also support the Unicode drawing
4166 defined in this file.
4167
4168 @retval EFI_SUCCESS The string was output to the device.
4169 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
4170 output the text.
4171 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
4172 defined text mode.
4173 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
4174 characters in the Unicode string could not be
4175 rendered and were skipped.
4176
4177 **/
4178 EFI_STATUS
4179 EFIAPI
4180 ConSplitterTextOutOutputString (
4181 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4182 IN CHAR16 *WString
4183 )
4184 {
4185 EFI_STATUS Status;
4186 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4187 UINTN Index;
4188 UINTN BackSpaceCount;
4189 EFI_STATUS ReturnStatus;
4190 CHAR16 *TargetString;
4191
4192 This->SetAttribute (This, This->Mode->Attribute);
4193
4194 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4195
4196 BackSpaceCount = 0;
4197
4198 for (TargetString = WString; *TargetString != L'\0'; TargetString++) {
4199 if (*TargetString == CHAR_BACKSPACE) {
4200 BackSpaceCount++;
4201 }
4202 }
4203
4204 if (BackSpaceCount == 0) {
4205 TargetString = WString;
4206 } else {
4207 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));
4208 ASSERT (TargetString != NULL);
4209
4210 StrCpy (TargetString, WString);
4211 }
4212 //
4213 // return the worst status met
4214 //
4215 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4216 Status = Private->TextOutList[Index].TextOut->OutputString (
4217 Private->TextOutList[Index].TextOut,
4218 TargetString
4219 );
4220 if (EFI_ERROR (Status)) {
4221 ReturnStatus = Status;
4222 }
4223 }
4224
4225 if (Private->CurrentNumberOfConsoles > 0) {
4226 Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;
4227 Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;
4228 }
4229
4230 if (BackSpaceCount > 0) {
4231 FreePool (TargetString);
4232 }
4233
4234 return ReturnStatus;
4235 }
4236
4237
4238 /**
4239 Verifies that all characters in a Unicode string can be output to the
4240 target device.
4241
4242 @param This Protocol instance pointer.
4243 @param WString The NULL-terminated Unicode string to be
4244 examined for the output device(s).
4245
4246 @retval EFI_SUCCESS The device(s) are capable of rendering the
4247 output string.
4248 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string
4249 cannot be rendered by one or more of the output
4250 devices mapped by the EFI handle.
4251
4252 **/
4253 EFI_STATUS
4254 EFIAPI
4255 ConSplitterTextOutTestString (
4256 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4257 IN CHAR16 *WString
4258 )
4259 {
4260 EFI_STATUS Status;
4261 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4262 UINTN Index;
4263 EFI_STATUS ReturnStatus;
4264
4265 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4266
4267 //
4268 // return the worst status met
4269 //
4270 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4271 Status = Private->TextOutList[Index].TextOut->TestString (
4272 Private->TextOutList[Index].TextOut,
4273 WString
4274 );
4275 if (EFI_ERROR (Status)) {
4276 ReturnStatus = Status;
4277 }
4278 }
4279 //
4280 // There is no DevNullTextOutTestString () since a Unicode buffer would
4281 // always return EFI_SUCCESS.
4282 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4283 //
4284 return ReturnStatus;
4285 }
4286
4287
4288 /**
4289 Returns information for an available text mode that the output device(s)
4290 supports.
4291
4292 @param This Protocol instance pointer.
4293 @param ModeNumber The mode number to return information on.
4294 @param Columns Returns the columns of the text output device
4295 for the requested ModeNumber.
4296 @param Rows Returns the rows of the text output device
4297 for the requested ModeNumber.
4298
4299 @retval EFI_SUCCESS The requested mode information was returned.
4300 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4301 the request.
4302 @retval EFI_UNSUPPORTED The mode number was not valid.
4303
4304 **/
4305 EFI_STATUS
4306 EFIAPI
4307 ConSplitterTextOutQueryMode (
4308 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4309 IN UINTN ModeNumber,
4310 OUT UINTN *Columns,
4311 OUT UINTN *Rows
4312 )
4313 {
4314 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4315 UINTN CurrentMode;
4316 INT32 *TextOutModeMap;
4317
4318 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4319
4320 //
4321 // Check whether param ModeNumber is valid.
4322 // ModeNumber should be within range 0 ~ MaxMode - 1.
4323 //
4324 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4325 return EFI_UNSUPPORTED;
4326 }
4327
4328 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4329 return EFI_UNSUPPORTED;
4330 }
4331
4332 //
4333 // We get the available mode from mode intersection map if it's available
4334 //
4335 if (Private->TextOutModeMap != NULL) {
4336 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4337 CurrentMode = (UINTN)(*TextOutModeMap);
4338 *Columns = Private->TextOutQueryData[CurrentMode].Columns;
4339 *Rows = Private->TextOutQueryData[CurrentMode].Rows;
4340 } else {
4341 *Columns = Private->TextOutQueryData[ModeNumber].Columns;
4342 *Rows = Private->TextOutQueryData[ModeNumber].Rows;
4343 }
4344
4345 if (*Columns <= 0 && *Rows <= 0) {
4346 return EFI_UNSUPPORTED;
4347
4348 }
4349
4350 return EFI_SUCCESS;
4351 }
4352
4353
4354 /**
4355 Sets the output device(s) to a specified mode.
4356
4357 @param This Protocol instance pointer.
4358 @param ModeNumber The mode number to set.
4359
4360 @retval EFI_SUCCESS The requested text mode was set.
4361 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4362 the request.
4363 @retval EFI_UNSUPPORTED The mode number was not valid.
4364
4365 **/
4366 EFI_STATUS
4367 EFIAPI
4368 ConSplitterTextOutSetMode (
4369 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4370 IN UINTN ModeNumber
4371 )
4372 {
4373 EFI_STATUS Status;
4374 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4375 UINTN Index;
4376 INT32 *TextOutModeMap;
4377 EFI_STATUS ReturnStatus;
4378
4379 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4380
4381 //
4382 // Check whether param ModeNumber is valid.
4383 // ModeNumber should be within range 0 ~ MaxMode - 1.
4384 //
4385 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4386 return EFI_UNSUPPORTED;
4387 }
4388
4389 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4390 return EFI_UNSUPPORTED;
4391 }
4392 //
4393 // If the mode is being set to the curent mode, then just clear the screen and return.
4394 //
4395 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {
4396 return ConSplitterTextOutClearScreen (This);
4397 }
4398 //
4399 // return the worst status met
4400 //
4401 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4402 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4403 Status = Private->TextOutList[Index].TextOut->SetMode (
4404 Private->TextOutList[Index].TextOut,
4405 TextOutModeMap[Index]
4406 );
4407 if (EFI_ERROR (Status)) {
4408 ReturnStatus = Status;
4409 }
4410 }
4411
4412 //
4413 // Set mode parameter to specified mode number
4414 //
4415 TextOutSetMode (Private, ModeNumber);
4416
4417 return ReturnStatus;
4418 }
4419
4420
4421 /**
4422 Sets the background and foreground colors for the OutputString () and
4423 ClearScreen () functions.
4424
4425 @param This Protocol instance pointer.
4426 @param Attribute The attribute to set. Bits 0..3 are the
4427 foreground color, and bits 4..6 are the
4428 background color. All other bits are undefined
4429 and must be zero. The valid Attributes are
4430 defined in this file.
4431
4432 @retval EFI_SUCCESS The attribute was set.
4433 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4434 the request.
4435 @retval EFI_UNSUPPORTED The attribute requested is not defined.
4436
4437 **/
4438 EFI_STATUS
4439 EFIAPI
4440 ConSplitterTextOutSetAttribute (
4441 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4442 IN UINTN Attribute
4443 )
4444 {
4445 EFI_STATUS Status;
4446 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4447 UINTN Index;
4448 EFI_STATUS ReturnStatus;
4449
4450 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4451
4452 //
4453 // Check whether param Attribute is valid.
4454 //
4455 if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {
4456 return EFI_UNSUPPORTED;
4457 }
4458
4459 //
4460 // return the worst status met
4461 //
4462 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4463 Status = Private->TextOutList[Index].TextOut->SetAttribute (
4464 Private->TextOutList[Index].TextOut,
4465 Attribute
4466 );
4467 if (EFI_ERROR (Status)) {
4468 ReturnStatus = Status;
4469 }
4470 }
4471
4472 Private->TextOutMode.Attribute = (INT32) Attribute;
4473
4474 return ReturnStatus;
4475 }
4476
4477
4478 /**
4479 Clears the output device(s) display to the currently selected background
4480 color.
4481
4482 @param This Protocol instance pointer.
4483
4484 @retval EFI_SUCCESS The operation completed successfully.
4485 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4486 the request.
4487 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4488
4489 **/
4490 EFI_STATUS
4491 EFIAPI
4492 ConSplitterTextOutClearScreen (
4493 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
4494 )
4495 {
4496 EFI_STATUS Status;
4497 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4498 UINTN Index;
4499 EFI_STATUS ReturnStatus;
4500
4501 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4502
4503 //
4504 // return the worst status met
4505 //
4506 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4507 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);
4508 if (EFI_ERROR (Status)) {
4509 ReturnStatus = Status;
4510 }
4511 }
4512
4513 //
4514 // No need to do extra check here as whether (Column, Row) is valid has
4515 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4516 // always be supported.
4517 //
4518 Private->TextOutMode.CursorColumn = 0;
4519 Private->TextOutMode.CursorRow = 0;
4520 Private->TextOutMode.CursorVisible = TRUE;
4521
4522 return ReturnStatus;
4523 }
4524
4525
4526 /**
4527 Sets the current coordinates of the cursor position
4528
4529 @param This Protocol instance pointer.
4530 @param Column The column position to set the cursor to. Must be
4531 greater than or equal to zero and less than the
4532 number of columns by QueryMode ().
4533 @param Row The row position to set the cursor to. Must be
4534 greater than or equal to zero and less than the
4535 number of rows by QueryMode ().
4536
4537 @retval EFI_SUCCESS The operation completed successfully.
4538 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4539 the request.
4540 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,
4541 or the cursor position is invalid for the
4542 current mode.
4543
4544 **/
4545 EFI_STATUS
4546 EFIAPI
4547 ConSplitterTextOutSetCursorPosition (
4548 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4549 IN UINTN Column,
4550 IN UINTN Row
4551 )
4552 {
4553 EFI_STATUS Status;
4554 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4555 UINTN Index;
4556 EFI_STATUS ReturnStatus;
4557 UINTN MaxColumn;
4558 UINTN MaxRow;
4559 INT32 *TextOutModeMap;
4560 INT32 ModeNumber;
4561 INT32 CurrentMode;
4562
4563 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4564 TextOutModeMap = NULL;
4565 ModeNumber = Private->TextOutMode.Mode;
4566
4567 //
4568 // Get current MaxColumn and MaxRow from intersection map
4569 //
4570 if (Private->TextOutModeMap != NULL) {
4571 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4572 CurrentMode = *TextOutModeMap;
4573 } else {
4574 CurrentMode = ModeNumber;
4575 }
4576
4577 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;
4578 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;
4579
4580 if (Column >= MaxColumn || Row >= MaxRow) {
4581 return EFI_UNSUPPORTED;
4582 }
4583 //
4584 // return the worst status met
4585 //
4586 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4587 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (
4588 Private->TextOutList[Index].TextOut,
4589 Column,
4590 Row
4591 );
4592 if (EFI_ERROR (Status)) {
4593 ReturnStatus = Status;
4594 }
4595 }
4596
4597 //
4598 // No need to do extra check here as whether (Column, Row) is valid has
4599 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4600 // always be supported.
4601 //
4602 Private->TextOutMode.CursorColumn = (INT32) Column;
4603 Private->TextOutMode.CursorRow = (INT32) Row;
4604
4605 return ReturnStatus;
4606 }
4607
4608
4609 /**
4610 Makes the cursor visible or invisible
4611
4612 @param This Protocol instance pointer.
4613 @param Visible If TRUE, the cursor is set to be visible. If
4614 FALSE, the cursor is set to be invisible.
4615
4616 @retval EFI_SUCCESS The operation completed successfully.
4617 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4618 the request, or the device does not support
4619 changing the cursor mode.
4620 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4621
4622 **/
4623 EFI_STATUS
4624 EFIAPI
4625 ConSplitterTextOutEnableCursor (
4626 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4627 IN BOOLEAN Visible
4628 )
4629 {
4630 EFI_STATUS Status;
4631 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4632 UINTN Index;
4633 EFI_STATUS ReturnStatus;
4634
4635 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4636
4637 //
4638 // return the worst status met
4639 //
4640 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4641 Status = Private->TextOutList[Index].TextOut->EnableCursor (
4642 Private->TextOutList[Index].TextOut,
4643 Visible
4644 );
4645 if (EFI_ERROR (Status)) {
4646 ReturnStatus = Status;
4647 }
4648 }
4649
4650 Private->TextOutMode.CursorVisible = Visible;
4651
4652 return ReturnStatus;
4653 }
4654