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