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