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