]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
Change the type of NotifyHandle from EFI_HANDLE to VOID * for SimpleTextInEx protocol.
[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 ElementSize and grow the buffer
1712 by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.
1713 Copy the current data in Buffer to the new version of Buffer and
1714 free the old version of buffer.
1715
1716 @param ElementSize 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 ElementSize,
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 Ptr = ReallocatePool (
1740 ElementSize * (*Count),
1741 ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT),
1742 *Buffer
1743 );
1744 if (Ptr == NULL) {
1745 return EFI_OUT_OF_RESOURCES;
1746 }
1747 *Count += CONSOLE_SPLITTER_ALLOC_UNIT;
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 LIST_ENTRY *Link;
1852 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
1853 UINTN TextInExListCount;
1854
1855 //
1856 // Enlarge the NotifyHandleList and the TextInExList
1857 //
1858 if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {
1859 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
1860 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1861 TextInExListCount = Private->TextInExListCount;
1862
1863 Status = ConSplitterGrowBuffer (
1864 sizeof (EFI_HANDLE),
1865 &TextInExListCount,
1866 (VOID **) &CurrentNotify->NotifyHandleList
1867 );
1868 if (EFI_ERROR (Status)) {
1869 return EFI_OUT_OF_RESOURCES;
1870 }
1871 }
1872 Status = ConSplitterGrowBuffer (
1873 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),
1874 &Private->TextInExListCount,
1875 (VOID **) &Private->TextInExList
1876 );
1877 if (EFI_ERROR (Status)) {
1878 return EFI_OUT_OF_RESOURCES;
1879 }
1880 }
1881
1882 //
1883 // Register the key notify in the new text-in device
1884 //
1885 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
1886 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1887 Status = TextInEx->RegisterKeyNotify (
1888 TextInEx,
1889 &CurrentNotify->KeyData,
1890 CurrentNotify->KeyNotificationFn,
1891 &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
1892 );
1893 if (EFI_ERROR (Status)) {
1894 for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) {
1895 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
1896 TextInEx->UnregisterKeyNotify (
1897 TextInEx,
1898 CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]
1899 );
1900 }
1901 return Status;
1902 }
1903 }
1904
1905 //
1906 // Add the new text-in device data structure into the Text Input Ex List.
1907 //
1908 Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;
1909 Private->CurrentNumberOfExConsoles++;
1910
1911 //
1912 // Extra CheckEvent added to reduce the double CheckEvent().
1913 //
1914 gBS->CheckEvent (TextInEx->WaitForKeyEx);
1915
1916 return EFI_SUCCESS;
1917 }
1918
1919 /**
1920 Remove Text Ex Device from Consplitter Text Input Ex list.
1921
1922 @param Private Text In Splitter pointer.
1923 @param TextInEx Simple Text Ex protocol pointer.
1924
1925 @retval EFI_SUCCESS Simple Text Input Ex Device removed successfully.
1926 @retval EFI_NOT_FOUND No Simple Text Input Ex Device found.
1927
1928 **/
1929 EFI_STATUS
1930 ConSplitterTextInExDeleteDevice (
1931 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1932 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
1933 )
1934 {
1935 UINTN Index;
1936 //
1937 // Remove the specified text-in device data structure from the Text Input Ex List,
1938 // and rearrange the remaining data structures in the Text In List.
1939 //
1940 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
1941 if (Private->TextInExList[Index] == TextInEx) {
1942 for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {
1943 Private->TextInExList[Index] = Private->TextInExList[Index + 1];
1944 }
1945
1946 Private->CurrentNumberOfExConsoles--;
1947 return EFI_SUCCESS;
1948 }
1949 }
1950
1951 return EFI_NOT_FOUND;
1952 }
1953
1954
1955 /**
1956 Add Simple Pointer Device in Consplitter Simple Pointer list.
1957
1958 @param Private Text In Splitter pointer.
1959 @param SimplePointer Simple Pointer protocol pointer.
1960
1961 @retval EFI_SUCCESS Simple Pointer Device added successfully.
1962 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
1963
1964 **/
1965 EFI_STATUS
1966 ConSplitterSimplePointerAddDevice (
1967 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1968 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
1969 )
1970 {
1971 EFI_STATUS Status;
1972
1973 //
1974 // If the Simple Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
1975 //
1976 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {
1977 Status = ConSplitterGrowBuffer (
1978 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
1979 &Private->PointerListCount,
1980 (VOID **) &Private->PointerList
1981 );
1982 if (EFI_ERROR (Status)) {
1983 return EFI_OUT_OF_RESOURCES;
1984 }
1985 }
1986 //
1987 // Add the new text-in device data structure into the Simple Pointer List.
1988 //
1989 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;
1990 Private->CurrentNumberOfPointers++;
1991
1992 return EFI_SUCCESS;
1993 }
1994
1995
1996 /**
1997 Remove Simple Pointer Device from Consplitter Simple Pointer list.
1998
1999 @param Private Text In Splitter pointer.
2000 @param SimplePointer Simple Pointer protocol pointer.
2001
2002 @retval EFI_SUCCESS Simple Pointer Device removed successfully.
2003 @retval EFI_NOT_FOUND No Simple Pointer Device found.
2004
2005 **/
2006 EFI_STATUS
2007 ConSplitterSimplePointerDeleteDevice (
2008 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2009 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
2010 )
2011 {
2012 UINTN Index;
2013 //
2014 // Remove the specified text-in device data structure from the Simple Pointer List,
2015 // and rearrange the remaining data structures in the Text In List.
2016 //
2017 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
2018 if (Private->PointerList[Index] == SimplePointer) {
2019 for (; Index < Private->CurrentNumberOfPointers - 1; Index++) {
2020 Private->PointerList[Index] = Private->PointerList[Index + 1];
2021 }
2022
2023 Private->CurrentNumberOfPointers--;
2024 return EFI_SUCCESS;
2025 }
2026 }
2027
2028 return EFI_NOT_FOUND;
2029 }
2030
2031
2032 /**
2033 Add Absolute Pointer Device in Consplitter Absolute Pointer list.
2034
2035 @param Private Text In Splitter pointer.
2036 @param AbsolutePointer Absolute Pointer protocol pointer.
2037
2038 @retval EFI_SUCCESS Absolute Pointer Device added successfully.
2039 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2040
2041 **/
2042 EFI_STATUS
2043 ConSplitterAbsolutePointerAddDevice (
2044 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2045 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer
2046 )
2047 {
2048 EFI_STATUS Status;
2049
2050 //
2051 // If the Absolute Pointer List is full, enlarge it by calling ConSplitterGrowBuffer().
2052 //
2053 if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {
2054 Status = ConSplitterGrowBuffer (
2055 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),
2056 &Private->AbsolutePointerListCount,
2057 (VOID **) &Private->AbsolutePointerList
2058 );
2059 if (EFI_ERROR (Status)) {
2060 return EFI_OUT_OF_RESOURCES;
2061 }
2062 }
2063 //
2064 // Add the new text-in device data structure into the Absolute Pointer List.
2065 //
2066 Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;
2067 Private->CurrentNumberOfAbsolutePointers++;
2068
2069 return EFI_SUCCESS;
2070 }
2071
2072
2073 /**
2074 Remove Absolute Pointer Device from Consplitter Absolute Pointer list.
2075
2076 @param Private Text In Splitter pointer.
2077 @param AbsolutePointer Absolute Pointer protocol pointer.
2078
2079 @retval EFI_SUCCESS Absolute Pointer Device removed successfully.
2080 @retval EFI_NOT_FOUND No Absolute Pointer Device found.
2081
2082 **/
2083 EFI_STATUS
2084 ConSplitterAbsolutePointerDeleteDevice (
2085 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2086 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer
2087 )
2088 {
2089 UINTN Index;
2090 //
2091 // Remove the specified text-in device data structure from the Absolute Pointer List,
2092 // and rearrange the remaining data structures from the Absolute Pointer List.
2093 //
2094 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
2095 if (Private->AbsolutePointerList[Index] == AbsolutePointer) {
2096 for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {
2097 Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];
2098 }
2099
2100 Private->CurrentNumberOfAbsolutePointers--;
2101 return EFI_SUCCESS;
2102 }
2103 }
2104
2105 return EFI_NOT_FOUND;
2106 }
2107
2108 /**
2109 Reallocate Text Out mode map.
2110
2111 Allocate new buffer and copy original buffer into the new buffer.
2112
2113 @param Private Consplitter Text Out pointer.
2114
2115 @retval EFI_SUCCESS Buffer size has grown
2116 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2117
2118 **/
2119 EFI_STATUS
2120 ConSplitterGrowMapTable (
2121 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
2122 )
2123 {
2124 UINTN Size;
2125 UINTN NewSize;
2126 UINTN TotalSize;
2127 INT32 *TextOutModeMap;
2128 INT32 *OldTextOutModeMap;
2129 INT32 *SrcAddress;
2130 INT32 Index;
2131
2132 NewSize = Private->TextOutListCount * sizeof (INT32);
2133 OldTextOutModeMap = Private->TextOutModeMap;
2134 TotalSize = NewSize * (Private->TextOutQueryDataCount);
2135
2136 //
2137 // Allocate new buffer for Text Out List.
2138 //
2139 TextOutModeMap = AllocatePool (TotalSize);
2140 if (TextOutModeMap == NULL) {
2141 return EFI_OUT_OF_RESOURCES;
2142 }
2143
2144 SetMem (TextOutModeMap, TotalSize, 0xFF);
2145 Private->TextOutModeMap = TextOutModeMap;
2146
2147 //
2148 // If TextOutList has been enlarged, need to realloc the mode map table
2149 // The mode map table is regarded as a two dimension array.
2150 //
2151 // Old New
2152 // 0 ---------> TextOutListCount ----> TextOutListCount
2153 // | -------------------------------------------
2154 // | | | |
2155 // | | | |
2156 // | | | |
2157 // | | | |
2158 // | | | |
2159 // \/ | | |
2160 // -------------------------------------------
2161 // QueryDataCount
2162 //
2163 if (OldTextOutModeMap != NULL) {
2164
2165 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);
2166 Index = 0;
2167 SrcAddress = OldTextOutModeMap;
2168
2169 //
2170 // Copy the old data to the new one
2171 //
2172 while (Index < Private->TextOutMode.MaxMode) {
2173 CopyMem (TextOutModeMap, SrcAddress, Size);
2174 TextOutModeMap += NewSize;
2175 SrcAddress += Size;
2176 Index++;
2177 }
2178 //
2179 // Free the old buffer
2180 //
2181 FreePool (OldTextOutModeMap);
2182 }
2183
2184 return EFI_SUCCESS;
2185 }
2186
2187
2188 /**
2189 Add new device's output mode to console splitter's mode list.
2190
2191 @param Private Text Out Splitter pointer
2192 @param TextOut Simple Text Output protocol pointer.
2193
2194 @retval EFI_SUCCESS Device added successfully.
2195 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2196
2197 **/
2198 EFI_STATUS
2199 ConSplitterAddOutputMode (
2200 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2201 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
2202 )
2203 {
2204 EFI_STATUS Status;
2205 INT32 MaxMode;
2206 INT32 Mode;
2207 UINTN Index;
2208
2209 MaxMode = TextOut->Mode->MaxMode;
2210 Private->TextOutMode.MaxMode = MaxMode;
2211
2212 //
2213 // Grow the buffer if query data buffer is not large enough to
2214 // hold all the mode supported by the first console.
2215 //
2216 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {
2217 Status = ConSplitterGrowBuffer (
2218 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
2219 &Private->TextOutQueryDataCount,
2220 (VOID **) &Private->TextOutQueryData
2221 );
2222 if (EFI_ERROR (Status)) {
2223 return EFI_OUT_OF_RESOURCES;
2224 }
2225 }
2226 //
2227 // Allocate buffer for the output mode map
2228 //
2229 Status = ConSplitterGrowMapTable (Private);
2230 if (EFI_ERROR (Status)) {
2231 return EFI_OUT_OF_RESOURCES;
2232 }
2233 //
2234 // As the first textout device, directly add the mode in to QueryData
2235 // and at the same time record the mapping between QueryData and TextOut.
2236 //
2237 Mode = 0;
2238 Index = 0;
2239 while (Mode < MaxMode) {
2240 Status = TextOut->QueryMode (
2241 TextOut,
2242 Mode,
2243 &Private->TextOutQueryData[Mode].Columns,
2244 &Private->TextOutQueryData[Mode].Rows
2245 );
2246 //
2247 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2248 // is clear to 0x0.
2249 //
2250 if ((EFI_ERROR(Status)) && (Mode == 1)) {
2251 Private->TextOutQueryData[Mode].Columns = 0;
2252 Private->TextOutQueryData[Mode].Rows = 0;
2253 }
2254 Private->TextOutModeMap[Index] = Mode;
2255 Mode++;
2256 Index += Private->TextOutListCount;
2257 }
2258
2259 return EFI_SUCCESS;
2260 }
2261
2262 /**
2263 Reconstruct TextOutModeMap to get intersection of modes.
2264
2265 This routine reconstruct TextOutModeMap to get the intersection
2266 of modes for all console out devices. Because EFI/UEFI spec require
2267 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the
2268 intersection for mode 0 and mode 1.
2269
2270 @param TextOutModeMap Current text out mode map, begin with the mode 80x25
2271 @param NewlyAddedMap New text out mode map, begin with the mode 80x25
2272 @param MapStepSize Mode step size for one console device
2273 @param NewMapStepSize New Mode step size for one console device
2274 @param MaxMode IN: Current max text mode, OUT: Updated max text mode.
2275 @param CurrentMode IN: Current text mode, OUT: Updated current text mode.
2276
2277 **/
2278 VOID
2279 ConSplitterGetIntersection (
2280 IN INT32 *TextOutModeMap,
2281 IN INT32 *NewlyAddedMap,
2282 IN UINTN MapStepSize,
2283 IN UINTN NewMapStepSize,
2284 IN OUT INT32 *MaxMode,
2285 IN OUT INT32 *CurrentMode
2286 )
2287 {
2288 INT32 Index;
2289 INT32 *CurrentMapEntry;
2290 INT32 *NextMapEntry;
2291 INT32 *NewMapEntry;
2292 INT32 CurrentMaxMode;
2293 INT32 Mode;
2294
2295 //
2296 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved
2297 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection
2298 // for mode 0 and mode 1, mode number starts from 2.
2299 //
2300 Index = 2;
2301 CurrentMapEntry = &TextOutModeMap[MapStepSize * 2];
2302 NextMapEntry = CurrentMapEntry;
2303 NewMapEntry = &NewlyAddedMap[NewMapStepSize * 2];
2304
2305 CurrentMaxMode = *MaxMode;
2306 Mode = *CurrentMode;
2307
2308 while (Index < CurrentMaxMode) {
2309 if (*NewMapEntry == -1) {
2310 //
2311 // This mode is not supported any more. Remove it. Special care
2312 // must be taken as this remove will also affect current mode;
2313 //
2314 if (Index == *CurrentMode) {
2315 Mode = -1;
2316 } else if (Index < *CurrentMode) {
2317 Mode--;
2318 }
2319 (*MaxMode)--;
2320 } else {
2321 if (CurrentMapEntry != NextMapEntry) {
2322 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));
2323 }
2324
2325 NextMapEntry += MapStepSize;
2326 }
2327
2328 CurrentMapEntry += MapStepSize;
2329 NewMapEntry += NewMapStepSize;
2330 Index++;
2331 }
2332
2333 *CurrentMode = Mode;
2334
2335 return ;
2336 }
2337
2338 /**
2339 Sync the device's output mode to console splitter's mode list.
2340
2341 @param Private Text Out Splitter pointer.
2342 @param TextOut Simple Text Output protocol pointer.
2343
2344 **/
2345 VOID
2346 ConSplitterSyncOutputMode (
2347 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2348 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
2349 )
2350 {
2351 INT32 CurrentMaxMode;
2352 INT32 Mode;
2353 INT32 Index;
2354 INT32 *TextOutModeMap;
2355 INT32 *MapTable;
2356 INT32 QueryMode;
2357 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;
2358 UINTN Rows;
2359 UINTN Columns;
2360 UINTN StepSize;
2361 EFI_STATUS Status;
2362
2363 //
2364 // Must make sure that current mode won't change even if mode number changes
2365 //
2366 CurrentMaxMode = Private->TextOutMode.MaxMode;
2367 TextOutModeMap = Private->TextOutModeMap;
2368 StepSize = Private->TextOutListCount;
2369 TextOutQueryData = Private->TextOutQueryData;
2370
2371 //
2372 // Query all the mode that the newly added TextOut supports
2373 //
2374 Mode = 0;
2375 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;
2376 while (Mode < TextOut->Mode->MaxMode) {
2377 Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);
2378
2379 if (EFI_ERROR(Status)) {
2380 if (Mode == 1) {
2381 //
2382 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData
2383 // is clear to 0x0.
2384 //
2385 MapTable[StepSize] = Mode;
2386 TextOutQueryData[Mode].Columns = 0;
2387 TextOutQueryData[Mode].Rows = 0;
2388 }
2389 Mode++;
2390 continue;
2391 }
2392 //
2393 // Search the intersection map and QueryData database to see if they intersects
2394 //
2395 Index = 0;
2396 while (Index < CurrentMaxMode) {
2397 QueryMode = *(TextOutModeMap + Index * StepSize);
2398 if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) {
2399 MapTable[Index * StepSize] = Mode;
2400 break;
2401 }
2402 Index++;
2403 }
2404 Mode++;
2405 }
2406 //
2407 // Now search the TextOutModeMap table to find the intersection of supported
2408 // mode between ConSplitter and the newly added device.
2409 //
2410 ConSplitterGetIntersection (
2411 TextOutModeMap,
2412 MapTable,
2413 StepSize,
2414 StepSize,
2415 &Private->TextOutMode.MaxMode,
2416 &Private->TextOutMode.Mode
2417 );
2418
2419 return ;
2420 }
2421
2422
2423 /**
2424 Sync output device between ConOut and StdErr output.
2425
2426 @retval EFI_SUCCESS Sync implemented successfully.
2427 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2428
2429 **/
2430 EFI_STATUS
2431 ConSplitterGetIntersectionBetweenConOutAndStrErr (
2432 VOID
2433 )
2434 {
2435 UINTN ConOutNumOfConsoles;
2436 UINTN StdErrNumOfConsoles;
2437 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;
2438 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;
2439 UINTN Indexi;
2440 UINTN Indexj;
2441 UINTN ConOutRows;
2442 UINTN ConOutColumns;
2443 UINTN StdErrRows;
2444 UINTN StdErrColumns;
2445 INT32 ConOutMaxMode;
2446 INT32 StdErrMaxMode;
2447 INT32 ConOutMode;
2448 INT32 StdErrMode;
2449 INT32 Mode;
2450 INT32 Index;
2451 INT32 *ConOutModeMap;
2452 INT32 *StdErrModeMap;
2453 INT32 *ConOutMapTable;
2454 INT32 *StdErrMapTable;
2455 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;
2456 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;
2457 UINTN ConOutStepSize;
2458 UINTN StdErrStepSize;
2459 BOOLEAN FoundTheSameTextOut;
2460 UINTN ConOutMapTableSize;
2461 UINTN StdErrMapTableSize;
2462
2463 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;
2464 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;
2465 ConOutTextOutList = mConOut.TextOutList;
2466 StdErrTextOutList = mStdErr.TextOutList;
2467
2468 Indexi = 0;
2469 FoundTheSameTextOut = FALSE;
2470 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {
2471 Indexj = 0;
2472 while (Indexj < StdErrNumOfConsoles) {
2473 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {
2474 FoundTheSameTextOut = TRUE;
2475 break;
2476 }
2477
2478 Indexj++;
2479 StdErrTextOutList++;
2480 }
2481
2482 Indexi++;
2483 ConOutTextOutList++;
2484 }
2485
2486 if (!FoundTheSameTextOut) {
2487 return EFI_SUCCESS;
2488 }
2489 //
2490 // Must make sure that current mode won't change even if mode number changes
2491 //
2492 ConOutMaxMode = mConOut.TextOutMode.MaxMode;
2493 ConOutModeMap = mConOut.TextOutModeMap;
2494 ConOutStepSize = mConOut.TextOutListCount;
2495 ConOutQueryData = mConOut.TextOutQueryData;
2496
2497 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;
2498 StdErrModeMap = mStdErr.TextOutModeMap;
2499 StdErrStepSize = mStdErr.TextOutListCount;
2500 StdErrQueryData = mStdErr.TextOutQueryData;
2501
2502 //
2503 // Allocate the map table and set the map table's index to -1.
2504 //
2505 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);
2506 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);
2507 if (ConOutMapTable == NULL) {
2508 return EFI_OUT_OF_RESOURCES;
2509 }
2510
2511 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);
2512
2513 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);
2514 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);
2515 if (StdErrMapTable == NULL) {
2516 return EFI_OUT_OF_RESOURCES;
2517 }
2518
2519 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);
2520
2521 //
2522 // Find the intersection of the two set of modes. If they actually intersect, the
2523 // correponding entry in the map table is set to 1.
2524 //
2525 Mode = 0;
2526 while (Mode < ConOutMaxMode) {
2527 //
2528 // Search the intersection map and QueryData database to see if they intersect
2529 //
2530 Index = 0;
2531 ConOutMode = *(ConOutModeMap + Mode * ConOutStepSize);
2532 ConOutRows = ConOutQueryData[ConOutMode].Rows;
2533 ConOutColumns = ConOutQueryData[ConOutMode].Columns;
2534 while (Index < StdErrMaxMode) {
2535 StdErrMode = *(StdErrModeMap + Index * StdErrStepSize);
2536 StdErrRows = StdErrQueryData[StdErrMode].Rows;
2537 StdErrColumns = StdErrQueryData[StdErrMode].Columns;
2538 if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) {
2539 ConOutMapTable[Mode] = 1;
2540 StdErrMapTable[Index] = 1;
2541 break;
2542 }
2543
2544 Index++;
2545 }
2546
2547 Mode++;
2548 }
2549 //
2550 // Now search the TextOutModeMap table to find the intersection of supported
2551 // mode between ConSplitter and the newly added device.
2552 //
2553 ConSplitterGetIntersection (
2554 ConOutModeMap,
2555 ConOutMapTable,
2556 mConOut.TextOutListCount,
2557 1,
2558 &(mConOut.TextOutMode.MaxMode),
2559 &(mConOut.TextOutMode.Mode)
2560 );
2561
2562 if (mConOut.TextOutMode.Mode < 0) {
2563 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);
2564 }
2565
2566 ConSplitterGetIntersection (
2567 StdErrModeMap,
2568 StdErrMapTable,
2569 mStdErr.TextOutListCount,
2570 1,
2571 &(mStdErr.TextOutMode.MaxMode),
2572 &(mStdErr.TextOutMode.Mode)
2573 );
2574
2575 if (mStdErr.TextOutMode.Mode < 0) {
2576 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);
2577 }
2578
2579 FreePool (ConOutMapTable);
2580 FreePool (StdErrMapTable);
2581
2582 return EFI_SUCCESS;
2583 }
2584
2585
2586 /**
2587 Add Grahpics Output modes into Consplitter Text Out list.
2588
2589 @param Private Text Out Splitter pointer.
2590 @param GraphicsOutput Graphics Output protocol pointer.
2591 @param UgaDraw UGA Draw protocol pointer.
2592
2593 @retval EFI_SUCCESS Output mode added successfully.
2594 @retval other Failed to add output mode.
2595
2596 **/
2597 EFI_STATUS
2598 ConSplitterAddGraphicsOutputMode (
2599 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2600 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2601 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2602 )
2603 {
2604 EFI_STATUS Status;
2605 UINTN Index;
2606 UINTN CurrentIndex;
2607 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
2608 UINTN SizeOfInfo;
2609 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
2610 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;
2611 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;
2612 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;
2613 UINTN NumberIndex;
2614 BOOLEAN Match;
2615 BOOLEAN AlreadyExist;
2616 UINT32 UgaHorizontalResolution;
2617 UINT32 UgaVerticalResolution;
2618 UINT32 UgaColorDepth;
2619 UINT32 UgaRefreshRate;
2620
2621 ASSERT (GraphicsOutput != NULL || UgaDraw != NULL);
2622
2623 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;
2624
2625 Index = 0;
2626 CurrentIndex = 0;
2627 Status = EFI_SUCCESS;
2628
2629 if (Private->CurrentNumberOfUgaDraw != 0) {
2630 //
2631 // If any UGA device has already been added, then there is no need to
2632 // calculate intersection of display mode of different GOP/UGA device,
2633 // since only one display mode will be exported (i.e. user-defined mode)
2634 //
2635 goto Done;
2636 }
2637
2638 if (GraphicsOutput != NULL) {
2639 if (Private->CurrentNumberOfGraphicsOutput == 0) {
2640 //
2641 // This is the first Graphics Output device added
2642 //
2643 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;
2644 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;
2645 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);
2646 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;
2647 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;
2648 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;
2649
2650 //
2651 // Allocate resource for the private mode buffer
2652 //
2653 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * GraphicsOutput->Mode->MaxMode);
2654 if (ModeBuffer == NULL) {
2655 return EFI_OUT_OF_RESOURCES;
2656 }
2657 FreePool (Private->GraphicsOutputModeBuffer);
2658 Private->GraphicsOutputModeBuffer = ModeBuffer;
2659
2660 //
2661 // Store all supported display modes to the private mode buffer
2662 //
2663 Mode = ModeBuffer;
2664 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {
2665 //
2666 // The Info buffer would be allocated by callee
2667 //
2668 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);
2669 if (EFI_ERROR (Status)) {
2670 return Status;
2671 }
2672 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2673 CopyMem (Mode, Info, SizeOfInfo);
2674 Mode++;
2675 FreePool (Info);
2676 }
2677 } else {
2678 //
2679 // Check intersection of display mode
2680 //
2681 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);
2682 if (ModeBuffer == NULL) {
2683 return EFI_OUT_OF_RESOURCES;
2684 }
2685
2686 MatchedMode = ModeBuffer;
2687 Mode = &Private->GraphicsOutputModeBuffer[0];
2688 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2689 Match = FALSE;
2690
2691 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {
2692 //
2693 // The Info buffer would be allocated by callee
2694 //
2695 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
2696 if (EFI_ERROR (Status)) {
2697 return Status;
2698 }
2699 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
2700 (Info->VerticalResolution == Mode->VerticalResolution)) {
2701 //
2702 // If GOP device supports one mode in current mode buffer,
2703 // it will be added into matched mode buffer
2704 //
2705 Match = TRUE;
2706 FreePool (Info);
2707 break;
2708 }
2709 FreePool (Info);
2710 }
2711
2712 if (Match) {
2713 AlreadyExist = FALSE;
2714
2715 //
2716 // Check if GOP mode has been in the mode buffer, ModeBuffer = MatchedMode at begin.
2717 //
2718 for (Info = ModeBuffer; Info < MatchedMode; Info++) {
2719 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
2720 (Info->VerticalResolution == Mode->VerticalResolution)) {
2721 AlreadyExist = TRUE;
2722 break;
2723 }
2724 }
2725
2726 if (!AlreadyExist) {
2727 CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2728
2729 //
2730 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly
2731 //
2732 MatchedMode->Version = 0;
2733 MatchedMode->PixelFormat = PixelBltOnly;
2734 ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
2735
2736 MatchedMode++;
2737 }
2738 }
2739
2740 Mode++;
2741 }
2742
2743 //
2744 // Drop the old mode buffer, assign it to a new one
2745 //
2746 FreePool (Private->GraphicsOutputModeBuffer);
2747 Private->GraphicsOutputModeBuffer = ModeBuffer;
2748
2749 //
2750 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2751 //
2752 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2753 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
2754 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
2755 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2756 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
2757 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2758 }
2759
2760 //
2761 // Graphics console driver can ensure the same mode for all GOP devices
2762 //
2763 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2764 Mode = &Private->GraphicsOutputModeBuffer[Index];
2765 if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) &&
2766 (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) {
2767 CurrentIndex = Index;
2768 break;
2769 }
2770 }
2771 if (Index >= CurrentGraphicsOutputMode->MaxMode) {
2772 //
2773 // if user defined mode is not found, set to default mode 800x600
2774 //
2775 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2776 Mode = &Private->GraphicsOutputModeBuffer[Index];
2777 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {
2778 CurrentIndex = Index;
2779 break;
2780 }
2781 }
2782 }
2783 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
2784 //
2785 // Graphics console driver can ensure the same mode for all GOP devices
2786 // so we can get the current mode from this video device
2787 //
2788 UgaDraw->GetMode (
2789 UgaDraw,
2790 &UgaHorizontalResolution,
2791 &UgaVerticalResolution,
2792 &UgaColorDepth,
2793 &UgaRefreshRate
2794 );
2795
2796 CurrentGraphicsOutputMode->MaxMode = 1;
2797 Info = CurrentGraphicsOutputMode->Info;
2798 Info->Version = 0;
2799 Info->HorizontalResolution = UgaHorizontalResolution;
2800 Info->VerticalResolution = UgaVerticalResolution;
2801 Info->PixelFormat = PixelBltOnly;
2802 Info->PixelsPerScanLine = UgaHorizontalResolution;
2803 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2804 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
2805 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2806
2807 //
2808 // Update the private mode buffer
2809 //
2810 CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
2811
2812 //
2813 // Only mode 0 is available to be set
2814 //
2815 CurrentIndex = 0;
2816 }
2817
2818 Done:
2819
2820 if (GraphicsOutput != NULL) {
2821 Private->CurrentNumberOfGraphicsOutput++;
2822 }
2823 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
2824 Private->CurrentNumberOfUgaDraw++;
2825 }
2826
2827 //
2828 // Force GraphicsOutput mode to be set,
2829 //
2830
2831 Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];
2832 if ((GraphicsOutput != NULL) &&
2833 (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&
2834 (Mode->VerticalResolution == CurrentGraphicsOutputMode->Info->VerticalResolution)) {
2835 CurrentGraphicsOutputMode->Mode = (UINT32) CurrentIndex;
2836 if ((Mode->HorizontalResolution != GraphicsOutput->Mode->Info->HorizontalResolution) ||
2837 (Mode->VerticalResolution != GraphicsOutput->Mode->Info->VerticalResolution)) {
2838 //
2839 // If all existing video device has been set to common mode, only set new GOP device to
2840 // the common mode
2841 //
2842 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
2843 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
2844 if (EFI_ERROR (Status)) {
2845 return Status;
2846 }
2847 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
2848 FreePool (Info);
2849 break;
2850 }
2851 FreePool (Info);
2852 }
2853 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
2854 }
2855 } else {
2856 //
2857 // Current mode number may need update now, so set it to an invalid mode number
2858 //
2859 CurrentGraphicsOutputMode->Mode = 0xffff;
2860 //
2861 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.
2862 //
2863 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);
2864 if (EFI_ERROR(Status)) {
2865 //
2866 // If user defined mode is not valid for display device, set to the default mode 800x600.
2867 //
2868 (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;
2869 (Private->GraphicsOutputModeBuffer[0]).VerticalResolution = 600;
2870 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);
2871 }
2872 }
2873
2874 return Status;
2875 }
2876
2877 /**
2878 Set the current console out mode.
2879
2880 This routine will get the current console mode information (column, row)
2881 from ConsoleOutMode variable and set it; if the variable does not exist,
2882 set to user defined console mode.
2883
2884 @param Private Consplitter Text Out pointer.
2885
2886 **/
2887 VOID
2888 ConsplitterSetConsoleOutMode (
2889 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
2890 )
2891 {
2892 UINTN Col;
2893 UINTN Row;
2894 UINTN Mode;
2895 UINTN PreferMode;
2896 UINTN BaseMode;
2897 UINTN MaxMode;
2898 EFI_STATUS Status;
2899 CONSOLE_OUT_MODE ModeInfo;
2900 CONSOLE_OUT_MODE MaxModeInfo;
2901 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
2902
2903 PreferMode = 0xFF;
2904 BaseMode = 0xFF;
2905 TextOut = &Private->TextOut;
2906 MaxMode = (UINTN) (TextOut->Mode->MaxMode);
2907
2908 MaxModeInfo.Column = 0;
2909 MaxModeInfo.Row = 0;
2910 ModeInfo.Column = PcdGet32 (PcdConOutColumn);
2911 ModeInfo.Row = PcdGet32 (PcdConOutRow);
2912
2913 //
2914 // To find the prefer mode and basic mode from Text Out mode list
2915 //
2916 for (Mode = 0; Mode < MaxMode; Mode++) {
2917 Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);
2918 if (!EFI_ERROR(Status)) {
2919 if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {
2920 //
2921 // Use user defined column and row
2922 //
2923 if (Col == ModeInfo.Column && Row == ModeInfo.Row) {
2924 PreferMode = Mode;
2925 }
2926 } else {
2927 //
2928 // If user sets PcdConOutColumn or PcdConOutRow to 0,
2929 // find and set the highest text mode.
2930 //
2931 if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {
2932 MaxModeInfo.Column = Col;
2933 MaxModeInfo.Row = Row;
2934 PreferMode = Mode;
2935 }
2936 }
2937 if (Col == 80 && Row == 25) {
2938 BaseMode = Mode;
2939 }
2940 }
2941 }
2942
2943 //
2944 // Set prefer mode to Text Out devices.
2945 //
2946 Status = TextOut->SetMode (TextOut, PreferMode);
2947 if (EFI_ERROR(Status)) {
2948 //
2949 // if current mode setting is failed, default 80x25 mode will be set.
2950 //
2951 Status = TextOut->SetMode (TextOut, BaseMode);
2952 ASSERT(!EFI_ERROR(Status));
2953
2954 PcdSet32 (PcdConOutColumn, 80);
2955 PcdSet32 (PcdConOutRow, 25);
2956 }
2957
2958 return ;
2959 }
2960
2961
2962 /**
2963 Add Text Output Device in Consplitter Text Output list.
2964
2965 @param Private Text Out Splitter pointer.
2966 @param TextOut Simple Text Output protocol pointer.
2967 @param GraphicsOutput Graphics Output protocol pointer.
2968 @param UgaDraw UGA Draw protocol pointer.
2969
2970 @retval EFI_SUCCESS Text Output Device added successfully.
2971 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
2972
2973 **/
2974 EFI_STATUS
2975 ConSplitterTextOutAddDevice (
2976 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2977 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
2978 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2979 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2980 )
2981 {
2982 EFI_STATUS Status;
2983 UINTN CurrentNumOfConsoles;
2984 INT32 MaxMode;
2985 UINT32 UgaHorizontalResolution;
2986 UINT32 UgaVerticalResolution;
2987 UINT32 UgaColorDepth;
2988 UINT32 UgaRefreshRate;
2989 TEXT_OUT_AND_GOP_DATA *TextAndGop;
2990 UINTN SizeOfInfo;
2991 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
2992 EFI_STATUS DeviceStatus;
2993
2994 Status = EFI_SUCCESS;
2995 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
2996
2997 //
2998 // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().
2999 //
3000 while (CurrentNumOfConsoles >= Private->TextOutListCount) {
3001 Status = ConSplitterGrowBuffer (
3002 sizeof (TEXT_OUT_AND_GOP_DATA),
3003 &Private->TextOutListCount,
3004 (VOID **) &Private->TextOutList
3005 );
3006 if (EFI_ERROR (Status)) {
3007 return EFI_OUT_OF_RESOURCES;
3008 }
3009 //
3010 // Also need to reallocate the TextOutModeMap table
3011 //
3012 Status = ConSplitterGrowMapTable (Private);
3013 if (EFI_ERROR (Status)) {
3014 return EFI_OUT_OF_RESOURCES;
3015 }
3016 }
3017
3018 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];
3019
3020 TextAndGop->TextOut = TextOut;
3021 TextAndGop->GraphicsOutput = GraphicsOutput;
3022 TextAndGop->UgaDraw = UgaDraw;
3023
3024 if (CurrentNumOfConsoles == 0) {
3025 //
3026 // Add the first device's output mode to console splitter's mode list
3027 //
3028 Status = ConSplitterAddOutputMode (Private, TextOut);
3029 } else {
3030 ConSplitterSyncOutputMode (Private, TextOut);
3031 }
3032
3033 Private->CurrentNumberOfConsoles++;
3034
3035 //
3036 // Scan both TextOutList, for the intersection TextOut device
3037 // maybe both ConOut and StdErr incorporate the same Text Out
3038 // device in them, thus the output of both should be synced.
3039 //
3040 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3041
3042 MaxMode = Private->TextOutMode.MaxMode;
3043 ASSERT (MaxMode >= 1);
3044
3045 DeviceStatus = EFI_DEVICE_ERROR;
3046 if (FeaturePcdGet (PcdConOutGopSupport)) {
3047 //
3048 // If GOP is produced by Consplitter, this device display mode will be added into Graphics Ouput modes.
3049 //
3050 if ((GraphicsOutput != NULL) || (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport))) {
3051 DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
3052 }
3053 }
3054
3055 if (FeaturePcdGet (PcdConOutUgaSupport)) {
3056 //
3057 // If UGA is produced by Consplitter
3058 //
3059 if (GraphicsOutput != NULL) {
3060 Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
3061 if (EFI_ERROR (Status)) {
3062 return Status;
3063 }
3064 ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
3065
3066 UgaHorizontalResolution = Info->HorizontalResolution;
3067 UgaVerticalResolution = Info->VerticalResolution;
3068
3069 FreePool (Info);
3070
3071 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
3072 Status = UgaDraw->GetMode (
3073 UgaDraw,
3074 &UgaHorizontalResolution,
3075 &UgaVerticalResolution,
3076 &UgaColorDepth,
3077 &UgaRefreshRate
3078 );
3079 if (!EFI_ERROR (Status) && EFI_ERROR (DeviceStatus)) {
3080 //
3081 // if GetMode is successfully and UGA device hasn't been set, set it
3082 //
3083 Status = ConSplitterUgaDrawSetMode (
3084 &Private->UgaDraw,
3085 UgaHorizontalResolution,
3086 UgaVerticalResolution,
3087 UgaColorDepth,
3088 UgaRefreshRate
3089 );
3090 }
3091 //
3092 // If GetMode/SetMode is failed, set to 800x600 mode
3093 //
3094 if(EFI_ERROR (Status)) {
3095 Status = ConSplitterUgaDrawSetMode (
3096 &Private->UgaDraw,
3097 800,
3098 600,
3099 32,
3100 60
3101 );
3102 }
3103 }
3104 }
3105
3106 //
3107 // After adding new console device, all existing console devices should be
3108 // synced to the current shared mode.
3109 //
3110 ConsplitterSetConsoleOutMode (Private);
3111
3112 return Status;
3113 }
3114
3115
3116 /**
3117 Remove Text Out Device in Consplitter Text Out list.
3118
3119 @param Private Text Out Splitter pointer.
3120 @param TextOut Simple Text Output Pointer protocol pointer.
3121
3122 @retval EFI_SUCCESS Text Out Device removed successfully.
3123 @retval EFI_NOT_FOUND No Text Out Device found.
3124
3125 **/
3126 EFI_STATUS
3127 ConSplitterTextOutDeleteDevice (
3128 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
3129 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
3130 )
3131 {
3132 INT32 Index;
3133 UINTN CurrentNumOfConsoles;
3134 TEXT_OUT_AND_GOP_DATA *TextOutList;
3135 EFI_STATUS Status;
3136
3137 //
3138 // Remove the specified text-out device data structure from the Text out List,
3139 // and rearrange the remaining data structures in the Text out List.
3140 //
3141 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
3142 Index = (INT32) CurrentNumOfConsoles - 1;
3143 TextOutList = Private->TextOutList;
3144 while (Index >= 0) {
3145 if (TextOutList->TextOut == TextOut) {
3146 if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
3147 Private->CurrentNumberOfUgaDraw--;
3148 }
3149 if (TextOutList->GraphicsOutput != NULL) {
3150 Private->CurrentNumberOfGraphicsOutput--;
3151 }
3152 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
3153 CurrentNumOfConsoles--;
3154 break;
3155 }
3156
3157 Index--;
3158 TextOutList++;
3159 }
3160 //
3161 // The specified TextOut is not managed by the ConSplitter driver
3162 //
3163 if (Index < 0) {
3164 return EFI_NOT_FOUND;
3165 }
3166
3167 if (CurrentNumOfConsoles == 0) {
3168 //
3169 // If the number of consoles is zero, reset all parameters
3170 //
3171 Private->CurrentNumberOfConsoles = 0;
3172 Private->TextOutMode.MaxMode = 1;
3173 Private->TextOutQueryData[0].Columns = 80;
3174 Private->TextOutQueryData[0].Rows = 25;
3175 TextOutSetMode (Private, 0);
3176
3177 return EFI_SUCCESS;
3178 }
3179 //
3180 // Max Mode is realy an intersection of the QueryMode command to all
3181 // devices. So we must copy the QueryMode of the first device to
3182 // QueryData.
3183 //
3184 ZeroMem (
3185 Private->TextOutQueryData,
3186 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)
3187 );
3188
3189 FreePool (Private->TextOutModeMap);
3190 Private->TextOutModeMap = NULL;
3191 TextOutList = Private->TextOutList;
3192
3193 //
3194 // Add the first TextOut to the QueryData array and ModeMap table
3195 //
3196 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);
3197
3198 //
3199 // Now add one by one
3200 //
3201 Index = 1;
3202 Private->CurrentNumberOfConsoles = 1;
3203 TextOutList++;
3204 while ((UINTN) Index < CurrentNumOfConsoles) {
3205 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);
3206 Index++;
3207 Private->CurrentNumberOfConsoles++;
3208 TextOutList++;
3209 }
3210
3211 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
3212
3213 return Status;
3214 }
3215
3216
3217 /**
3218 Reset the input device and optionaly run diagnostics
3219
3220 @param This Protocol instance pointer.
3221 @param ExtendedVerification Driver may perform diagnostics on reset.
3222
3223 @retval EFI_SUCCESS The device was reset.
3224 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3225 not be reset.
3226
3227 **/
3228 EFI_STATUS
3229 EFIAPI
3230 ConSplitterTextInReset (
3231 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3232 IN BOOLEAN ExtendedVerification
3233 )
3234 {
3235 EFI_STATUS Status;
3236 EFI_STATUS ReturnStatus;
3237 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3238 UINTN Index;
3239
3240 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3241
3242 Private->KeyEventSignalState = FALSE;
3243
3244 //
3245 // return the worst status met
3246 //
3247 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3248 Status = Private->TextInList[Index]->Reset (
3249 Private->TextInList[Index],
3250 ExtendedVerification
3251 );
3252 if (EFI_ERROR (Status)) {
3253 ReturnStatus = Status;
3254 }
3255 }
3256
3257 return ReturnStatus;
3258 }
3259
3260
3261 /**
3262 Reads the next keystroke from the input device. The WaitForKey Event can
3263 be used to test for existance of a keystroke via WaitForEvent () call.
3264
3265 @param Private Protocol instance pointer.
3266 @param Key Driver may perform diagnostics on reset.
3267
3268 @retval EFI_SUCCESS The keystroke information was returned.
3269 @retval EFI_NOT_READY There was no keystroke data availiable.
3270 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3271 to hardware errors.
3272
3273 **/
3274 EFI_STATUS
3275 EFIAPI
3276 ConSplitterTextInPrivateReadKeyStroke (
3277 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
3278 OUT EFI_INPUT_KEY *Key
3279 )
3280 {
3281 EFI_STATUS Status;
3282 UINTN Index;
3283 EFI_INPUT_KEY CurrentKey;
3284
3285 Key->UnicodeChar = 0;
3286 Key->ScanCode = SCAN_NULL;
3287
3288 //
3289 // if no physical console input device exists, return EFI_NOT_READY;
3290 // if any physical console input device has key input,
3291 // return the key and EFI_SUCCESS.
3292 //
3293 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
3294 Status = Private->TextInList[Index]->ReadKeyStroke (
3295 Private->TextInList[Index],
3296 &CurrentKey
3297 );
3298 if (!EFI_ERROR (Status)) {
3299 *Key = CurrentKey;
3300 return Status;
3301 }
3302 }
3303
3304 return EFI_NOT_READY;
3305 }
3306
3307
3308 /**
3309 Reads the next keystroke from the input device. The WaitForKey Event can
3310 be used to test for existance of a keystroke via WaitForEvent () call.
3311
3312 @param This Protocol instance pointer.
3313 @param Key Driver may perform diagnostics on reset.
3314
3315 @retval EFI_SUCCESS The keystroke information was returned.
3316 @retval EFI_NOT_READY There was no keystroke data availiable.
3317 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3318 to hardware errors.
3319
3320 **/
3321 EFI_STATUS
3322 EFIAPI
3323 ConSplitterTextInReadKeyStroke (
3324 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
3325 OUT EFI_INPUT_KEY *Key
3326 )
3327 {
3328 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3329
3330 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3331
3332 Private->KeyEventSignalState = FALSE;
3333
3334 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
3335 }
3336
3337
3338 /**
3339 This event aggregates all the events of the ConIn devices in the spliter.
3340
3341 If any events of physical ConIn devices are signaled, signal the ConIn
3342 spliter event. This will cause the calling code to call
3343 ConSplitterTextInReadKeyStroke ().
3344
3345 @param Event The Event assoicated with callback.
3346 @param Context Context registered when Event was created.
3347
3348 **/
3349 VOID
3350 EFIAPI
3351 ConSplitterTextInWaitForKey (
3352 IN EFI_EVENT Event,
3353 IN VOID *Context
3354 )
3355 {
3356 EFI_STATUS Status;
3357 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3358 UINTN Index;
3359
3360 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
3361
3362 if (Private->KeyEventSignalState) {
3363 //
3364 // If KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3365 //
3366 gBS->SignalEvent (Event);
3367 return ;
3368 }
3369
3370 //
3371 // If any physical console input device has key input, signal the event.
3372 //
3373 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
3374 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);
3375 if (!EFI_ERROR (Status)) {
3376 gBS->SignalEvent (Event);
3377 Private->KeyEventSignalState = TRUE;
3378 }
3379 }
3380 }
3381
3382
3383
3384 /**
3385 Test if the key has been registered on input device.
3386
3387 @param RegsiteredData A pointer to a buffer that is filled in with the
3388 keystroke state data for the key that was
3389 registered.
3390 @param InputData A pointer to a buffer that is filled in with the
3391 keystroke state data for the key that was
3392 pressed.
3393
3394 @retval TRUE Key be pressed matches a registered key.
3395 @retval FLASE Match failed.
3396
3397 **/
3398 BOOLEAN
3399 IsKeyRegistered (
3400 IN EFI_KEY_DATA *RegsiteredData,
3401 IN EFI_KEY_DATA *InputData
3402 )
3403 {
3404 ASSERT (RegsiteredData != NULL && InputData != NULL);
3405
3406 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
3407 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
3408 return FALSE;
3409 }
3410
3411 //
3412 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
3413 //
3414 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
3415 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
3416 return FALSE;
3417 }
3418 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
3419 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
3420 return FALSE;
3421 }
3422
3423 return TRUE;
3424
3425 }
3426
3427
3428 /**
3429 Reset the input device and optionaly run diagnostics
3430
3431 @param This Protocol instance pointer.
3432 @param ExtendedVerification Driver may perform diagnostics on reset.
3433
3434 @retval EFI_SUCCESS The device was reset.
3435 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3436 not be reset.
3437
3438 **/
3439 EFI_STATUS
3440 EFIAPI
3441 ConSplitterTextInResetEx (
3442 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3443 IN BOOLEAN ExtendedVerification
3444 )
3445 {
3446 EFI_STATUS Status;
3447 EFI_STATUS ReturnStatus;
3448 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3449 UINTN Index;
3450
3451 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3452
3453 Private->KeyEventSignalState = FALSE;
3454
3455 //
3456 // return the worst status met
3457 //
3458 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {
3459 Status = Private->TextInExList[Index]->Reset (
3460 Private->TextInExList[Index],
3461 ExtendedVerification
3462 );
3463 if (EFI_ERROR (Status)) {
3464 ReturnStatus = Status;
3465 }
3466 }
3467
3468 return ReturnStatus;
3469
3470 }
3471
3472
3473 /**
3474 Reads the next keystroke from the input device. The WaitForKey Event can
3475 be used to test for existance of a keystroke via WaitForEvent () call.
3476
3477 @param This Protocol instance pointer.
3478 @param KeyData A pointer to a buffer that is filled in with the
3479 keystroke state data for the key that was
3480 pressed.
3481
3482 @retval EFI_SUCCESS The keystroke information was returned.
3483 @retval EFI_NOT_READY There was no keystroke data availiable.
3484 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
3485 to hardware errors.
3486 @retval EFI_INVALID_PARAMETER KeyData is NULL.
3487
3488 **/
3489 EFI_STATUS
3490 EFIAPI
3491 ConSplitterTextInReadKeyStrokeEx (
3492 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3493 OUT EFI_KEY_DATA *KeyData
3494 )
3495 {
3496 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3497 EFI_STATUS Status;
3498 UINTN Index;
3499 EFI_KEY_DATA CurrentKeyData;
3500
3501
3502 if (KeyData == NULL) {
3503 return EFI_INVALID_PARAMETER;
3504 }
3505
3506 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3507
3508 Private->KeyEventSignalState = FALSE;
3509
3510 KeyData->Key.UnicodeChar = 0;
3511 KeyData->Key.ScanCode = SCAN_NULL;
3512
3513 //
3514 // if no physical console input device exists, return EFI_NOT_READY;
3515 // if any physical console input device has key input,
3516 // return the key and EFI_SUCCESS.
3517 //
3518 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3519 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (
3520 Private->TextInExList[Index],
3521 &CurrentKeyData
3522 );
3523 if (!EFI_ERROR (Status)) {
3524 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));
3525 return Status;
3526 }
3527 }
3528
3529 return EFI_NOT_READY;
3530 }
3531
3532
3533 /**
3534 Set certain state for the input device.
3535
3536 @param This Protocol instance pointer.
3537 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
3538 state for the input device.
3539
3540 @retval EFI_SUCCESS The device state was set successfully.
3541 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3542 could not have the setting adjusted.
3543 @retval EFI_UNSUPPORTED The device does not have the ability to set its
3544 state.
3545 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
3546
3547 **/
3548 EFI_STATUS
3549 EFIAPI
3550 ConSplitterTextInSetState (
3551 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3552 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
3553 )
3554 {
3555 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3556 EFI_STATUS Status;
3557 UINTN Index;
3558
3559 if (KeyToggleState == NULL) {
3560 return EFI_INVALID_PARAMETER;
3561 }
3562
3563 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3564
3565 //
3566 // if no physical console input device exists, return EFI_SUCCESS;
3567 // otherwise return the status of setting state of physical console input device
3568 //
3569 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3570 Status = Private->TextInExList[Index]->SetState (
3571 Private->TextInExList[Index],
3572 KeyToggleState
3573 );
3574 if (EFI_ERROR (Status)) {
3575 return Status;
3576 }
3577 }
3578
3579 return EFI_SUCCESS;
3580
3581 }
3582
3583
3584 /**
3585 Register a notification function for a particular keystroke for the input device.
3586
3587 @param This Protocol instance pointer.
3588 @param KeyData A pointer to a buffer that is filled in with the
3589 keystroke information data for the key that was
3590 pressed.
3591 @param KeyNotificationFunction Points to the function to be called when the key
3592 sequence is typed specified by KeyData.
3593 @param NotifyHandle Points to the unique handle assigned to the
3594 registered notification.
3595
3596 @retval EFI_SUCCESS The notification function was registered
3597 successfully.
3598 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
3599 structures.
3600 @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.
3601
3602 **/
3603 EFI_STATUS
3604 EFIAPI
3605 ConSplitterTextInRegisterKeyNotify (
3606 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3607 IN EFI_KEY_DATA *KeyData,
3608 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
3609 OUT VOID **NotifyHandle
3610 )
3611 {
3612 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3613 EFI_STATUS Status;
3614 UINTN Index;
3615 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;
3616 LIST_ENTRY *Link;
3617 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3618
3619
3620 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
3621 return EFI_INVALID_PARAMETER;
3622 }
3623
3624 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3625
3626 //
3627 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
3628 //
3629 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3630 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3631 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
3632 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
3633 *NotifyHandle = CurrentNotify;
3634 return EFI_SUCCESS;
3635 }
3636 }
3637 }
3638
3639 //
3640 // Allocate resource to save the notification function
3641 //
3642 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));
3643 if (NewNotify == NULL) {
3644 return EFI_OUT_OF_RESOURCES;
3645 }
3646 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount);
3647 if (NewNotify->NotifyHandleList == NULL) {
3648 gBS->FreePool (NewNotify);
3649 return EFI_OUT_OF_RESOURCES;
3650 }
3651 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;
3652 NewNotify->KeyNotificationFn = KeyNotificationFunction;
3653 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
3654
3655 //
3656 // Return the wrong status of registering key notify of
3657 // physical console input device if meet problems
3658 //
3659 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3660 Status = Private->TextInExList[Index]->RegisterKeyNotify (
3661 Private->TextInExList[Index],
3662 KeyData,
3663 KeyNotificationFunction,
3664 &NewNotify->NotifyHandleList[Index]
3665 );
3666 if (EFI_ERROR (Status)) {
3667 //
3668 // Un-register the key notify on all physical console input devices
3669 //
3670 while (Index-- != 0) {
3671 Private->TextInExList[Index]->UnregisterKeyNotify (
3672 Private->TextInExList[Index],
3673 NewNotify->NotifyHandleList[Index]
3674 );
3675 }
3676 gBS->FreePool (NewNotify->NotifyHandleList);
3677 gBS->FreePool (NewNotify);
3678 return Status;
3679 }
3680 }
3681
3682 InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);
3683
3684 *NotifyHandle = NewNotify;
3685
3686 return EFI_SUCCESS;
3687
3688 }
3689
3690
3691 /**
3692 Remove a registered notification function from a particular keystroke.
3693
3694 @param This Protocol instance pointer.
3695 @param NotificationHandle The handle of the notification function being
3696 unregistered.
3697
3698 @retval EFI_SUCCESS The notification function was unregistered
3699 successfully.
3700 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
3701
3702 **/
3703 EFI_STATUS
3704 EFIAPI
3705 ConSplitterTextInUnregisterKeyNotify (
3706 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
3707 IN VOID *NotificationHandle
3708 )
3709 {
3710 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3711 UINTN Index;
3712 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;
3713 LIST_ENTRY *Link;
3714
3715 if (NotificationHandle == NULL) {
3716 return EFI_INVALID_PARAMETER;
3717 }
3718
3719 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3720
3721 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
3722 CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);
3723 if (CurrentNotify == NotificationHandle) {
3724 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {
3725 Private->TextInExList[Index]->UnregisterKeyNotify (
3726 Private->TextInExList[Index],
3727 CurrentNotify->NotifyHandleList[Index]
3728 );
3729 }
3730 RemoveEntryList (&CurrentNotify->NotifyEntry);
3731
3732 gBS->FreePool (CurrentNotify->NotifyHandleList);
3733 gBS->FreePool (CurrentNotify);
3734 return EFI_SUCCESS;
3735 }
3736 }
3737
3738 //
3739 // NotificationHandle is not found in database
3740 //
3741 return EFI_INVALID_PARAMETER;
3742 }
3743
3744
3745 /**
3746 Reset the input device and optionaly run diagnostics
3747
3748 @param This Protocol instance pointer.
3749 @param ExtendedVerification Driver may perform diagnostics on reset.
3750
3751 @retval EFI_SUCCESS The device was reset.
3752 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
3753 not be reset.
3754
3755 **/
3756 EFI_STATUS
3757 EFIAPI
3758 ConSplitterSimplePointerReset (
3759 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
3760 IN BOOLEAN ExtendedVerification
3761 )
3762 {
3763 EFI_STATUS Status;
3764 EFI_STATUS ReturnStatus;
3765 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3766 UINTN Index;
3767
3768 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
3769
3770 Private->InputEventSignalState = FALSE;
3771
3772 if (Private->CurrentNumberOfPointers == 0) {
3773 return EFI_SUCCESS;
3774 }
3775 //
3776 // return the worst status met
3777 //
3778 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {
3779 Status = Private->PointerList[Index]->Reset (
3780 Private->PointerList[Index],
3781 ExtendedVerification
3782 );
3783 if (EFI_ERROR (Status)) {
3784 ReturnStatus = Status;
3785 }
3786 }
3787
3788 return ReturnStatus;
3789 }
3790
3791
3792 /**
3793 Reads the next keystroke from the input device. The WaitForKey Event can
3794 be used to test for existance of a keystroke via WaitForEvent () call.
3795
3796 @param Private Protocol instance pointer.
3797 @param State The state information of simple pointer device.
3798
3799 @retval EFI_SUCCESS The keystroke information was returned.
3800 @retval EFI_NOT_READY There was no keystroke data availiable.
3801 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3802 to hardware errors.
3803
3804 **/
3805 EFI_STATUS
3806 EFIAPI
3807 ConSplitterSimplePointerPrivateGetState (
3808 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
3809 IN OUT EFI_SIMPLE_POINTER_STATE *State
3810 )
3811 {
3812 EFI_STATUS Status;
3813 EFI_STATUS ReturnStatus;
3814 UINTN Index;
3815 EFI_SIMPLE_POINTER_STATE CurrentState;
3816
3817 State->RelativeMovementX = 0;
3818 State->RelativeMovementY = 0;
3819 State->RelativeMovementZ = 0;
3820 State->LeftButton = FALSE;
3821 State->RightButton = FALSE;
3822
3823 //
3824 // if no physical console input device exists, return EFI_NOT_READY;
3825 // if any physical console input device has key input,
3826 // return the key and EFI_SUCCESS.
3827 //
3828 ReturnStatus = EFI_NOT_READY;
3829 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
3830
3831 Status = Private->PointerList[Index]->GetState (
3832 Private->PointerList[Index],
3833 &CurrentState
3834 );
3835 if (!EFI_ERROR (Status)) {
3836 if (ReturnStatus == EFI_NOT_READY) {
3837 ReturnStatus = EFI_SUCCESS;
3838 }
3839
3840 if (CurrentState.LeftButton) {
3841 State->LeftButton = TRUE;
3842 }
3843
3844 if (CurrentState.RightButton) {
3845 State->RightButton = TRUE;
3846 }
3847
3848 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {
3849 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;
3850 }
3851
3852 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {
3853 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;
3854 }
3855
3856 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {
3857 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;
3858 }
3859 } else if (Status == EFI_DEVICE_ERROR) {
3860 ReturnStatus = EFI_DEVICE_ERROR;
3861 }
3862 }
3863
3864 return ReturnStatus;
3865 }
3866
3867
3868 /**
3869 Reads the next keystroke from the input device. The WaitForKey Event can
3870 be used to test for existance of a keystroke via WaitForEvent () call.
3871
3872 @param This A pointer to protocol instance.
3873 @param State A pointer to state information on the pointer device
3874
3875 @retval EFI_SUCCESS The keystroke information was returned in State.
3876 @retval EFI_NOT_READY There was no keystroke data availiable.
3877 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due
3878 to hardware errors.
3879
3880 **/
3881 EFI_STATUS
3882 EFIAPI
3883 ConSplitterSimplePointerGetState (
3884 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
3885 IN OUT EFI_SIMPLE_POINTER_STATE *State
3886 )
3887 {
3888 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3889
3890 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
3891
3892 Private->InputEventSignalState = FALSE;
3893
3894 return ConSplitterSimplePointerPrivateGetState (Private, State);
3895 }
3896
3897
3898 /**
3899 This event agregates all the events of the ConIn devices in the spliter.
3900 If any events of physical ConIn devices are signaled, signal the ConIn
3901 spliter event. This will cause the calling code to call
3902 ConSplitterTextInReadKeyStroke ().
3903
3904 @param Event The Event assoicated with callback.
3905 @param Context Context registered when Event was created.
3906
3907 **/
3908 VOID
3909 EFIAPI
3910 ConSplitterSimplePointerWaitForInput (
3911 IN EFI_EVENT Event,
3912 IN VOID *Context
3913 )
3914 {
3915 EFI_STATUS Status;
3916 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3917 UINTN Index;
3918
3919 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
3920
3921 //
3922 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
3923 //
3924 if (Private->InputEventSignalState) {
3925 gBS->SignalEvent (Event);
3926 return ;
3927 }
3928 //
3929 // if any physical console input device has key input, signal the event.
3930 //
3931 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
3932 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);
3933 if (!EFI_ERROR (Status)) {
3934 gBS->SignalEvent (Event);
3935 Private->InputEventSignalState = TRUE;
3936 }
3937 }
3938 }
3939
3940 /**
3941 Resets the pointer device hardware.
3942
3943 @param This Protocol instance pointer.
3944 @param ExtendedVerification Driver may perform diagnostics on reset.
3945
3946 @retval EFI_SUCCESS The device was reset.
3947 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
3948 could not be reset.
3949
3950 **/
3951 EFI_STATUS
3952 EFIAPI
3953 ConSplitterAbsolutePointerReset (
3954 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
3955 IN BOOLEAN ExtendedVerification
3956 )
3957 {
3958 EFI_STATUS Status;
3959 EFI_STATUS ReturnStatus;
3960 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
3961 UINTN Index;
3962
3963 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
3964
3965 Private->AbsoluteInputEventSignalState = FALSE;
3966
3967 if (Private->CurrentNumberOfAbsolutePointers == 0) {
3968 return EFI_SUCCESS;
3969 }
3970 //
3971 // return the worst status met
3972 //
3973 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
3974 Status = Private->AbsolutePointerList[Index]->Reset (
3975 Private->AbsolutePointerList[Index],
3976 ExtendedVerification
3977 );
3978 if (EFI_ERROR (Status)) {
3979 ReturnStatus = Status;
3980 }
3981 }
3982
3983 return ReturnStatus;
3984 }
3985
3986
3987 /**
3988 Retrieves the current state of a pointer device.
3989
3990 @param This Protocol instance pointer.
3991 @param State A pointer to the state information on the
3992 pointer device.
3993
3994 @retval EFI_SUCCESS The state of the pointer device was returned in
3995 State..
3996 @retval EFI_NOT_READY The state of the pointer device has not changed
3997 since the last call to GetState().
3998 @retval EFI_DEVICE_ERROR A device error occurred while attempting to
3999 retrieve the pointer device's current state.
4000
4001 **/
4002 EFI_STATUS
4003 EFIAPI
4004 ConSplitterAbsolutePointerGetState (
4005 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
4006 IN OUT EFI_ABSOLUTE_POINTER_STATE *State
4007 )
4008 {
4009 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4010 EFI_STATUS Status;
4011 EFI_STATUS ReturnStatus;
4012 UINTN Index;
4013 EFI_ABSOLUTE_POINTER_STATE CurrentState;
4014
4015
4016 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);
4017
4018 Private->AbsoluteInputEventSignalState = FALSE;
4019
4020 State->CurrentX = 0;
4021 State->CurrentY = 0;
4022 State->CurrentZ = 0;
4023 State->ActiveButtons = 0;
4024
4025 //
4026 // if no physical pointer device exists, return EFI_NOT_READY;
4027 // if any physical pointer device has changed state,
4028 // return the state and EFI_SUCCESS.
4029 //
4030 ReturnStatus = EFI_NOT_READY;
4031 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4032
4033 Status = Private->AbsolutePointerList[Index]->GetState (
4034 Private->AbsolutePointerList[Index],
4035 &CurrentState
4036 );
4037 if (!EFI_ERROR (Status)) {
4038 if (ReturnStatus == EFI_NOT_READY) {
4039 ReturnStatus = EFI_SUCCESS;
4040 }
4041
4042 State->ActiveButtons = CurrentState.ActiveButtons;
4043
4044 if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {
4045 State->CurrentX = CurrentState.CurrentX;
4046 }
4047 if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {
4048 State->CurrentY = CurrentState.CurrentY;
4049 }
4050 if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {
4051 State->CurrentZ = CurrentState.CurrentZ;
4052 }
4053
4054 } else if (Status == EFI_DEVICE_ERROR) {
4055 ReturnStatus = EFI_DEVICE_ERROR;
4056 }
4057 }
4058
4059 return ReturnStatus;
4060 }
4061
4062
4063 /**
4064 This event agregates all the events of the pointer devices in the splitter.
4065 If any events of physical pointer devices are signaled, signal the pointer
4066 splitter event. This will cause the calling code to call
4067 ConSplitterAbsolutePointerGetState ().
4068
4069 @param Event The Event assoicated with callback.
4070 @param Context Context registered when Event was created.
4071
4072 **/
4073 VOID
4074 EFIAPI
4075 ConSplitterAbsolutePointerWaitForInput (
4076 IN EFI_EVENT Event,
4077 IN VOID *Context
4078 )
4079 {
4080 EFI_STATUS Status;
4081 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
4082 UINTN Index;
4083
4084 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
4085
4086 //
4087 // if AbsoluteInputEventSignalState is flagged before,
4088 // and not cleared by Reset() or GetState(), signal it
4089 //
4090 if (Private->AbsoluteInputEventSignalState) {
4091 gBS->SignalEvent (Event);
4092 return ;
4093 }
4094 //
4095 // if any physical console input device has key input, signal the event.
4096 //
4097 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {
4098 Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);
4099 if (!EFI_ERROR (Status)) {
4100 gBS->SignalEvent (Event);
4101 Private->AbsoluteInputEventSignalState = TRUE;
4102 }
4103 }
4104 }
4105
4106
4107 /**
4108 Reset the text output device hardware and optionaly run diagnostics
4109
4110 @param This Protocol instance pointer.
4111 @param ExtendedVerification Driver may perform more exhaustive verfication
4112 operation of the device during reset.
4113
4114 @retval EFI_SUCCESS The text output device was reset.
4115 @retval EFI_DEVICE_ERROR The text output device is not functioning
4116 correctly and could not be reset.
4117
4118 **/
4119 EFI_STATUS
4120 EFIAPI
4121 ConSplitterTextOutReset (
4122 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4123 IN BOOLEAN ExtendedVerification
4124 )
4125 {
4126 EFI_STATUS Status;
4127 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4128 UINTN Index;
4129 EFI_STATUS ReturnStatus;
4130
4131 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4132
4133 //
4134 // return the worst status met
4135 //
4136 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4137 Status = Private->TextOutList[Index].TextOut->Reset (
4138 Private->TextOutList[Index].TextOut,
4139 ExtendedVerification
4140 );
4141 if (EFI_ERROR (Status)) {
4142 ReturnStatus = Status;
4143 }
4144 }
4145
4146 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));
4147
4148 //
4149 // reset all mode parameters
4150 //
4151 TextOutSetMode (Private, 0);
4152
4153 return ReturnStatus;
4154 }
4155
4156
4157 /**
4158 Write a Unicode string to the output device.
4159
4160 @param This Protocol instance pointer.
4161 @param WString The NULL-terminated Unicode string to be
4162 displayed on the output device(s). All output
4163 devices must also support the Unicode drawing
4164 defined in this file.
4165
4166 @retval EFI_SUCCESS The string was output to the device.
4167 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
4168 output the text.
4169 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
4170 defined text mode.
4171 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
4172 characters in the Unicode string could not be
4173 rendered and were skipped.
4174
4175 **/
4176 EFI_STATUS
4177 EFIAPI
4178 ConSplitterTextOutOutputString (
4179 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4180 IN CHAR16 *WString
4181 )
4182 {
4183 EFI_STATUS Status;
4184 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4185 UINTN Index;
4186 EFI_STATUS ReturnStatus;
4187 UINTN MaxColumn;
4188 UINTN MaxRow;
4189
4190 This->SetAttribute (This, This->Mode->Attribute);
4191
4192 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4193
4194 //
4195 // return the worst status met
4196 //
4197 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4198 Status = Private->TextOutList[Index].TextOut->OutputString (
4199 Private->TextOutList[Index].TextOut,
4200 WString
4201 );
4202 if (EFI_ERROR (Status)) {
4203 ReturnStatus = Status;
4204 }
4205 }
4206
4207 if (Private->CurrentNumberOfConsoles > 0) {
4208 Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;
4209 Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;
4210 } else {
4211 //
4212 // When there is no real console devices in system,
4213 // update cursor position for the virtual device in consplitter.
4214 //
4215 Private->TextOut.QueryMode (
4216 &Private->TextOut,
4217 Private->TextOutMode.Mode,
4218 &MaxColumn,
4219 &MaxRow
4220 );
4221 for (; *WString != CHAR_NULL; WString++) {
4222 switch (*WString) {
4223 case CHAR_BACKSPACE:
4224 if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {
4225 Private->TextOutMode.CursorRow--;
4226 Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);
4227 } else if (Private->TextOutMode.CursorColumn > 0) {
4228 Private->TextOutMode.CursorColumn--;
4229 }
4230 break;
4231
4232 case CHAR_LINEFEED:
4233 if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
4234 Private->TextOutMode.CursorRow++;
4235 }
4236 break;
4237
4238 case CHAR_CARRIAGE_RETURN:
4239 Private->TextOutMode.CursorColumn = 0;
4240 break;
4241
4242 default:
4243 if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {
4244 Private->TextOutMode.CursorColumn++;
4245 } else {
4246 Private->TextOutMode.CursorColumn = 0;
4247 if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {
4248 Private->TextOutMode.CursorRow++;
4249 }
4250 }
4251 break;
4252 }
4253 }
4254 }
4255
4256 return ReturnStatus;
4257 }
4258
4259
4260 /**
4261 Verifies that all characters in a Unicode string can be output to the
4262 target device.
4263
4264 @param This Protocol instance pointer.
4265 @param WString The NULL-terminated Unicode string to be
4266 examined for the output device(s).
4267
4268 @retval EFI_SUCCESS The device(s) are capable of rendering the
4269 output string.
4270 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string
4271 cannot be rendered by one or more of the output
4272 devices mapped by the EFI handle.
4273
4274 **/
4275 EFI_STATUS
4276 EFIAPI
4277 ConSplitterTextOutTestString (
4278 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4279 IN CHAR16 *WString
4280 )
4281 {
4282 EFI_STATUS Status;
4283 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4284 UINTN Index;
4285 EFI_STATUS ReturnStatus;
4286
4287 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4288
4289 //
4290 // return the worst status met
4291 //
4292 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4293 Status = Private->TextOutList[Index].TextOut->TestString (
4294 Private->TextOutList[Index].TextOut,
4295 WString
4296 );
4297 if (EFI_ERROR (Status)) {
4298 ReturnStatus = Status;
4299 }
4300 }
4301 //
4302 // There is no DevNullTextOutTestString () since a Unicode buffer would
4303 // always return EFI_SUCCESS.
4304 // ReturnStatus will be EFI_SUCCESS if no consoles are present
4305 //
4306 return ReturnStatus;
4307 }
4308
4309
4310 /**
4311 Returns information for an available text mode that the output device(s)
4312 supports.
4313
4314 @param This Protocol instance pointer.
4315 @param ModeNumber The mode number to return information on.
4316 @param Columns Returns the columns of the text output device
4317 for the requested ModeNumber.
4318 @param Rows Returns the rows of the text output device
4319 for the requested ModeNumber.
4320
4321 @retval EFI_SUCCESS The requested mode information was returned.
4322 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4323 the request.
4324 @retval EFI_UNSUPPORTED The mode number was not valid.
4325
4326 **/
4327 EFI_STATUS
4328 EFIAPI
4329 ConSplitterTextOutQueryMode (
4330 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4331 IN UINTN ModeNumber,
4332 OUT UINTN *Columns,
4333 OUT UINTN *Rows
4334 )
4335 {
4336 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4337 UINTN CurrentMode;
4338 INT32 *TextOutModeMap;
4339
4340 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4341
4342 //
4343 // Check whether param ModeNumber is valid.
4344 // ModeNumber should be within range 0 ~ MaxMode - 1.
4345 //
4346 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4347 return EFI_UNSUPPORTED;
4348 }
4349
4350 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4351 return EFI_UNSUPPORTED;
4352 }
4353
4354 //
4355 // We get the available mode from mode intersection map if it's available
4356 //
4357 if (Private->TextOutModeMap != NULL) {
4358 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4359 CurrentMode = (UINTN)(*TextOutModeMap);
4360 *Columns = Private->TextOutQueryData[CurrentMode].Columns;
4361 *Rows = Private->TextOutQueryData[CurrentMode].Rows;
4362 } else {
4363 *Columns = Private->TextOutQueryData[ModeNumber].Columns;
4364 *Rows = Private->TextOutQueryData[ModeNumber].Rows;
4365 }
4366
4367 if (*Columns <= 0 && *Rows <= 0) {
4368 return EFI_UNSUPPORTED;
4369
4370 }
4371
4372 return EFI_SUCCESS;
4373 }
4374
4375
4376 /**
4377 Sets the output device(s) to a specified mode.
4378
4379 @param This Protocol instance pointer.
4380 @param ModeNumber The mode number to set.
4381
4382 @retval EFI_SUCCESS The requested text mode was set.
4383 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4384 the request.
4385 @retval EFI_UNSUPPORTED The mode number was not valid.
4386
4387 **/
4388 EFI_STATUS
4389 EFIAPI
4390 ConSplitterTextOutSetMode (
4391 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4392 IN UINTN ModeNumber
4393 )
4394 {
4395 EFI_STATUS Status;
4396 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4397 UINTN Index;
4398 INT32 *TextOutModeMap;
4399 EFI_STATUS ReturnStatus;
4400
4401 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4402
4403 //
4404 // Check whether param ModeNumber is valid.
4405 // ModeNumber should be within range 0 ~ MaxMode - 1.
4406 //
4407 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {
4408 return EFI_UNSUPPORTED;
4409 }
4410
4411 if ((INT32) ModeNumber >= This->Mode->MaxMode) {
4412 return EFI_UNSUPPORTED;
4413 }
4414 //
4415 // If the mode is being set to the curent mode, then just clear the screen and return.
4416 //
4417 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {
4418 return ConSplitterTextOutClearScreen (This);
4419 }
4420 //
4421 // return the worst status met
4422 //
4423 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4424 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4425 Status = Private->TextOutList[Index].TextOut->SetMode (
4426 Private->TextOutList[Index].TextOut,
4427 TextOutModeMap[Index]
4428 );
4429 if (EFI_ERROR (Status)) {
4430 ReturnStatus = Status;
4431 }
4432 }
4433
4434 //
4435 // Set mode parameter to specified mode number
4436 //
4437 TextOutSetMode (Private, ModeNumber);
4438
4439 return ReturnStatus;
4440 }
4441
4442
4443 /**
4444 Sets the background and foreground colors for the OutputString () and
4445 ClearScreen () functions.
4446
4447 @param This Protocol instance pointer.
4448 @param Attribute The attribute to set. Bits 0..3 are the
4449 foreground color, and bits 4..6 are the
4450 background color. All other bits are undefined
4451 and must be zero. The valid Attributes are
4452 defined in this file.
4453
4454 @retval EFI_SUCCESS The attribute was set.
4455 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4456 the request.
4457 @retval EFI_UNSUPPORTED The attribute requested is not defined.
4458
4459 **/
4460 EFI_STATUS
4461 EFIAPI
4462 ConSplitterTextOutSetAttribute (
4463 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4464 IN UINTN Attribute
4465 )
4466 {
4467 EFI_STATUS Status;
4468 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4469 UINTN Index;
4470 EFI_STATUS ReturnStatus;
4471
4472 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4473
4474 //
4475 // Check whether param Attribute is valid.
4476 //
4477 if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {
4478 return EFI_UNSUPPORTED;
4479 }
4480
4481 //
4482 // return the worst status met
4483 //
4484 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4485 Status = Private->TextOutList[Index].TextOut->SetAttribute (
4486 Private->TextOutList[Index].TextOut,
4487 Attribute
4488 );
4489 if (EFI_ERROR (Status)) {
4490 ReturnStatus = Status;
4491 }
4492 }
4493
4494 Private->TextOutMode.Attribute = (INT32) Attribute;
4495
4496 return ReturnStatus;
4497 }
4498
4499
4500 /**
4501 Clears the output device(s) display to the currently selected background
4502 color.
4503
4504 @param This Protocol instance pointer.
4505
4506 @retval EFI_SUCCESS The operation completed successfully.
4507 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4508 the request.
4509 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4510
4511 **/
4512 EFI_STATUS
4513 EFIAPI
4514 ConSplitterTextOutClearScreen (
4515 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
4516 )
4517 {
4518 EFI_STATUS Status;
4519 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4520 UINTN Index;
4521 EFI_STATUS ReturnStatus;
4522
4523 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4524
4525 //
4526 // return the worst status met
4527 //
4528 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4529 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);
4530 if (EFI_ERROR (Status)) {
4531 ReturnStatus = Status;
4532 }
4533 }
4534
4535 //
4536 // No need to do extra check here as whether (Column, Row) is valid has
4537 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4538 // always be supported.
4539 //
4540 Private->TextOutMode.CursorColumn = 0;
4541 Private->TextOutMode.CursorRow = 0;
4542 Private->TextOutMode.CursorVisible = TRUE;
4543
4544 return ReturnStatus;
4545 }
4546
4547
4548 /**
4549 Sets the current coordinates of the cursor position
4550
4551 @param This Protocol instance pointer.
4552 @param Column The column position to set the cursor to. Must be
4553 greater than or equal to zero and less than the
4554 number of columns by QueryMode ().
4555 @param Row The row position to set the cursor to. Must be
4556 greater than or equal to zero and less than the
4557 number of rows by QueryMode ().
4558
4559 @retval EFI_SUCCESS The operation completed successfully.
4560 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4561 the request.
4562 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,
4563 or the cursor position is invalid for the
4564 current mode.
4565
4566 **/
4567 EFI_STATUS
4568 EFIAPI
4569 ConSplitterTextOutSetCursorPosition (
4570 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4571 IN UINTN Column,
4572 IN UINTN Row
4573 )
4574 {
4575 EFI_STATUS Status;
4576 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4577 UINTN Index;
4578 EFI_STATUS ReturnStatus;
4579 UINTN MaxColumn;
4580 UINTN MaxRow;
4581 INT32 *TextOutModeMap;
4582 INT32 ModeNumber;
4583 INT32 CurrentMode;
4584
4585 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4586 TextOutModeMap = NULL;
4587 ModeNumber = Private->TextOutMode.Mode;
4588
4589 //
4590 // Get current MaxColumn and MaxRow from intersection map
4591 //
4592 if (Private->TextOutModeMap != NULL) {
4593 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;
4594 CurrentMode = *TextOutModeMap;
4595 } else {
4596 CurrentMode = ModeNumber;
4597 }
4598
4599 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;
4600 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;
4601
4602 if (Column >= MaxColumn || Row >= MaxRow) {
4603 return EFI_UNSUPPORTED;
4604 }
4605 //
4606 // return the worst status met
4607 //
4608 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4609 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (
4610 Private->TextOutList[Index].TextOut,
4611 Column,
4612 Row
4613 );
4614 if (EFI_ERROR (Status)) {
4615 ReturnStatus = Status;
4616 }
4617 }
4618
4619 //
4620 // No need to do extra check here as whether (Column, Row) is valid has
4621 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
4622 // always be supported.
4623 //
4624 Private->TextOutMode.CursorColumn = (INT32) Column;
4625 Private->TextOutMode.CursorRow = (INT32) Row;
4626
4627 return ReturnStatus;
4628 }
4629
4630
4631 /**
4632 Makes the cursor visible or invisible
4633
4634 @param This Protocol instance pointer.
4635 @param Visible If TRUE, the cursor is set to be visible. If
4636 FALSE, the cursor is set to be invisible.
4637
4638 @retval EFI_SUCCESS The operation completed successfully.
4639 @retval EFI_DEVICE_ERROR The device had an error and could not complete
4640 the request, or the device does not support
4641 changing the cursor mode.
4642 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
4643
4644 **/
4645 EFI_STATUS
4646 EFIAPI
4647 ConSplitterTextOutEnableCursor (
4648 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
4649 IN BOOLEAN Visible
4650 )
4651 {
4652 EFI_STATUS Status;
4653 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
4654 UINTN Index;
4655 EFI_STATUS ReturnStatus;
4656
4657 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
4658
4659 //
4660 // return the worst status met
4661 //
4662 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
4663 Status = Private->TextOutList[Index].TextOut->EnableCursor (
4664 Private->TextOutList[Index].TextOut,
4665 Visible
4666 );
4667 if (EFI_ERROR (Status)) {
4668 ReturnStatus = Status;
4669 }
4670 }
4671
4672 Private->TextOutMode.CursorVisible = Visible;
4673
4674 return ReturnStatus;
4675 }
4676