1. Add PcdConOutGopSupport and PcdConOutUgaSupport in MdeModulePkg.dec
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitter.c
1 /**@file
2 Console Splitter Driver. Any Handle that attatched
3 EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver.
4
5 So far it works like any other driver by opening a SimpleTextIn and/or
6 SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big
7 difference is this driver does not layer a protocol on the passed in
8 handle, or construct a child handle like a standard device or bus driver.
9 This driver produces three virtual handles as children, one for console input
10 splitter, one for console output splitter and one for error output splitter.
11 EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to
12 identify the splitter type.
13
14 Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL
15 and Console I/O protocol, will be produced in the driver entry point.
16 The virtual handle are added on driver entry and never removed.
17 Such design ensures sytem function well during none console device situation.
18
19 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
20 All rights reserved. This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
24
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27
28 **/
29
30 #include "ConSplitter.h"
31
32 //
33 // Global Variables
34 //
35 STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {
36 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE,
37 (EFI_HANDLE) NULL,
38 {
39 ConSplitterTextInReset,
40 ConSplitterTextInReadKeyStroke,
41 (EFI_EVENT) NULL
42 },
43 0,
44 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,
45 0,
46
47 {
48 ConSplitterSimplePointerReset,
49 ConSplitterSimplePointerGetState,
50 (EFI_EVENT) NULL,
51 (EFI_SIMPLE_POINTER_MODE *) NULL
52 },
53 {
54 0x10000,
55 0x10000,
56 0x10000,
57 TRUE,
58 TRUE
59 },
60 0,
61 (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,
62 0,
63
64 FALSE,
65 {
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
70 },
71 0,
72 {
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
77 },
78 (EFI_EVENT) NULL,
79
80 FALSE,
81 FALSE
82 };
83
84 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
85 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
86 (EFI_HANDLE) NULL,
87 {
88 ConSplitterTextOutReset,
89 ConSplitterTextOutOutputString,
90 ConSplitterTextOutTestString,
91 ConSplitterTextOutQueryMode,
92 ConSplitterTextOutSetMode,
93 ConSplitterTextOutSetAttribute,
94 ConSplitterTextOutClearScreen,
95 ConSplitterTextOutSetCursorPosition,
96 ConSplitterTextOutEnableCursor,
97 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
98 },
99 {
100 1,
101 0,
102 0,
103 0,
104 0,
105 FALSE,
106 },
107 {
108 ConSpliterUgaDrawGetMode,
109 ConSpliterUgaDrawSetMode,
110 ConSpliterUgaDrawBlt
111 },
112 0,
113 0,
114 0,
115 0,
116 (EFI_UGA_PIXEL *) NULL,
117 {
118 ConSpliterGraphicsOutputQueryMode,
119 ConSpliterGraphicsOutputSetMode,
120 ConSpliterGraphicsOutputBlt,
121 NULL
122 },
123 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
124 (TEXT_OUT_GOP_MODE *) NULL,
125 0,
126 TRUE,
127 {
128 ConSpliterConsoleControlGetMode,
129 ConSpliterConsoleControlSetMode,
130 ConSpliterConsoleControlLockStdIn
131 },
132
133 0,
134 (TEXT_OUT_AND_GOP_DATA *) NULL,
135 0,
136 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
137 0,
138 (INT32 *) NULL,
139
140 EfiConsoleControlScreenText,
141 0,
142 0,
143 (CHAR16 *) NULL,
144 (INT32 *) NULL
145 };
146
147 STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
148 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,
149 (EFI_HANDLE) NULL,
150 {
151 ConSplitterTextOutReset,
152 ConSplitterTextOutOutputString,
153 ConSplitterTextOutTestString,
154 ConSplitterTextOutQueryMode,
155 ConSplitterTextOutSetMode,
156 ConSplitterTextOutSetAttribute,
157 ConSplitterTextOutClearScreen,
158 ConSplitterTextOutSetCursorPosition,
159 ConSplitterTextOutEnableCursor,
160 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL
161 },
162 {
163 1,
164 0,
165 0,
166 0,
167 0,
168 FALSE,
169 },
170 {
171 ConSpliterUgaDrawGetMode,
172 ConSpliterUgaDrawSetMode,
173 ConSpliterUgaDrawBlt
174 },
175 0,
176 0,
177 0,
178 0,
179 (EFI_UGA_PIXEL *) NULL,
180 {
181 ConSpliterGraphicsOutputQueryMode,
182 ConSpliterGraphicsOutputSetMode,
183 ConSpliterGraphicsOutputBlt,
184 NULL
185 },
186 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
187 (TEXT_OUT_GOP_MODE *) NULL,
188 0,
189 TRUE,
190 {
191 ConSpliterConsoleControlGetMode,
192 ConSpliterConsoleControlSetMode,
193 ConSpliterConsoleControlLockStdIn
194 },
195
196 0,
197 (TEXT_OUT_AND_GOP_DATA *) NULL,
198 0,
199 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,
200 0,
201 (INT32 *) NULL,
202
203 EfiConsoleControlScreenText,
204 0,
205 0,
206 (CHAR16 *) NULL,
207 (INT32 *) NULL
208 };
209
210 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = {
211 ConSplitterConInDriverBindingSupported,
212 ConSplitterConInDriverBindingStart,
213 ConSplitterConInDriverBindingStop,
214 0xa,
215 NULL,
216 NULL
217 };
218
219 EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = {
220 ConSplitterSimplePointerDriverBindingSupported,
221 ConSplitterSimplePointerDriverBindingStart,
222 ConSplitterSimplePointerDriverBindingStop,
223 0xa,
224 NULL,
225 NULL
226 };
227
228 EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = {
229 ConSplitterConOutDriverBindingSupported,
230 ConSplitterConOutDriverBindingStart,
231 ConSplitterConOutDriverBindingStop,
232 0xa,
233 NULL,
234 NULL
235 };
236
237 EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = {
238 ConSplitterStdErrDriverBindingSupported,
239 ConSplitterStdErrDriverBindingStart,
240 ConSplitterStdErrDriverBindingStop,
241 0xa,
242 NULL,
243 NULL
244 };
245
246 /**
247 The user Entry Point for module ConSplitter. The user code starts with this function.
248
249 @param[in] ImageHandle The firmware allocated handle for the EFI image.
250 @param[in] SystemTable A pointer to the EFI System Table.
251
252 @retval EFI_SUCCESS The entry point is executed successfully.
253 @retval other Some error occurs when executing this entry point.
254
255 **/
256 EFI_STATUS
257 EFIAPI
258 InitializeConSplitter(
259 IN EFI_HANDLE ImageHandle,
260 IN EFI_SYSTEM_TABLE *SystemTable
261 )
262 {
263 EFI_STATUS Status;
264
265 //
266 // Install driver model protocol(s).
267 //
268 Status = EfiLibInstallDriverBindingComponentName2 (
269 ImageHandle,
270 SystemTable,
271 &gConSplitterConInDriverBinding,
272 ImageHandle,
273 &gConSplitterConInComponentName,
274 &gConSplitterConInComponentName2
275 );
276 ASSERT_EFI_ERROR (Status);
277
278 Status = EfiLibInstallDriverBindingComponentName2 (
279 ImageHandle,
280 SystemTable,
281 &gConSplitterSimplePointerDriverBinding,
282 NULL,
283 &gConSplitterSimplePointerComponentName,
284 &gConSplitterSimplePointerComponentName2
285 );
286 ASSERT_EFI_ERROR (Status);
287
288 Status = EfiLibInstallDriverBindingComponentName2 (
289 ImageHandle,
290 SystemTable,
291 &gConSplitterConOutDriverBinding,
292 NULL,
293 &gConSplitterConOutComponentName,
294 &gConSplitterConOutComponentName2
295 );
296 ASSERT_EFI_ERROR (Status);
297
298 Status = EfiLibInstallDriverBindingComponentName2 (
299 ImageHandle,
300 SystemTable,
301 &gConSplitterStdErrDriverBinding,
302 NULL,
303 &gConSplitterStdErrComponentName,
304 &gConSplitterStdErrComponentName2
305 );
306 ASSERT_EFI_ERROR (Status);
307
308
309 //
310 // Call the original Entry Point
311 //
312 Status = ConSplitterDriverEntry (ImageHandle, SystemTable);
313
314 return Status;
315 }
316
317
318 EFI_STATUS
319 EFIAPI
320 ConSplitterDriverEntry (
321 IN EFI_HANDLE ImageHandle,
322 IN EFI_SYSTEM_TABLE *SystemTable
323 )
324 /*++
325
326 Routine Description:
327 Intialize a virtual console device to act as an agrigator of physical console
328 devices.
329
330 Arguments:
331 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
332 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
333 Returns:
334 EFI_SUCCESS
335
336 --*/
337 {
338 EFI_STATUS Status;
339
340 ASSERT (FeaturePcdGet (PcdConOutGopSupport) ||
341 FeaturePcdGet (PcdConOutUgaSupport));
342 //
343 // The driver creates virtual handles for ConIn, ConOut, and StdErr.
344 // The virtual handles will always exist even if no console exist in the
345 // system. This is need to support hotplug devices like USB.
346 //
347 //
348 // Create virtual device handle for StdErr Splitter
349 //
350 Status = ConSplitterTextOutConstructor (&mStdErr);
351 if (!EFI_ERROR (Status)) {
352 Status = gBS->InstallMultipleProtocolInterfaces (
353 &mStdErr.VirtualHandle,
354 &gEfiSimpleTextOutProtocolGuid,
355 &mStdErr.TextOut,
356 &gEfiPrimaryStandardErrorDeviceGuid,
357 NULL,
358 NULL
359 );
360 }
361 //
362 // Create virtual device handle for ConIn Splitter
363 //
364 Status = ConSplitterTextInConstructor (&mConIn);
365 if (!EFI_ERROR (Status)) {
366 Status = gBS->InstallMultipleProtocolInterfaces (
367 &mConIn.VirtualHandle,
368 &gEfiSimpleTextInProtocolGuid,
369 &mConIn.TextIn,
370 &gEfiSimplePointerProtocolGuid,
371 &mConIn.SimplePointer,
372 &gEfiPrimaryConsoleInDeviceGuid,
373 NULL,
374 NULL
375 );
376 if (!EFI_ERROR (Status)) {
377 //
378 // Update the EFI System Table with new virtual console
379 //
380 gST->ConsoleInHandle = mConIn.VirtualHandle;
381 gST->ConIn = &mConIn.TextIn;
382 }
383 }
384 //
385 // Create virtual device handle for ConOut Splitter
386 //
387 Status = ConSplitterTextOutConstructor (&mConOut);
388 if (!EFI_ERROR (Status)) {
389 if (!FeaturePcdGet (PcdConOutGopSupport)) {
390 //
391 // In EFI mode, UGA Draw protocol is installed
392 //
393 Status = gBS->InstallMultipleProtocolInterfaces (
394 &mConOut.VirtualHandle,
395 &gEfiSimpleTextOutProtocolGuid,
396 &mConOut.TextOut,
397 &gEfiUgaDrawProtocolGuid,
398 &mConOut.UgaDraw,
399 &gEfiConsoleControlProtocolGuid,
400 &mConOut.ConsoleControl,
401 &gEfiPrimaryConsoleOutDeviceGuid,
402 NULL,
403 NULL
404 );
405 } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
406 //
407 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.
408 //
409 Status = gBS->InstallMultipleProtocolInterfaces (
410 &mConOut.VirtualHandle,
411 &gEfiSimpleTextOutProtocolGuid,
412 &mConOut.TextOut,
413 &gEfiGraphicsOutputProtocolGuid,
414 &mConOut.GraphicsOutput,
415 &gEfiConsoleControlProtocolGuid,
416 &mConOut.ConsoleControl,
417 &gEfiPrimaryConsoleOutDeviceGuid,
418 NULL,
419 NULL
420 );
421 } else {
422 //
423 // In EFI and UEFI comptible mode, Graphics Output Protocol and UGA are
424 // installed on virtual handle.
425 //
426 Status = gBS->InstallMultipleProtocolInterfaces (
427 &mConOut.VirtualHandle,
428 &gEfiSimpleTextOutProtocolGuid,
429 &mConOut.TextOut,
430 &gEfiGraphicsOutputProtocolGuid,
431 &mConOut.GraphicsOutput,
432 &gEfiUgaDrawProtocolGuid,
433 &mConOut.UgaDraw,
434 &gEfiConsoleControlProtocolGuid,
435 &mConOut.ConsoleControl,
436 &gEfiPrimaryConsoleOutDeviceGuid,
437 NULL,
438 NULL
439 );
440 }
441
442 if (!EFI_ERROR (Status)) {
443 //
444 // Update the EFI System Table with new virtual console
445 //
446 gST->ConsoleOutHandle = mConOut.VirtualHandle;
447 gST->ConOut = &mConOut.TextOut;
448 }
449
450 }
451 //
452 // Update the CRC32 in the EFI System Table header
453 //
454 gST->Hdr.CRC32 = 0;
455 gBS->CalculateCrc32 (
456 (UINT8 *) &gST->Hdr,
457 gST->Hdr.HeaderSize,
458 &gST->Hdr.CRC32
459 );
460
461 return EFI_SUCCESS;
462 }
463
464 EFI_STATUS
465 ConSplitterTextInConstructor (
466 TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate
467 )
468 /*++
469
470 Routine Description:
471
472 Construct the ConSplitter.
473
474 Arguments:
475
476 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.
477
478 Returns:
479 EFI_OUT_OF_RESOURCES - Out of resources.
480
481 --*/
482 {
483 EFI_STATUS Status;
484
485 //
486 // Initilize console input splitter's private data.
487 //
488 Status = ConSplitterGrowBuffer (
489 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),
490 &ConInPrivate->TextInListCount,
491 (VOID **) &ConInPrivate->TextInList
492 );
493 if (EFI_ERROR (Status)) {
494 return EFI_OUT_OF_RESOURCES;
495 }
496 //
497 // Create Event to support locking StdIn Device
498 //
499 Status = gBS->CreateEvent (
500 EVT_TIMER | EVT_NOTIFY_SIGNAL,
501 TPL_CALLBACK,
502 ConSpliterConsoleControlLockStdInEvent,
503 NULL,
504 &ConInPrivate->LockEvent
505 );
506 ASSERT_EFI_ERROR (Status);
507
508 Status = gBS->CreateEvent (
509 EVT_NOTIFY_WAIT,
510 TPL_NOTIFY,
511 ConSplitterTextInWaitForKey,
512 ConInPrivate,
513 &ConInPrivate->TextIn.WaitForKey
514 );
515 ASSERT_EFI_ERROR (Status);
516
517 ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;
518
519 Status = ConSplitterGrowBuffer (
520 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
521 &ConInPrivate->PointerListCount,
522 (VOID **) &ConInPrivate->PointerList
523 );
524 if (EFI_ERROR (Status)) {
525 return EFI_OUT_OF_RESOURCES;
526 }
527
528 Status = gBS->CreateEvent (
529 EVT_NOTIFY_WAIT,
530 TPL_NOTIFY,
531 ConSplitterSimplePointerWaitForInput,
532 ConInPrivate,
533 &ConInPrivate->SimplePointer.WaitForInput
534 );
535
536 return Status;
537 }
538
539 EFI_STATUS
540 ConSplitterTextOutConstructor (
541 TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate
542 )
543 {
544 EFI_STATUS Status;
545
546 //
547 // Initilize console output splitter's private data.
548 //
549 ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;
550
551 Status = ConSplitterGrowBuffer (
552 sizeof (TEXT_OUT_AND_GOP_DATA),
553 &ConOutPrivate->TextOutListCount,
554 (VOID **) &ConOutPrivate->TextOutList
555 );
556 if (EFI_ERROR (Status)) {
557 return EFI_OUT_OF_RESOURCES;
558 }
559
560 Status = ConSplitterGrowBuffer (
561 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
562 &ConOutPrivate->TextOutQueryDataCount,
563 (VOID **) &ConOutPrivate->TextOutQueryData
564 );
565 if (EFI_ERROR (Status)) {
566 return EFI_OUT_OF_RESOURCES;
567 }
568 //
569 // Setup the DevNullTextOut console to 80 x 25
570 //
571 ConOutPrivate->TextOutQueryData[0].Columns = 80;
572 ConOutPrivate->TextOutQueryData[0].Rows = 25;
573 DevNullTextOutSetMode (ConOutPrivate, 0);
574
575 if (FeaturePcdGet (PcdConOutUgaSupport)) {
576 //
577 // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel
578 //
579 ConSpliterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);
580 }
581 if (FeaturePcdGet (PcdConOutGopSupport)) {
582 //
583 // Setup resource for mode information in Graphics Output Protocol interface
584 //
585 if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {
586 return EFI_OUT_OF_RESOURCES;
587 }
588 if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {
589 return EFI_OUT_OF_RESOURCES;
590 }
591 //
592 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel
593 //
594 if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {
595 return EFI_OUT_OF_RESOURCES;
596 }
597 ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;
598 ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;
599
600 //
601 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()
602 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
603 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
604 //
605 ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;
606 ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
607 ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
608 ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;
609 ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;
610
611 ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;
612 //
613 // Initial current mode to unknow state, and then set to mode 0
614 //
615 ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;
616 ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);
617 }
618
619 return Status;
620 }
621
622 STATIC
623 EFI_STATUS
624 ConSplitterSupported (
625 IN EFI_DRIVER_BINDING_PROTOCOL *This,
626 IN EFI_HANDLE ControllerHandle,
627 IN EFI_GUID *Guid
628 )
629 /*++
630
631 Routine Description:
632 Generic Supported Check
633
634 Arguments:
635 This - Pointer to protocol.
636 ControllerHandle - Controller Handle.
637 Guid - Guid.
638
639 Returns:
640
641 EFI_UNSUPPORTED - unsupported.
642 EFI_SUCCESS - operation is OK.
643
644 --*/
645 {
646 EFI_STATUS Status;
647 VOID *Instance;
648
649 //
650 // Make sure the Console Splitter does not attempt to attach to itself
651 //
652 if (ControllerHandle == mConIn.VirtualHandle) {
653 return EFI_UNSUPPORTED;
654 }
655
656 if (ControllerHandle == mConOut.VirtualHandle) {
657 return EFI_UNSUPPORTED;
658 }
659
660 if (ControllerHandle == mStdErr.VirtualHandle) {
661 return EFI_UNSUPPORTED;
662 }
663 //
664 // Check to see whether the handle has the ConsoleInDevice GUID on it
665 //
666 Status = gBS->OpenProtocol (
667 ControllerHandle,
668 Guid,
669 &Instance,
670 This->DriverBindingHandle,
671 ControllerHandle,
672 EFI_OPEN_PROTOCOL_BY_DRIVER
673 );
674
675 if (EFI_ERROR (Status)) {
676 return Status;
677 }
678
679 gBS->CloseProtocol (
680 ControllerHandle,
681 Guid,
682 This->DriverBindingHandle,
683 ControllerHandle
684 );
685
686 return EFI_SUCCESS;
687 }
688
689 EFI_STATUS
690 EFIAPI
691 ConSplitterConInDriverBindingSupported (
692 IN EFI_DRIVER_BINDING_PROTOCOL *This,
693 IN EFI_HANDLE ControllerHandle,
694 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
695 )
696 /*++
697
698 Routine Description:
699 Console In Supported Check
700
701 Arguments:
702 This - Pointer to protocol.
703 ControllerHandle - Controller handle.
704 RemainingDevicePath - Remaining device path.
705
706 Returns:
707
708 EFI_STATUS
709
710 --*/
711 {
712 return ConSplitterSupported (
713 This,
714 ControllerHandle,
715 &gEfiConsoleInDeviceGuid
716 );
717 }
718
719 EFI_STATUS
720 EFIAPI
721 ConSplitterSimplePointerDriverBindingSupported (
722 IN EFI_DRIVER_BINDING_PROTOCOL *This,
723 IN EFI_HANDLE ControllerHandle,
724 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
725 )
726 /*++
727
728 Routine Description:
729 Standard Error Supported Check
730
731 Arguments:
732 This - Pointer to protocol.
733 ControllerHandle - Controller handle.
734 RemainingDevicePath - Remaining device path.
735
736 Returns:
737
738 EFI_STATUS
739
740 --*/
741 {
742 return ConSplitterSupported (
743 This,
744 ControllerHandle,
745 &gEfiSimplePointerProtocolGuid
746 );
747 }
748
749 EFI_STATUS
750 EFIAPI
751 ConSplitterConOutDriverBindingSupported (
752 IN EFI_DRIVER_BINDING_PROTOCOL *This,
753 IN EFI_HANDLE ControllerHandle,
754 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
755 )
756 /*++
757
758 Routine Description:
759 Console Out Supported Check
760
761 Arguments:
762 This - Pointer to protocol.
763 ControllerHandle - Controller handle.
764 RemainingDevicePath - Remaining device path.
765
766 Returns:
767
768 EFI_STATUS
769
770 --*/
771 {
772 return ConSplitterSupported (
773 This,
774 ControllerHandle,
775 &gEfiConsoleOutDeviceGuid
776 );
777 }
778
779 EFI_STATUS
780 EFIAPI
781 ConSplitterStdErrDriverBindingSupported (
782 IN EFI_DRIVER_BINDING_PROTOCOL *This,
783 IN EFI_HANDLE ControllerHandle,
784 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
785 )
786 /*++
787
788 Routine Description:
789 Standard Error Supported Check
790
791 Arguments:
792 This - Pointer to protocol.
793 ControllerHandle - Controller handle.
794 RemainingDevicePath - Remaining device path.
795
796 Returns:
797
798 EFI_STATUS
799
800 --*/
801 {
802 return ConSplitterSupported (
803 This,
804 ControllerHandle,
805 &gEfiStandardErrorDeviceGuid
806 );
807 }
808
809 STATIC
810 EFI_STATUS
811 EFIAPI
812 ConSplitterStart (
813 IN EFI_DRIVER_BINDING_PROTOCOL *This,
814 IN EFI_HANDLE ControllerHandle,
815 IN EFI_HANDLE ConSplitterVirtualHandle,
816 IN EFI_GUID *DeviceGuid,
817 IN EFI_GUID *InterfaceGuid,
818 IN VOID **Interface
819 )
820 /*++
821
822 Routine Description:
823 Start ConSplitter on ControllerHandle, and create the virtual
824 agrogated console device on first call Start for a SimpleTextIn handle.
825
826 Arguments:
827 (Standard DriverBinding Protocol Start() function)
828
829 Returns:
830 EFI_ERROR if a SimpleTextIn protocol is not started.
831
832 --*/
833 {
834 EFI_STATUS Status;
835 VOID *Instance;
836
837 //
838 // Check to see whether the handle has the ConsoleInDevice GUID on it
839 //
840 Status = gBS->OpenProtocol (
841 ControllerHandle,
842 DeviceGuid,
843 &Instance,
844 This->DriverBindingHandle,
845 ControllerHandle,
846 EFI_OPEN_PROTOCOL_BY_DRIVER
847 );
848 if (EFI_ERROR (Status)) {
849 return Status;
850 }
851
852 Status = gBS->OpenProtocol (
853 ControllerHandle,
854 DeviceGuid,
855 &Instance,
856 This->DriverBindingHandle,
857 ConSplitterVirtualHandle,
858 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
859 );
860 if (EFI_ERROR (Status)) {
861 return Status;
862 }
863
864 return gBS->OpenProtocol (
865 ControllerHandle,
866 InterfaceGuid,
867 Interface,
868 This->DriverBindingHandle,
869 ConSplitterVirtualHandle,
870 EFI_OPEN_PROTOCOL_GET_PROTOCOL
871 );
872 }
873
874 EFI_STATUS
875 EFIAPI
876 ConSplitterConInDriverBindingStart (
877 IN EFI_DRIVER_BINDING_PROTOCOL *This,
878 IN EFI_HANDLE ControllerHandle,
879 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
880 )
881 /*++
882
883 Routine Description:
884 Start ConSplitter on ControllerHandle, and create the virtual
885 agrogated console device on first call Start for a SimpleTextIn handle.
886
887 Arguments:
888 This - Pointer to protocol.
889 ControllerHandle - Controller handle.
890 RemainingDevicePath - Remaining device path.
891
892 Returns:
893
894 EFI_STATUS
895 EFI_ERROR if a SimpleTextIn protocol is not started.
896
897 --*/
898 {
899 EFI_STATUS Status;
900 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;
901
902 //
903 // Start ConSplitter on ControllerHandle, and create the virtual
904 // agrogated console device on first call Start for a SimpleTextIn handle.
905 //
906 Status = ConSplitterStart (
907 This,
908 ControllerHandle,
909 mConIn.VirtualHandle,
910 &gEfiConsoleInDeviceGuid,
911 &gEfiSimpleTextInProtocolGuid,
912 (VOID **) &TextIn
913 );
914 if (EFI_ERROR (Status)) {
915 return Status;
916 }
917
918 return ConSplitterTextInAddDevice (&mConIn, TextIn);
919 }
920
921 EFI_STATUS
922 EFIAPI
923 ConSplitterSimplePointerDriverBindingStart (
924 IN EFI_DRIVER_BINDING_PROTOCOL *This,
925 IN EFI_HANDLE ControllerHandle,
926 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
927 )
928 /*++
929
930 Routine Description:
931 Start ConSplitter on ControllerHandle, and create the virtual
932 agrogated console device on first call Start for a SimpleTextIn handle.
933
934 Arguments:
935 This - Pointer to protocol.
936 ControllerHandle - Controller handle.
937 RemainingDevicePath - Remaining device path.
938
939 Returns:
940
941 EFI_ERROR if a SimpleTextIn protocol is not started.
942
943 --*/
944 {
945 EFI_STATUS Status;
946 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
947
948 Status = ConSplitterStart (
949 This,
950 ControllerHandle,
951 mConIn.VirtualHandle,
952 &gEfiSimplePointerProtocolGuid,
953 &gEfiSimplePointerProtocolGuid,
954 (VOID **) &SimplePointer
955 );
956 if (EFI_ERROR (Status)) {
957 return Status;
958 }
959
960 return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);
961 }
962
963 EFI_STATUS
964 EFIAPI
965 ConSplitterConOutDriverBindingStart (
966 IN EFI_DRIVER_BINDING_PROTOCOL *This,
967 IN EFI_HANDLE ControllerHandle,
968 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
969 )
970 /*++
971
972 Routine Description:
973 Start ConSplitter on ControllerHandle, and create the virtual
974 agrogated console device on first call Start for a SimpleTextIn handle.
975
976 Arguments:
977 This - Pointer to protocol.
978 ControllerHandle - Controller handle.
979 RemainingDevicePath - Remaining device path.
980
981 Returns:
982 EFI_ERROR if a SimpleTextIn protocol is not started.
983
984 --*/
985 {
986 EFI_STATUS Status;
987 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
988 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
989 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
990
991 Status = ConSplitterStart (
992 This,
993 ControllerHandle,
994 mConOut.VirtualHandle,
995 &gEfiConsoleOutDeviceGuid,
996 &gEfiSimpleTextOutProtocolGuid,
997 (VOID **) &TextOut
998 );
999 if (EFI_ERROR (Status)) {
1000 return Status;
1001 }
1002 //
1003 // Try to Open Graphics Output protocol
1004 //
1005 Status = gBS->OpenProtocol (
1006 ControllerHandle,
1007 &gEfiGraphicsOutputProtocolGuid,
1008 (VOID **) &GraphicsOutput,
1009 This->DriverBindingHandle,
1010 mConOut.VirtualHandle,
1011 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1012 );
1013 if (EFI_ERROR (Status)) {
1014 GraphicsOutput = NULL;
1015 }
1016 //
1017 // Open UGA_DRAW protocol
1018 //
1019 Status = gBS->OpenProtocol (
1020 ControllerHandle,
1021 &gEfiUgaDrawProtocolGuid,
1022 (VOID **) &UgaDraw,
1023 This->DriverBindingHandle,
1024 mConOut.VirtualHandle,
1025 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1026 );
1027 if (EFI_ERROR (Status)) {
1028 UgaDraw = NULL;
1029 }
1030 //
1031 // If both ConOut and StdErr incorporate the same Text Out device,
1032 // their MaxMode and QueryData should be the intersection of both.
1033 //
1034 Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);
1035 ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
1036
1037 if (FeaturePcdGet (PcdConOutUgaSupport)) {
1038 //
1039 // Match the UGA mode data of ConOut with the current mode
1040 //
1041 if (UgaDraw != NULL) {
1042 UgaDraw->GetMode (
1043 UgaDraw,
1044 &mConOut.UgaHorizontalResolution,
1045 &mConOut.UgaVerticalResolution,
1046 &mConOut.UgaColorDepth,
1047 &mConOut.UgaRefreshRate
1048 );
1049 }
1050 }
1051 return Status;
1052 }
1053
1054 EFI_STATUS
1055 EFIAPI
1056 ConSplitterStdErrDriverBindingStart (
1057 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1058 IN EFI_HANDLE ControllerHandle,
1059 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1060 )
1061 /*++
1062
1063 Routine Description:
1064 Start ConSplitter on ControllerHandle, and create the virtual
1065 agrogated console device on first call Start for a SimpleTextIn handle.
1066
1067 Arguments:
1068 This - Pointer to protocol.
1069 ControllerHandle - Controller handle.
1070 RemainingDevicePath - Remaining device path.
1071
1072 Returns:
1073 EFI_ERROR if a SimpleTextIn protocol is not started.
1074
1075 --*/
1076 {
1077 EFI_STATUS Status;
1078 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1079
1080 Status = ConSplitterStart (
1081 This,
1082 ControllerHandle,
1083 mStdErr.VirtualHandle,
1084 &gEfiStandardErrorDeviceGuid,
1085 &gEfiSimpleTextOutProtocolGuid,
1086 (VOID **) &TextOut
1087 );
1088 if (EFI_ERROR (Status)) {
1089 return Status;
1090 }
1091 //
1092 // If both ConOut and StdErr incorporate the same Text Out device,
1093 // their MaxMode and QueryData should be the intersection of both.
1094 //
1095 Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
1096 ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
1097 if (EFI_ERROR (Status)) {
1098 return Status;
1099 }
1100
1101 if (mStdErr.CurrentNumberOfConsoles == 1) {
1102 gST->StandardErrorHandle = mStdErr.VirtualHandle;
1103 gST->StdErr = &mStdErr.TextOut;
1104 //
1105 // Update the CRC32 in the EFI System Table header
1106 //
1107 gST->Hdr.CRC32 = 0;
1108 gBS->CalculateCrc32 (
1109 (UINT8 *) &gST->Hdr,
1110 gST->Hdr.HeaderSize,
1111 &gST->Hdr.CRC32
1112 );
1113 }
1114
1115 return Status;
1116 }
1117
1118 STATIC
1119 EFI_STATUS
1120 EFIAPI
1121 ConSplitterStop (
1122 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1123 IN EFI_HANDLE ControllerHandle,
1124 IN EFI_HANDLE ConSplitterVirtualHandle,
1125 IN EFI_GUID *DeviceGuid,
1126 IN EFI_GUID *InterfaceGuid,
1127 IN VOID **Interface
1128 )
1129 /*++
1130
1131 Routine Description:
1132
1133 Arguments:
1134 (Standard DriverBinding Protocol Stop() function)
1135
1136 Returns:
1137
1138 None
1139
1140 --*/
1141 {
1142 EFI_STATUS Status;
1143
1144 Status = gBS->OpenProtocol (
1145 ControllerHandle,
1146 InterfaceGuid,
1147 Interface,
1148 This->DriverBindingHandle,
1149 ControllerHandle,
1150 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1151 );
1152 if (EFI_ERROR (Status)) {
1153 return Status;
1154 }
1155 //
1156 // close the protocol refered.
1157 //
1158 gBS->CloseProtocol (
1159 ControllerHandle,
1160 DeviceGuid,
1161 This->DriverBindingHandle,
1162 ConSplitterVirtualHandle
1163 );
1164 gBS->CloseProtocol (
1165 ControllerHandle,
1166 DeviceGuid,
1167 This->DriverBindingHandle,
1168 ControllerHandle
1169 );
1170
1171 return EFI_SUCCESS;
1172 }
1173
1174 EFI_STATUS
1175 EFIAPI
1176 ConSplitterConInDriverBindingStop (
1177 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1178 IN EFI_HANDLE ControllerHandle,
1179 IN UINTN NumberOfChildren,
1180 IN EFI_HANDLE *ChildHandleBuffer
1181 )
1182 /*++
1183
1184 Routine Description:
1185
1186 Arguments:
1187 (Standard DriverBinding Protocol Stop() function)
1188
1189 Returns:
1190
1191 None
1192
1193 --*/
1194 {
1195 EFI_STATUS Status;
1196 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;
1197
1198 if (NumberOfChildren == 0) {
1199 return EFI_SUCCESS;
1200 }
1201
1202 Status = ConSplitterStop (
1203 This,
1204 ControllerHandle,
1205 mConIn.VirtualHandle,
1206 &gEfiConsoleInDeviceGuid,
1207 &gEfiSimpleTextInProtocolGuid,
1208 (VOID **) &TextIn
1209 );
1210 if (EFI_ERROR (Status)) {
1211 return Status;
1212 }
1213 //
1214 // Delete this console input device's data structures.
1215 //
1216 return ConSplitterTextInDeleteDevice (&mConIn, TextIn);
1217 }
1218
1219 EFI_STATUS
1220 EFIAPI
1221 ConSplitterSimplePointerDriverBindingStop (
1222 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1223 IN EFI_HANDLE ControllerHandle,
1224 IN UINTN NumberOfChildren,
1225 IN EFI_HANDLE *ChildHandleBuffer
1226 )
1227 /*++
1228
1229 Routine Description:
1230
1231 Arguments:
1232 (Standard DriverBinding Protocol Stop() function)
1233
1234 Returns:
1235
1236 None
1237
1238 --*/
1239 {
1240 EFI_STATUS Status;
1241 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
1242
1243 if (NumberOfChildren == 0) {
1244 return EFI_SUCCESS;
1245 }
1246
1247 Status = ConSplitterStop (
1248 This,
1249 ControllerHandle,
1250 mConIn.VirtualHandle,
1251 &gEfiSimplePointerProtocolGuid,
1252 &gEfiSimplePointerProtocolGuid,
1253 (VOID **) &SimplePointer
1254 );
1255 if (EFI_ERROR (Status)) {
1256 return Status;
1257 }
1258 //
1259 // Delete this console input device's data structures.
1260 //
1261 return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);
1262 }
1263
1264 EFI_STATUS
1265 EFIAPI
1266 ConSplitterConOutDriverBindingStop (
1267 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1268 IN EFI_HANDLE ControllerHandle,
1269 IN UINTN NumberOfChildren,
1270 IN EFI_HANDLE *ChildHandleBuffer
1271 )
1272 /*++
1273
1274 Routine Description:
1275
1276 Arguments:
1277 (Standard DriverBinding Protocol Stop() function)
1278
1279 Returns:
1280
1281 None
1282
1283 --*/
1284 {
1285 EFI_STATUS Status;
1286 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1287
1288 if (NumberOfChildren == 0) {
1289 return EFI_SUCCESS;
1290 }
1291
1292 Status = ConSplitterStop (
1293 This,
1294 ControllerHandle,
1295 mConOut.VirtualHandle,
1296 &gEfiConsoleOutDeviceGuid,
1297 &gEfiSimpleTextOutProtocolGuid,
1298 (VOID **) &TextOut
1299 );
1300 if (EFI_ERROR (Status)) {
1301 return Status;
1302 }
1303
1304 //
1305 // Delete this console output device's data structures.
1306 //
1307 return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);
1308 }
1309
1310 EFI_STATUS
1311 EFIAPI
1312 ConSplitterStdErrDriverBindingStop (
1313 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1314 IN EFI_HANDLE ControllerHandle,
1315 IN UINTN NumberOfChildren,
1316 IN EFI_HANDLE *ChildHandleBuffer
1317 )
1318 /*++
1319
1320 Routine Description:
1321
1322 Arguments:
1323 (Standard DriverBinding Protocol Stop() function)
1324
1325 Returns:
1326
1327 EFI_SUCCESS - Complete successfully.
1328
1329 --*/
1330 {
1331 EFI_STATUS Status;
1332 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
1333
1334 if (NumberOfChildren == 0) {
1335 return EFI_SUCCESS;
1336 }
1337
1338 Status = ConSplitterStop (
1339 This,
1340 ControllerHandle,
1341 mStdErr.VirtualHandle,
1342 &gEfiStandardErrorDeviceGuid,
1343 &gEfiSimpleTextOutProtocolGuid,
1344 (VOID **) &TextOut
1345 );
1346 if (EFI_ERROR (Status)) {
1347 return Status;
1348 }
1349 //
1350 // Delete this console error out device's data structures.
1351 //
1352 Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
1353 if (EFI_ERROR (Status)) {
1354 return Status;
1355 }
1356
1357 if (mStdErr.CurrentNumberOfConsoles == 0) {
1358 gST->StandardErrorHandle = NULL;
1359 gST->StdErr = NULL;
1360 //
1361 // Update the CRC32 in the EFI System Table header
1362 //
1363 gST->Hdr.CRC32 = 0;
1364 gBS->CalculateCrc32 (
1365 (UINT8 *) &gST->Hdr,
1366 gST->Hdr.HeaderSize,
1367 &gST->Hdr.CRC32
1368 );
1369 }
1370
1371 return Status;
1372 }
1373
1374 EFI_STATUS
1375 ConSplitterGrowBuffer (
1376 IN UINTN SizeOfCount,
1377 IN UINTN *Count,
1378 IN OUT VOID **Buffer
1379 )
1380 /*++
1381
1382 Routine Description:
1383 Take the passed in Buffer of size SizeOfCount and grow the buffer
1384 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
1385 bytes. Copy the current data in Buffer to the new version of Buffer
1386 and free the old version of buffer.
1387
1388
1389 Arguments:
1390 SizeOfCount - Size of element in array
1391 Count - Current number of elements in array
1392 Buffer - Bigger version of passed in Buffer with all the data
1393
1394 Returns:
1395 EFI_SUCCESS - Buffer size has grown
1396 EFI_OUT_OF_RESOURCES - Could not grow the buffer size
1397
1398 None
1399
1400 --*/
1401 {
1402 UINTN NewSize;
1403 UINTN OldSize;
1404 VOID *Ptr;
1405
1406 //
1407 // grow the buffer to new buffer size,
1408 // copy the old buffer's content to the new-size buffer,
1409 // then free the old buffer.
1410 //
1411 OldSize = *Count * SizeOfCount;
1412 *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;
1413 NewSize = *Count * SizeOfCount;
1414
1415 Ptr = AllocateZeroPool (NewSize);
1416 if (Ptr == NULL) {
1417 return EFI_OUT_OF_RESOURCES;
1418 }
1419
1420 CopyMem (Ptr, *Buffer, OldSize);
1421
1422 if (*Buffer != NULL) {
1423 FreePool (*Buffer);
1424 }
1425
1426 *Buffer = Ptr;
1427
1428 return EFI_SUCCESS;
1429 }
1430
1431 EFI_STATUS
1432 ConSplitterTextInAddDevice (
1433 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1434 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn
1435 )
1436 /*++
1437
1438 Routine Description:
1439
1440 Arguments:
1441
1442 Returns:
1443
1444 EFI_SUCCESS
1445 EFI_OUT_OF_RESOURCES
1446
1447 --*/
1448 {
1449 EFI_STATUS Status;
1450
1451 //
1452 // If the Text In List is full, enlarge it by calling growbuffer().
1453 //
1454 if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {
1455 Status = ConSplitterGrowBuffer (
1456 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),
1457 &Private->TextInListCount,
1458 (VOID **) &Private->TextInList
1459 );
1460 if (EFI_ERROR (Status)) {
1461 return EFI_OUT_OF_RESOURCES;
1462 }
1463 }
1464 //
1465 // Add the new text-in device data structure into the Text In List.
1466 //
1467 Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;
1468 Private->CurrentNumberOfConsoles++;
1469
1470 //
1471 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c
1472 //
1473 gBS->CheckEvent (TextIn->WaitForKey);
1474
1475 return EFI_SUCCESS;
1476 }
1477
1478 EFI_STATUS
1479 ConSplitterTextInDeleteDevice (
1480 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1481 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn
1482 )
1483 /*++
1484
1485 Routine Description:
1486
1487 Arguments:
1488
1489 Returns:
1490
1491 EFI_SUCCESS
1492 EFI_NOT_FOUND
1493
1494 --*/
1495 {
1496 UINTN Index;
1497 //
1498 // Remove the specified text-in device data structure from the Text In List,
1499 // and rearrange the remaining data structures in the Text In List.
1500 //
1501 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
1502 if (Private->TextInList[Index] == TextIn) {
1503 for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {
1504 Private->TextInList[Index] = Private->TextInList[Index + 1];
1505 }
1506
1507 Private->CurrentNumberOfConsoles--;
1508 return EFI_SUCCESS;
1509 }
1510 }
1511
1512 return EFI_NOT_FOUND;
1513 }
1514
1515 EFI_STATUS
1516 ConSplitterSimplePointerAddDevice (
1517 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1518 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
1519 )
1520 /*++
1521
1522 Routine Description:
1523
1524 Arguments:
1525
1526 Returns:
1527
1528 EFI_OUT_OF_RESOURCES
1529 EFI_SUCCESS
1530
1531 --*/
1532 {
1533 EFI_STATUS Status;
1534
1535 //
1536 // If the Text In List is full, enlarge it by calling growbuffer().
1537 //
1538 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {
1539 Status = ConSplitterGrowBuffer (
1540 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
1541 &Private->PointerListCount,
1542 (VOID **) &Private->PointerList
1543 );
1544 if (EFI_ERROR (Status)) {
1545 return EFI_OUT_OF_RESOURCES;
1546 }
1547 }
1548 //
1549 // Add the new text-in device data structure into the Text In List.
1550 //
1551 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;
1552 Private->CurrentNumberOfPointers++;
1553 return EFI_SUCCESS;
1554 }
1555
1556 EFI_STATUS
1557 ConSplitterSimplePointerDeleteDevice (
1558 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
1559 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
1560 )
1561 /*++
1562
1563 Routine Description:
1564
1565 Arguments:
1566
1567 Returns:
1568
1569 None
1570
1571 --*/
1572 {
1573 UINTN Index;
1574 //
1575 // Remove the specified text-in device data structure from the Text In List,
1576 // and rearrange the remaining data structures in the Text In List.
1577 //
1578 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
1579 if (Private->PointerList[Index] == SimplePointer) {
1580 for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {
1581 Private->PointerList[Index] = Private->PointerList[Index + 1];
1582 }
1583
1584 Private->CurrentNumberOfPointers--;
1585 return EFI_SUCCESS;
1586 }
1587 }
1588
1589 return EFI_NOT_FOUND;
1590 }
1591
1592 STATIC
1593 EFI_STATUS
1594 ConSplitterGrowMapTable (
1595 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1596 )
1597 /*++
1598
1599 Routine Description:
1600
1601 Arguments:
1602
1603 Returns:
1604
1605 None
1606
1607 --*/
1608 {
1609 UINTN Size;
1610 UINTN NewSize;
1611 UINTN TotalSize;
1612 INT32 *TextOutModeMap;
1613 INT32 *OldTextOutModeMap;
1614 INT32 *SrcAddress;
1615 INT32 Index;
1616
1617 NewSize = Private->TextOutListCount * sizeof (INT32);
1618 OldTextOutModeMap = Private->TextOutModeMap;
1619 TotalSize = NewSize * Private->TextOutQueryDataCount;
1620
1621 TextOutModeMap = AllocateZeroPool (TotalSize);
1622 if (TextOutModeMap == NULL) {
1623 return EFI_OUT_OF_RESOURCES;
1624 }
1625
1626 SetMem (TextOutModeMap, TotalSize, 0xFF);
1627 Private->TextOutModeMap = TextOutModeMap;
1628
1629 //
1630 // If TextOutList has been enlarged, need to realloc the mode map table
1631 // The mode map table is regarded as a two dimension array.
1632 //
1633 // Old New
1634 // 0 ---------> TextOutListCount ----> TextOutListCount
1635 // | -------------------------------------------
1636 // | | | |
1637 // | | | |
1638 // | | | |
1639 // | | | |
1640 // | | | |
1641 // \/ | | |
1642 // -------------------------------------------
1643 // QueryDataCount
1644 //
1645 if (OldTextOutModeMap != NULL) {
1646
1647 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);
1648 Index = 0;
1649 SrcAddress = OldTextOutModeMap;
1650
1651 //
1652 // Copy the old data to the new one
1653 //
1654 while (Index < Private->TextOutMode.MaxMode) {
1655 CopyMem (TextOutModeMap, SrcAddress, Size);
1656 TextOutModeMap += NewSize;
1657 SrcAddress += Size;
1658 Index++;
1659 }
1660 //
1661 // Free the old buffer
1662 //
1663 FreePool (OldTextOutModeMap);
1664 }
1665
1666 return EFI_SUCCESS;
1667 }
1668
1669 STATIC
1670 EFI_STATUS
1671 ConSplitterAddOutputMode (
1672 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1673 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
1674 )
1675 /*++
1676
1677 Routine Description:
1678
1679 Arguments:
1680
1681 Returns:
1682
1683 None
1684
1685 --*/
1686 {
1687 EFI_STATUS Status;
1688 INT32 MaxMode;
1689 INT32 Mode;
1690 UINTN Index;
1691
1692 MaxMode = TextOut->Mode->MaxMode;
1693 Private->TextOutMode.MaxMode = MaxMode;
1694
1695 //
1696 // Grow the buffer if query data buffer is not large enough to
1697 // hold all the mode supported by the first console.
1698 //
1699 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {
1700 Status = ConSplitterGrowBuffer (
1701 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),
1702 &Private->TextOutQueryDataCount,
1703 (VOID **) &Private->TextOutQueryData
1704 );
1705 if (EFI_ERROR (Status)) {
1706 return EFI_OUT_OF_RESOURCES;
1707 }
1708 }
1709 //
1710 // Allocate buffer for the output mode map
1711 //
1712 Status = ConSplitterGrowMapTable (Private);
1713 if (EFI_ERROR (Status)) {
1714 return EFI_OUT_OF_RESOURCES;
1715 }
1716 //
1717 // As the first textout device, directly add the mode in to QueryData
1718 // and at the same time record the mapping between QueryData and TextOut.
1719 //
1720 Mode = 0;
1721 Index = 0;
1722 while (Mode < MaxMode) {
1723 TextOut->QueryMode (
1724 TextOut,
1725 Mode,
1726 &Private->TextOutQueryData[Mode].Columns,
1727 &Private->TextOutQueryData[Mode].Rows
1728 );
1729 Private->TextOutModeMap[Index] = Mode;
1730 Mode++;
1731 Index += Private->TextOutListCount;
1732 }
1733
1734 return EFI_SUCCESS;
1735 }
1736
1737 STATIC
1738 VOID
1739 ConSplitterGetIntersection (
1740 IN INT32 *TextOutModeMap,
1741 IN INT32 *NewlyAddedMap,
1742 IN UINTN MapStepSize,
1743 IN UINTN NewMapStepSize,
1744 OUT INT32 *MaxMode,
1745 OUT INT32 *CurrentMode
1746 )
1747 {
1748 INT32 Index;
1749 INT32 *CurrentMapEntry;
1750 INT32 *NextMapEntry;
1751 INT32 CurrentMaxMode;
1752 INT32 Mode;
1753
1754 Index = 0;
1755 CurrentMapEntry = TextOutModeMap;
1756 NextMapEntry = TextOutModeMap;
1757 CurrentMaxMode = *MaxMode;
1758 Mode = *CurrentMode;
1759
1760 while (Index < CurrentMaxMode) {
1761 if (*NewlyAddedMap == -1) {
1762 //
1763 // This mode is not supported any more. Remove it. Special care
1764 // must be taken as this remove will also affect current mode;
1765 //
1766 if (Index == *CurrentMode) {
1767 Mode = -1;
1768 } else if (Index < *CurrentMode) {
1769 Mode--;
1770 }
1771 (*MaxMode)--;
1772 } else {
1773 if (CurrentMapEntry != NextMapEntry) {
1774 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));
1775 }
1776
1777 NextMapEntry += MapStepSize;
1778 }
1779
1780 CurrentMapEntry += MapStepSize;
1781 NewlyAddedMap += NewMapStepSize;
1782 Index++;
1783 }
1784
1785 *CurrentMode = Mode;
1786
1787 return ;
1788 }
1789
1790 STATIC
1791 VOID
1792 ConSplitterSyncOutputMode (
1793 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1794 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
1795 )
1796 /*++
1797
1798 Routine Description:
1799
1800 Arguments:
1801 Private - Private data structure.
1802 TextOut - Text Out Protocol.
1803 Returns:
1804
1805 None
1806
1807 --*/
1808 {
1809 INT32 CurrentMaxMode;
1810 INT32 Mode;
1811 INT32 Index;
1812 INT32 *TextOutModeMap;
1813 INT32 *MapTable;
1814 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;
1815 UINTN Rows;
1816 UINTN Columns;
1817 UINTN StepSize;
1818
1819 //
1820 // Must make sure that current mode won't change even if mode number changes
1821 //
1822 CurrentMaxMode = Private->TextOutMode.MaxMode;
1823 TextOutModeMap = Private->TextOutModeMap;
1824 StepSize = Private->TextOutListCount;
1825 TextOutQueryData = Private->TextOutQueryData;
1826
1827 //
1828 // Query all the mode that the newly added TextOut supports
1829 //
1830 Mode = 0;
1831 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;
1832 while (Mode < TextOut->Mode->MaxMode) {
1833 TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);
1834
1835 //
1836 // Search the QueryData database to see if they intersects
1837 //
1838 Index = 0;
1839 while (Index < CurrentMaxMode) {
1840 if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {
1841 MapTable[Index * StepSize] = Mode;
1842 break;
1843 }
1844
1845 Index++;
1846 }
1847
1848 Mode++;
1849 }
1850 //
1851 // Now search the TextOutModeMap table to find the intersection of supported
1852 // mode between ConSplitter and the newly added device.
1853 //
1854 ConSplitterGetIntersection (
1855 TextOutModeMap,
1856 MapTable,
1857 StepSize,
1858 StepSize,
1859 &Private->TextOutMode.MaxMode,
1860 &Private->TextOutMode.Mode
1861 );
1862
1863 return ;
1864 }
1865
1866 STATIC
1867 EFI_STATUS
1868 ConSplitterGetIntersectionBetweenConOutAndStrErr (
1869 VOID
1870 )
1871 /*++
1872
1873 Routine Description:
1874
1875 Arguments:
1876
1877 Returns:
1878
1879 None
1880 EFI_OUT_OF_RESOURCES
1881
1882 --*/
1883 {
1884 UINTN ConOutNumOfConsoles;
1885 UINTN StdErrNumOfConsoles;
1886 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;
1887 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;
1888 UINTN Indexi;
1889 UINTN Indexj;
1890 UINTN Rows;
1891 UINTN Columns;
1892 INT32 ConOutMaxMode;
1893 INT32 StdErrMaxMode;
1894 INT32 Mode;
1895 INT32 Index;
1896 INT32 *ConOutModeMap;
1897 INT32 *StdErrModeMap;
1898 INT32 *ConOutMapTable;
1899 INT32 *StdErrMapTable;
1900 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;
1901 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;
1902 BOOLEAN FoundTheSameTextOut;
1903 UINTN ConOutMapTableSize;
1904 UINTN StdErrMapTableSize;
1905
1906 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;
1907 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;
1908 ConOutTextOutList = mConOut.TextOutList;
1909 StdErrTextOutList = mStdErr.TextOutList;
1910
1911 Indexi = 0;
1912 FoundTheSameTextOut = FALSE;
1913 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {
1914 Indexj = 0;
1915 while (Indexj < StdErrNumOfConsoles) {
1916 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {
1917 FoundTheSameTextOut = TRUE;
1918 break;
1919 }
1920
1921 Indexj++;
1922 StdErrTextOutList++;
1923 }
1924
1925 Indexi++;
1926 ConOutTextOutList++;
1927 }
1928
1929 if (!FoundTheSameTextOut) {
1930 return EFI_SUCCESS;
1931 }
1932 //
1933 // Must make sure that current mode won't change even if mode number changes
1934 //
1935 ConOutMaxMode = mConOut.TextOutMode.MaxMode;
1936 ConOutModeMap = mConOut.TextOutModeMap;
1937 ConOutQueryData = mConOut.TextOutQueryData;
1938
1939 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;
1940 StdErrModeMap = mStdErr.TextOutModeMap;
1941 StdErrQueryData = mStdErr.TextOutQueryData;
1942
1943 //
1944 // Allocate the map table and set the map table's index to -1.
1945 //
1946 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);
1947 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);
1948 if (ConOutMapTable == NULL) {
1949 return EFI_OUT_OF_RESOURCES;
1950 }
1951
1952 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);
1953
1954 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);
1955 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);
1956 if (StdErrMapTable == NULL) {
1957 return EFI_OUT_OF_RESOURCES;
1958 }
1959
1960 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);
1961
1962 //
1963 // Find the intersection of the two set of modes. If they actually intersect, the
1964 // correponding entry in the map table is set to 1.
1965 //
1966 Mode = 0;
1967 while (Mode < ConOutMaxMode) {
1968 //
1969 // Search the other's QueryData database to see if they intersect
1970 //
1971 Index = 0;
1972 Rows = ConOutQueryData[Mode].Rows;
1973 Columns = ConOutQueryData[Mode].Columns;
1974 while (Index < StdErrMaxMode) {
1975 if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {
1976 ConOutMapTable[Mode] = 1;
1977 StdErrMapTable[Index] = 1;
1978 break;
1979 }
1980
1981 Index++;
1982 }
1983
1984 Mode++;
1985 }
1986 //
1987 // Now search the TextOutModeMap table to find the intersection of supported
1988 // mode between ConSplitter and the newly added device.
1989 //
1990 ConSplitterGetIntersection (
1991 ConOutModeMap,
1992 ConOutMapTable,
1993 mConOut.TextOutListCount,
1994 1,
1995 &(mConOut.TextOutMode.MaxMode),
1996 &(mConOut.TextOutMode.Mode)
1997 );
1998 if (mConOut.TextOutMode.Mode < 0) {
1999 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);
2000 }
2001
2002 ConSplitterGetIntersection (
2003 StdErrModeMap,
2004 StdErrMapTable,
2005 mStdErr.TextOutListCount,
2006 1,
2007 &(mStdErr.TextOutMode.MaxMode),
2008 &(mStdErr.TextOutMode.Mode)
2009 );
2010 if (mStdErr.TextOutMode.Mode < 0) {
2011 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);
2012 }
2013
2014 FreePool (ConOutMapTable);
2015 FreePool (StdErrMapTable);
2016
2017 return EFI_SUCCESS;
2018 }
2019
2020 STATIC
2021 EFI_STATUS
2022 ConSplitterAddGraphicsOutputMode (
2023 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2024 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2025 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2026 )
2027 /*++
2028
2029 Routine Description:
2030
2031 Arguments:
2032
2033 Returns:
2034
2035 None
2036
2037 --*/
2038 {
2039 EFI_STATUS Status;
2040 UINTN Index;
2041 TEXT_OUT_GOP_MODE *Mode;
2042 UINTN SizeOfInfo;
2043 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
2044 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;
2045 TEXT_OUT_GOP_MODE *ModeBuffer;
2046 TEXT_OUT_GOP_MODE *MatchedMode;
2047 UINTN NumberIndex;
2048 BOOLEAN Match;
2049
2050 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {
2051 return EFI_UNSUPPORTED;
2052 }
2053
2054 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;
2055
2056 if (GraphicsOutput != NULL) {
2057 if (Private->CurrentNumberOfGraphicsOutput == 0) {
2058 //
2059 // This is the first Graphics Output device added
2060 //
2061 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;
2062 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;
2063 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);
2064 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;
2065 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;
2066 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;
2067
2068 //
2069 // Allocate resource for the private mode buffer
2070 //
2071 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);
2072 if (ModeBuffer == NULL) {
2073 return EFI_OUT_OF_RESOURCES;
2074 }
2075 FreePool (Private->GraphicsOutputModeBuffer);
2076 Private->GraphicsOutputModeBuffer = ModeBuffer;
2077
2078 //
2079 // Store all supported display modes to the private mode buffer
2080 //
2081 Mode = ModeBuffer;
2082 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {
2083 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);
2084 if (EFI_ERROR (Status)) {
2085 return Status;
2086 }
2087 Mode->HorizontalResolution = Info->HorizontalResolution;
2088 Mode->VerticalResolution = Info->VerticalResolution;
2089 Mode++;
2090 FreePool (Info);
2091 }
2092 } else {
2093 //
2094 // Check intersection of display mode
2095 //
2096 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);
2097 if (ModeBuffer == NULL) {
2098 return EFI_OUT_OF_RESOURCES;
2099 }
2100
2101 MatchedMode = ModeBuffer;
2102 Mode = &Private->GraphicsOutputModeBuffer[0];
2103 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2104 Match = FALSE;
2105
2106 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {
2107 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
2108 if (EFI_ERROR (Status)) {
2109 return Status;
2110 }
2111 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&
2112 (Info->VerticalResolution == Mode->VerticalResolution)){
2113 Match = TRUE;
2114 FreePool (Info);
2115 break;
2116 }
2117 FreePool (Info);
2118 }
2119
2120 if (Match) {
2121 CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));
2122 MatchedMode++;
2123 }
2124
2125 Mode++;
2126 }
2127
2128 //
2129 // Drop the old mode buffer, assign it to a new one
2130 //
2131 FreePool (Private->GraphicsOutputModeBuffer);
2132 Private->GraphicsOutputModeBuffer = ModeBuffer;
2133
2134 //
2135 // Physical frame buffer is no longer available when there are more than one physical GOP devices
2136 //
2137 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));
2138 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
2139 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));
2140 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2141 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;
2142 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2143 }
2144
2145 //
2146 // Select a prefered Display mode 800x600
2147 //
2148 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {
2149 Mode = &Private->GraphicsOutputModeBuffer[Index];
2150 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {
2151 break;
2152 }
2153 }
2154 //
2155 // Prefered mode is not found, set to mode 0
2156 //
2157 if (Index >= CurrentGraphicsOutputMode->MaxMode) {
2158 Index = 0;
2159 }
2160
2161 //
2162 // Current mode number may need update now, so set it to an invalide mode number
2163 //
2164 CurrentGraphicsOutputMode->Mode = 0xffff;
2165 } else {
2166 //
2167 // For UGA device, it's inconvenient to retrieve all the supported display modes.
2168 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec
2169 //
2170 CurrentGraphicsOutputMode->MaxMode = 1;
2171 CurrentGraphicsOutputMode->Info->Version = 0;
2172 CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;
2173 CurrentGraphicsOutputMode->Info->VerticalResolution = 600;
2174 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;
2175 CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;
2176 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
2177 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;
2178 CurrentGraphicsOutputMode->FrameBufferSize = 0;
2179
2180 //
2181 // Update the private mode buffer
2182 //
2183 ModeBuffer = &Private->GraphicsOutputModeBuffer[0];
2184 ModeBuffer->HorizontalResolution = 800;
2185 ModeBuffer->VerticalResolution = 600;
2186
2187 //
2188 // Current mode is unknow now, set it to an invalid mode number 0xffff
2189 //
2190 CurrentGraphicsOutputMode->Mode = 0xffff;
2191 Index = 0;
2192 }
2193
2194 //
2195 // Force GraphicsOutput mode to be set,
2196 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode
2197 //
2198 Private->HardwareNeedsStarting = TRUE;
2199 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);
2200
2201 Private->CurrentNumberOfGraphicsOutput++;
2202
2203 return Status;
2204 }
2205
2206 EFI_STATUS
2207 ConSplitterTextOutAddDevice (
2208 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2209 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
2210 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
2211 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
2212 )
2213 /*++
2214
2215 Routine Description:
2216
2217 Arguments:
2218
2219 Returns:
2220
2221 None
2222
2223 --*/
2224 {
2225 EFI_STATUS Status;
2226 UINTN CurrentNumOfConsoles;
2227 INT32 CurrentMode;
2228 INT32 MaxMode;
2229 TEXT_OUT_AND_GOP_DATA *TextAndGop;
2230
2231 Status = EFI_SUCCESS;
2232 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
2233
2234 //
2235 // If the Text Out List is full, enlarge it by calling growbuffer().
2236 //
2237 while (CurrentNumOfConsoles >= Private->TextOutListCount) {
2238 Status = ConSplitterGrowBuffer (
2239 sizeof (TEXT_OUT_AND_GOP_DATA),
2240 &Private->TextOutListCount,
2241 (VOID **) &Private->TextOutList
2242 );
2243 if (EFI_ERROR (Status)) {
2244 return EFI_OUT_OF_RESOURCES;
2245 }
2246 //
2247 // Also need to reallocate the TextOutModeMap table
2248 //
2249 Status = ConSplitterGrowMapTable (Private);
2250 if (EFI_ERROR (Status)) {
2251 return EFI_OUT_OF_RESOURCES;
2252 }
2253 }
2254
2255 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];
2256
2257 TextAndGop->TextOut = TextOut;
2258 TextAndGop->GraphicsOutput = GraphicsOutput;
2259 TextAndGop->UgaDraw = UgaDraw;
2260
2261 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {
2262 //
2263 // If No UGA device then use the ConOut device
2264 //
2265 TextAndGop->TextOutEnabled = TRUE;
2266 } else {
2267 //
2268 // If UGA device use ConOut device only used if UGA screen is in Text mode
2269 //
2270 TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);
2271 }
2272
2273 if (CurrentNumOfConsoles == 0) {
2274 //
2275 // Add the first device's output mode to console splitter's mode list
2276 //
2277 Status = ConSplitterAddOutputMode (Private, TextOut);
2278 } else {
2279 ConSplitterSyncOutputMode (Private, TextOut);
2280 }
2281
2282 Private->CurrentNumberOfConsoles++;
2283
2284 //
2285 // Scan both TextOutList, for the intersection TextOut device
2286 // maybe both ConOut and StdErr incorporate the same Text Out
2287 // device in them, thus the output of both should be synced.
2288 //
2289 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2290
2291 CurrentMode = Private->TextOutMode.Mode;
2292 MaxMode = Private->TextOutMode.MaxMode;
2293 ASSERT (MaxMode >= 1);
2294
2295 if (FeaturePcdGet (PcdConOutGopSupport)) {
2296 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {
2297 ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
2298 }
2299 }
2300
2301 if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {
2302 //
2303 // We just added a new UGA device in graphics mode
2304 //
2305 if (FeaturePcdGet (PcdConOutGopSupport)) {
2306 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
2307 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {
2308 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
2309 }
2310 } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {
2311 //
2312 // The new console supports the same mode of the current console so sync up
2313 //
2314 DevNullSyncGopStdOut (Private);
2315 } else {
2316 //
2317 // If ConOut, then set the mode to Mode #0 which us 80 x 25
2318 //
2319 Private->TextOut.SetMode (&Private->TextOut, 0);
2320 }
2321
2322 return Status;
2323 }
2324
2325 EFI_STATUS
2326 ConSplitterTextOutDeleteDevice (
2327 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
2328 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut
2329 )
2330 /*++
2331
2332 Routine Description:
2333
2334 Arguments:
2335
2336 Returns:
2337
2338 None
2339
2340 --*/
2341 {
2342 INT32 Index;
2343 UINTN CurrentNumOfConsoles;
2344 TEXT_OUT_AND_GOP_DATA *TextOutList;
2345 EFI_STATUS Status;
2346
2347 //
2348 // Remove the specified text-out device data structure from the Text out List,
2349 // and rearrange the remaining data structures in the Text out List.
2350 //
2351 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;
2352 Index = (INT32) CurrentNumOfConsoles - 1;
2353 TextOutList = Private->TextOutList;
2354 while (Index >= 0) {
2355 if (TextOutList->TextOut == TextOut) {
2356 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);
2357 CurrentNumOfConsoles--;
2358 break;
2359 }
2360
2361 Index--;
2362 TextOutList++;
2363 }
2364 //
2365 // The specified TextOut is not managed by the ConSplitter driver
2366 //
2367 if (Index < 0) {
2368 return EFI_NOT_FOUND;
2369 }
2370
2371 if (CurrentNumOfConsoles == 0) {
2372 //
2373 // If the number of consoles is zero clear the Dev NULL device
2374 //
2375 Private->CurrentNumberOfConsoles = 0;
2376 Private->TextOutMode.MaxMode = 1;
2377 Private->TextOutQueryData[0].Columns = 80;
2378 Private->TextOutQueryData[0].Rows = 25;
2379 DevNullTextOutSetMode (Private, 0);
2380
2381 return EFI_SUCCESS;
2382 }
2383 //
2384 // Max Mode is realy an intersection of the QueryMode command to all
2385 // devices. So we must copy the QueryMode of the first device to
2386 // QueryData.
2387 //
2388 ZeroMem (
2389 Private->TextOutQueryData,
2390 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)
2391 );
2392
2393 FreePool (Private->TextOutModeMap);
2394 Private->TextOutModeMap = NULL;
2395 TextOutList = Private->TextOutList;
2396
2397 //
2398 // Add the first TextOut to the QueryData array and ModeMap table
2399 //
2400 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);
2401
2402 //
2403 // Now add one by one
2404 //
2405 Index = 1;
2406 Private->CurrentNumberOfConsoles = 1;
2407 TextOutList++;
2408 while ((UINTN) Index < CurrentNumOfConsoles) {
2409 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);
2410 Index++;
2411 Private->CurrentNumberOfConsoles++;
2412 TextOutList++;
2413 }
2414
2415 ConSplitterGetIntersectionBetweenConOutAndStrErr ();
2416
2417 return Status;
2418 }
2419 //
2420 // ConSplitter TextIn member functions
2421 //
2422 EFI_STATUS
2423 EFIAPI
2424 ConSplitterTextInReset (
2425 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
2426 IN BOOLEAN ExtendedVerification
2427 )
2428 /*++
2429
2430 Routine Description:
2431 Reset the input device and optionaly run diagnostics
2432
2433 Arguments:
2434 This - Protocol instance pointer.
2435 ExtendedVerification - Driver may perform diagnostics on reset.
2436
2437 Returns:
2438 EFI_SUCCESS - The device was reset.
2439 EFI_DEVICE_ERROR - The device is not functioning properly and could
2440 not be reset.
2441
2442 --*/
2443 {
2444 EFI_STATUS Status;
2445 EFI_STATUS ReturnStatus;
2446 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2447 UINTN Index;
2448
2449 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
2450
2451 Private->KeyEventSignalState = FALSE;
2452
2453 //
2454 // return the worst status met
2455 //
2456 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
2457 Status = Private->TextInList[Index]->Reset (
2458 Private->TextInList[Index],
2459 ExtendedVerification
2460 );
2461 if (EFI_ERROR (Status)) {
2462 ReturnStatus = Status;
2463 }
2464 }
2465
2466 return ReturnStatus;
2467 }
2468
2469 EFI_STATUS
2470 EFIAPI
2471 ConSplitterTextInPrivateReadKeyStroke (
2472 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2473 OUT EFI_INPUT_KEY *Key
2474 )
2475 /*++
2476
2477 Routine Description:
2478 Reads the next keystroke from the input device. The WaitForKey Event can
2479 be used to test for existance of a keystroke via WaitForEvent () call.
2480
2481 Arguments:
2482 This - Protocol instance pointer.
2483 Key - Driver may perform diagnostics on reset.
2484
2485 Returns:
2486 EFI_SUCCESS - The keystroke information was returned.
2487 EFI_NOT_READY - There was no keystroke data availiable.
2488 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2489 hardware errors.
2490
2491 --*/
2492 {
2493 EFI_STATUS Status;
2494 UINTN Index;
2495 EFI_INPUT_KEY CurrentKey;
2496
2497 Key->UnicodeChar = 0;
2498 Key->ScanCode = SCAN_NULL;
2499
2500 //
2501 // if no physical console input device exists, return EFI_NOT_READY;
2502 // if any physical console input device has key input,
2503 // return the key and EFI_SUCCESS.
2504 //
2505 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
2506 Status = Private->TextInList[Index]->ReadKeyStroke (
2507 Private->TextInList[Index],
2508 &CurrentKey
2509 );
2510 if (!EFI_ERROR (Status)) {
2511 *Key = CurrentKey;
2512 return Status;
2513 }
2514 }
2515
2516 return EFI_NOT_READY;
2517 }
2518
2519 BOOLEAN
2520 ConSpliterConssoleControlStdInLocked (
2521 VOID
2522 )
2523 /*++
2524
2525 Routine Description:
2526 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is
2527 the only device locked.
2528
2529 Arguments:
2530 NONE
2531
2532 Returns:
2533 TRUE - StdIn locked
2534 FALSE - StdIn working normally
2535
2536 --*/
2537 {
2538 return mConIn.PasswordEnabled;
2539 }
2540
2541 VOID
2542 EFIAPI
2543 ConSpliterConsoleControlLockStdInEvent (
2544 IN EFI_EVENT Event,
2545 IN VOID *Context
2546 )
2547 /*++
2548
2549 Routine Description:
2550 This timer event will fire when StdIn is locked. It will check the key
2551 sequence on StdIn to see if it matches the password. Any error in the
2552 password will cause the check to reset. As long a mConIn.PasswordEnabled is
2553 TRUE the StdIn splitter will not report any input.
2554
2555 Arguments:
2556 (Standard EFI_EVENT_NOTIFY)
2557
2558 Returns:
2559 None
2560
2561 --*/
2562 {
2563 EFI_STATUS Status;
2564 EFI_INPUT_KEY Key;
2565 CHAR16 BackSpaceString[2];
2566 CHAR16 SpaceString[2];
2567
2568 do {
2569 Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);
2570 if (!EFI_ERROR (Status)) {
2571 //
2572 // if it's an ENTER, match password
2573 //
2574 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {
2575 mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;
2576 if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {
2577 //
2578 // Password not match
2579 //
2580 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");
2581 mConIn.PwdIndex = 0;
2582 } else {
2583 //
2584 // Key matches password sequence
2585 //
2586 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);
2587 mConIn.PasswordEnabled = FALSE;
2588 Status = EFI_NOT_READY;
2589 }
2590 } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {
2591 //
2592 // BackSpace met
2593 //
2594 if (mConIn.PwdIndex > 0) {
2595 BackSpaceString[0] = CHAR_BACKSPACE;
2596 BackSpaceString[1] = 0;
2597
2598 SpaceString[0] = ' ';
2599 SpaceString[1] = 0;
2600
2601 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);
2602 ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);
2603 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);
2604
2605 mConIn.PwdIndex--;
2606 }
2607 } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {
2608 //
2609 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input
2610 //
2611 if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {
2612 if (mConIn.PwdIndex == 0) {
2613 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");
2614 }
2615
2616 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");
2617 mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;
2618 mConIn.PwdIndex++;
2619 }
2620 }
2621 }
2622 } while (!EFI_ERROR (Status));
2623 }
2624
2625 EFI_STATUS
2626 EFIAPI
2627 ConSpliterConsoleControlLockStdIn (
2628 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
2629 IN CHAR16 *Password
2630 )
2631 /*++
2632
2633 Routine Description:
2634 If Password is NULL unlock the password state variable and set the event
2635 timer. If the Password is too big return an error. If the Password is valid
2636 Copy the Password and enable state variable and then arm the periodic timer
2637
2638 Arguments:
2639
2640 Returns:
2641 EFI_SUCCESS - Lock the StdIn device
2642 EFI_INVALID_PARAMETER - Password is NULL
2643 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails
2644
2645 --*/
2646 {
2647 if (Password == NULL) {
2648 return EFI_INVALID_PARAMETER;
2649 }
2650
2651 if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {
2652 //
2653 // Currently have a max password size
2654 //
2655 return EFI_OUT_OF_RESOURCES;
2656 }
2657 //
2658 // Save the password, initialize state variables and arm event timer
2659 //
2660 StrCpy (mConIn.Password, Password);
2661 mConIn.PasswordEnabled = TRUE;
2662 mConIn.PwdIndex = 0;
2663 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));
2664
2665 return EFI_SUCCESS;
2666 }
2667
2668 EFI_STATUS
2669 EFIAPI
2670 ConSplitterTextInReadKeyStroke (
2671 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
2672 OUT EFI_INPUT_KEY *Key
2673 )
2674 /*++
2675
2676 Routine Description:
2677 Reads the next keystroke from the input device. The WaitForKey Event can
2678 be used to test for existance of a keystroke via WaitForEvent () call.
2679 If the ConIn is password locked make it look like no keystroke is availible
2680
2681 Arguments:
2682 This - Protocol instance pointer.
2683 Key - Driver may perform diagnostics on reset.
2684
2685 Returns:
2686 EFI_SUCCESS - The keystroke information was returned.
2687 EFI_NOT_READY - There was no keystroke data availiable.
2688 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2689 hardware errors.
2690
2691 --*/
2692 {
2693 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2694
2695 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
2696 if (Private->PasswordEnabled) {
2697 //
2698 // If StdIn Locked return not ready
2699 //
2700 return EFI_NOT_READY;
2701 }
2702
2703 Private->KeyEventSignalState = FALSE;
2704
2705 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);
2706 }
2707
2708 VOID
2709 EFIAPI
2710 ConSplitterTextInWaitForKey (
2711 IN EFI_EVENT Event,
2712 IN VOID *Context
2713 )
2714 /*++
2715
2716 Routine Description:
2717 This event agregates all the events of the ConIn devices in the spliter.
2718 If the ConIn is password locked then return.
2719 If any events of physical ConIn devices are signaled, signal the ConIn
2720 spliter event. This will cause the calling code to call
2721 ConSplitterTextInReadKeyStroke ().
2722
2723 Arguments:
2724 Event - The Event assoicated with callback.
2725 Context - Context registered when Event was created.
2726
2727 Returns:
2728 None
2729
2730 --*/
2731 {
2732 EFI_STATUS Status;
2733 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2734 UINTN Index;
2735
2736 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
2737 if (Private->PasswordEnabled) {
2738 //
2739 // If StdIn Locked return not ready
2740 //
2741 return ;
2742 }
2743
2744 //
2745 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2746 //
2747 if (Private->KeyEventSignalState) {
2748 gBS->SignalEvent (Event);
2749 return ;
2750 }
2751 //
2752 // if any physical console input device has key input, signal the event.
2753 //
2754 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
2755 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);
2756 if (!EFI_ERROR (Status)) {
2757 gBS->SignalEvent (Event);
2758 Private->KeyEventSignalState = TRUE;
2759 }
2760 }
2761 }
2762
2763 EFI_STATUS
2764 EFIAPI
2765 ConSplitterSimplePointerReset (
2766 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
2767 IN BOOLEAN ExtendedVerification
2768 )
2769 /*++
2770
2771 Routine Description:
2772 Reset the input device and optionaly run diagnostics
2773
2774 Arguments:
2775 This - Protocol instance pointer.
2776 ExtendedVerification - Driver may perform diagnostics on reset.
2777
2778 Returns:
2779 EFI_SUCCESS - The device was reset.
2780 EFI_DEVICE_ERROR - The device is not functioning properly and could
2781 not be reset.
2782
2783 --*/
2784 {
2785 EFI_STATUS Status;
2786 EFI_STATUS ReturnStatus;
2787 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2788 UINTN Index;
2789
2790 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
2791
2792 Private->InputEventSignalState = FALSE;
2793
2794 if (Private->CurrentNumberOfPointers == 0) {
2795 return EFI_SUCCESS;
2796 }
2797 //
2798 // return the worst status met
2799 //
2800 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {
2801 Status = Private->PointerList[Index]->Reset (
2802 Private->PointerList[Index],
2803 ExtendedVerification
2804 );
2805 if (EFI_ERROR (Status)) {
2806 ReturnStatus = Status;
2807 }
2808 }
2809
2810 return ReturnStatus;
2811 }
2812
2813 STATIC
2814 EFI_STATUS
2815 EFIAPI
2816 ConSplitterSimplePointerPrivateGetState (
2817 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,
2818 IN OUT EFI_SIMPLE_POINTER_STATE *State
2819 )
2820 /*++
2821
2822 Routine Description:
2823 Reads the next keystroke from the input device. The WaitForKey Event can
2824 be used to test for existance of a keystroke via WaitForEvent () call.
2825
2826 Arguments:
2827 This - Protocol instance pointer.
2828 State -
2829
2830 Returns:
2831 EFI_SUCCESS - The keystroke information was returned.
2832 EFI_NOT_READY - There was no keystroke data availiable.
2833 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2834 hardware errors.
2835
2836 --*/
2837 {
2838 EFI_STATUS Status;
2839 EFI_STATUS ReturnStatus;
2840 UINTN Index;
2841 EFI_SIMPLE_POINTER_STATE CurrentState;
2842
2843 State->RelativeMovementX = 0;
2844 State->RelativeMovementY = 0;
2845 State->RelativeMovementZ = 0;
2846 State->LeftButton = FALSE;
2847 State->RightButton = FALSE;
2848
2849 //
2850 // if no physical console input device exists, return EFI_NOT_READY;
2851 // if any physical console input device has key input,
2852 // return the key and EFI_SUCCESS.
2853 //
2854 ReturnStatus = EFI_NOT_READY;
2855 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
2856
2857 Status = Private->PointerList[Index]->GetState (
2858 Private->PointerList[Index],
2859 &CurrentState
2860 );
2861 if (!EFI_ERROR (Status)) {
2862 if (ReturnStatus == EFI_NOT_READY) {
2863 ReturnStatus = EFI_SUCCESS;
2864 }
2865
2866 if (CurrentState.LeftButton) {
2867 State->LeftButton = TRUE;
2868 }
2869
2870 if (CurrentState.RightButton) {
2871 State->RightButton = TRUE;
2872 }
2873
2874 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {
2875 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;
2876 }
2877
2878 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {
2879 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;
2880 }
2881
2882 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {
2883 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;
2884 }
2885 } else if (Status == EFI_DEVICE_ERROR) {
2886 ReturnStatus = EFI_DEVICE_ERROR;
2887 }
2888 }
2889
2890 return ReturnStatus;
2891 }
2892
2893 EFI_STATUS
2894 EFIAPI
2895 ConSplitterSimplePointerGetState (
2896 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
2897 IN OUT EFI_SIMPLE_POINTER_STATE *State
2898 )
2899 /*++
2900
2901 Routine Description:
2902 Reads the next keystroke from the input device. The WaitForKey Event can
2903 be used to test for existance of a keystroke via WaitForEvent () call.
2904 If the ConIn is password locked make it look like no keystroke is availible
2905
2906 Arguments:
2907 This - Protocol instance pointer.
2908 State -
2909
2910 Returns:
2911 EFI_SUCCESS - The keystroke information was returned.
2912 EFI_NOT_READY - There was no keystroke data availiable.
2913 EFI_DEVICE_ERROR - The keydtroke information was not returned due to
2914 hardware errors.
2915
2916 --*/
2917 {
2918 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2919
2920 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);
2921 if (Private->PasswordEnabled) {
2922 //
2923 // If StdIn Locked return not ready
2924 //
2925 return EFI_NOT_READY;
2926 }
2927
2928 Private->InputEventSignalState = FALSE;
2929
2930 return ConSplitterSimplePointerPrivateGetState (Private, State);
2931 }
2932
2933 VOID
2934 EFIAPI
2935 ConSplitterSimplePointerWaitForInput (
2936 IN EFI_EVENT Event,
2937 IN VOID *Context
2938 )
2939 /*++
2940
2941 Routine Description:
2942 This event agregates all the events of the ConIn devices in the spliter.
2943 If the ConIn is password locked then return.
2944 If any events of physical ConIn devices are signaled, signal the ConIn
2945 spliter event. This will cause the calling code to call
2946 ConSplitterTextInReadKeyStroke ().
2947
2948 Arguments:
2949 Event - The Event assoicated with callback.
2950 Context - Context registered when Event was created.
2951
2952 Returns:
2953 None
2954
2955 --*/
2956 {
2957 EFI_STATUS Status;
2958 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;
2959 UINTN Index;
2960
2961 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;
2962 if (Private->PasswordEnabled) {
2963 //
2964 // If StdIn Locked return not ready
2965 //
2966 return ;
2967 }
2968
2969 //
2970 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()
2971 //
2972 if (Private->InputEventSignalState) {
2973 gBS->SignalEvent (Event);
2974 return ;
2975 }
2976 //
2977 // if any physical console input device has key input, signal the event.
2978 //
2979 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
2980 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);
2981 if (!EFI_ERROR (Status)) {
2982 gBS->SignalEvent (Event);
2983 Private->InputEventSignalState = TRUE;
2984 }
2985 }
2986 }
2987
2988 EFI_STATUS
2989 EFIAPI
2990 ConSplitterTextOutReset (
2991 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
2992 IN BOOLEAN ExtendedVerification
2993 )
2994 /*++
2995
2996 Routine Description:
2997 Reset the text output device hardware and optionaly run diagnostics
2998
2999 Arguments:
3000 This - Protocol instance pointer.
3001 ExtendedVerification - Driver may perform more exhaustive verfication
3002 operation of the device during reset.
3003
3004 Returns:
3005 EFI_SUCCESS - The text output device was reset.
3006 EFI_DEVICE_ERROR - The text output device is not functioning correctly and
3007 could not be reset.
3008
3009 --*/
3010 {
3011 EFI_STATUS Status;
3012 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
3013 UINTN Index;
3014 EFI_STATUS ReturnStatus;
3015
3016 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3017
3018 //
3019 // return the worst status met
3020 //
3021 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3022
3023 if (Private->TextOutList[Index].TextOutEnabled) {
3024
3025 Status = Private->TextOutList[Index].TextOut->Reset (
3026 Private->TextOutList[Index].TextOut,
3027 ExtendedVerification
3028 );
3029 if (EFI_ERROR (Status)) {
3030 ReturnStatus = Status;
3031 }
3032 }
3033 }
3034
3035 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
3036
3037 Status = DevNullTextOutSetMode (Private, 0);
3038 if (EFI_ERROR (Status)) {
3039 ReturnStatus = Status;
3040 }
3041
3042 return ReturnStatus;
3043 }
3044
3045 EFI_STATUS
3046 EFIAPI
3047 ConSplitterTextOutOutputString (
3048 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
3049 IN CHAR16 *WString
3050 )
3051 /*++
3052
3053 Routine Description:
3054 Write a Unicode string to the output device.
3055
3056 Arguments:
3057 This - Protocol instance pointer.
3058 String - The NULL-terminated Unicode string to be displayed on the output
3059 device(s). All output devices must also support the Unicode
3060 drawing defined in this file.
3061
3062 Returns:
3063 EFI_SUCCESS - The string was output to the device.
3064 EFI_DEVICE_ERROR - The device reported an error while attempting to output
3065 the text.
3066 EFI_UNSUPPORTED - The output device's mode is not currently in a
3067 defined text mode.
3068 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
3069 characters in the Unicode string could not be
3070 rendered and were skipped.
3071
3072 --*/
3073 {
3074 EFI_STATUS Status;
3075 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
3076 UINTN Index;
3077 UINTN BackSpaceCount;
3078 EFI_STATUS ReturnStatus;
3079 CHAR16 *TargetString;
3080
3081 This->SetAttribute (This, This->Mode->Attribute);
3082
3083 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3084
3085 BackSpaceCount = 0;
3086 for (TargetString = WString; *TargetString; TargetString++) {
3087 if (*TargetString == CHAR_BACKSPACE) {
3088 BackSpaceCount++;
3089 }
3090
3091 }
3092
3093 if (BackSpaceCount == 0) {
3094 TargetString = WString;
3095 } else {
3096 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));
3097 StrCpy (TargetString, WString);
3098 }
3099 //
3100 // return the worst status met
3101 //
3102 Status = DevNullTextOutOutputString (Private, TargetString);
3103 if (EFI_ERROR (Status)) {
3104 ReturnStatus = Status;
3105 }
3106
3107 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3108
3109 if (Private->TextOutList[Index].TextOutEnabled) {
3110 Status = Private->TextOutList[Index].TextOut->OutputString (
3111 Private->TextOutList[Index].TextOut,
3112 TargetString
3113 );
3114 if (EFI_ERROR (Status)) {
3115 ReturnStatus = Status;
3116 }
3117 }
3118 }
3119
3120 if (BackSpaceCount) {
3121 FreePool (TargetString);
3122 }
3123
3124 return ReturnStatus;
3125 }
3126
3127 EFI_STATUS
3128 EFIAPI
3129 ConSplitterTextOutTestString (
3130 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
3131 IN CHAR16 *WString
3132 )
3133 /*++
3134
3135 Routine Description:
3136 Verifies that all characters in a Unicode string can be output to the
3137 target device.
3138
3139 Arguments:
3140 This - Protocol instance pointer.
3141 String - The NULL-terminated Unicode string to be examined for the output
3142 device(s).
3143
3144 Returns:
3145 EFI_SUCCESS - The device(s) are capable of rendering the output string.
3146 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be
3147 rendered by one or more of the output devices mapped
3148 by the EFI handle.
3149
3150 --*/
3151 {
3152 EFI_STATUS Status;
3153 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
3154 UINTN Index;
3155 EFI_STATUS ReturnStatus;
3156
3157 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
3158
3159 //
3160 // return the worst status met
3161 //
3162 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {
3163 if (Private->TextOutList[Index].TextOutEnabled) {
3164 Status = Private->TextOutList[Index].TextOut->TestString (
3165 Private->TextOutList[Index].TextOut,
3166 WString
3167 );
3168 if (EFI_ERROR (Status)) {
3169 ReturnStatus = Status;
3170 }
3171 }
3172 }
3173 //
3174 // There is no DevNullTextOutTestString () since a Unicode buffer would
3175 // always return EFI_SUCCESS.
3176 // ReturnStatus will be EFI_SUCCESS if no consoles are present
3177 //
3178 return ReturnStatus;
3179 }
3180
3181 EFI_STATUS
3182 EFIAPI
3183 ConSplitterTextOutQueryMode (
3184 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
3185 IN UINTN ModeNumber,
3186 OUT UINTN *Columns,
3187 OUT UINTN *Rows