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