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