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