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