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