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