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