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