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