]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
sync tracker to remove duplicate display mode in ConOut virtual handle GOP instance.
[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
2246 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;\r
2247 UINTN Rows;\r
2248 UINTN Columns;\r
2249 UINTN StepSize;\r
2250\r
2251 //\r
2252 // Must make sure that current mode won't change even if mode number changes\r
2253 //\r
2254 CurrentMaxMode = Private->TextOutMode.MaxMode;\r
2255 TextOutModeMap = Private->TextOutModeMap;\r
2256 StepSize = Private->TextOutListCount;\r
2257 TextOutQueryData = Private->TextOutQueryData;\r
2258\r
2259 //\r
2260 // Query all the mode that the newly added TextOut supports\r
2261 //\r
2262 Mode = 0;\r
2263 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
2264 while (Mode < TextOut->Mode->MaxMode) {\r
2265 TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
2266\r
2267 //\r
2268 // Search the QueryData database to see if they intersects\r
2269 //\r
2270 Index = 0;\r
2271 while (Index < CurrentMaxMode) {\r
2272 if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
2273 MapTable[Index * StepSize] = Mode;\r
2274 break;\r
2275 }\r
2276\r
2277 Index++;\r
2278 }\r
2279\r
2280 Mode++;\r
2281 }\r
2282 //\r
2283 // Now search the TextOutModeMap table to find the intersection of supported\r
2284 // mode between ConSplitter and the newly added device.\r
2285 //\r
2286 ConSplitterGetIntersection (\r
2287 TextOutModeMap,\r
2288 MapTable,\r
2289 StepSize,\r
2290 StepSize,\r
2291 &Private->TextOutMode.MaxMode,\r
2292 &Private->TextOutMode.Mode\r
2293 );\r
2294\r
2295 return ;\r
2296}\r
2297\r
2298STATIC\r
2299EFI_STATUS\r
2300ConSplitterGetIntersectionBetweenConOutAndStrErr (\r
2301 VOID\r
2302 )\r
2303/*++\r
2304\r
2305Routine Description:\r
2306\r
2307Arguments:\r
2308\r
2309Returns:\r
2310\r
2311 None\r
2312 EFI_OUT_OF_RESOURCES\r
2313\r
2314--*/\r
2315{\r
2316 UINTN ConOutNumOfConsoles;\r
2317 UINTN StdErrNumOfConsoles;\r
2318 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;\r
2319 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;\r
2320 UINTN Indexi;\r
2321 UINTN Indexj;\r
2322 UINTN Rows;\r
2323 UINTN Columns;\r
2324 INT32 ConOutMaxMode;\r
2325 INT32 StdErrMaxMode;\r
2326 INT32 Mode;\r
2327 INT32 Index;\r
2328 INT32 *ConOutModeMap;\r
2329 INT32 *StdErrModeMap;\r
2330 INT32 *ConOutMapTable;\r
2331 INT32 *StdErrMapTable;\r
2332 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;\r
2333 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;\r
2334 BOOLEAN FoundTheSameTextOut;\r
2335 UINTN ConOutMapTableSize;\r
2336 UINTN StdErrMapTableSize;\r
2337\r
2338 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;\r
2339 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;\r
2340 ConOutTextOutList = mConOut.TextOutList;\r
2341 StdErrTextOutList = mStdErr.TextOutList;\r
2342\r
2343 Indexi = 0;\r
2344 FoundTheSameTextOut = FALSE;\r
2345 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {\r
2346 Indexj = 0;\r
2347 while (Indexj < StdErrNumOfConsoles) {\r
2348 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {\r
2349 FoundTheSameTextOut = TRUE;\r
2350 break;\r
2351 }\r
2352\r
2353 Indexj++;\r
2354 StdErrTextOutList++;\r
2355 }\r
2356\r
2357 Indexi++;\r
2358 ConOutTextOutList++;\r
2359 }\r
2360\r
2361 if (!FoundTheSameTextOut) {\r
2362 return EFI_SUCCESS;\r
2363 }\r
2364 //\r
2365 // Must make sure that current mode won't change even if mode number changes\r
2366 //\r
2367 ConOutMaxMode = mConOut.TextOutMode.MaxMode;\r
2368 ConOutModeMap = mConOut.TextOutModeMap;\r
2369 ConOutQueryData = mConOut.TextOutQueryData;\r
2370\r
2371 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;\r
2372 StdErrModeMap = mStdErr.TextOutModeMap;\r
2373 StdErrQueryData = mStdErr.TextOutQueryData;\r
2374\r
2375 //\r
2376 // Allocate the map table and set the map table's index to -1.\r
2377 //\r
2378 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);\r
2379 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);\r
2380 if (ConOutMapTable == NULL) {\r
2381 return EFI_OUT_OF_RESOURCES;\r
2382 }\r
2383\r
2384 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);\r
2385\r
2386 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);\r
2387 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);\r
2388 if (StdErrMapTable == NULL) {\r
2389 return EFI_OUT_OF_RESOURCES;\r
2390 }\r
2391\r
2392 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);\r
2393\r
2394 //\r
2395 // Find the intersection of the two set of modes. If they actually intersect, the\r
2396 // correponding entry in the map table is set to 1.\r
2397 //\r
2398 Mode = 0;\r
2399 while (Mode < ConOutMaxMode) {\r
2400 //\r
2401 // Search the other's QueryData database to see if they intersect\r
2402 //\r
2403 Index = 0;\r
2404 Rows = ConOutQueryData[Mode].Rows;\r
2405 Columns = ConOutQueryData[Mode].Columns;\r
2406 while (Index < StdErrMaxMode) {\r
2407 if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
2408 ConOutMapTable[Mode] = 1;\r
2409 StdErrMapTable[Index] = 1;\r
2410 break;\r
2411 }\r
2412\r
2413 Index++;\r
2414 }\r
2415\r
2416 Mode++;\r
2417 }\r
2418 //\r
2419 // Now search the TextOutModeMap table to find the intersection of supported\r
2420 // mode between ConSplitter and the newly added device.\r
2421 //\r
2422 ConSplitterGetIntersection (\r
2423 ConOutModeMap,\r
2424 ConOutMapTable,\r
2425 mConOut.TextOutListCount,\r
2426 1,\r
2427 &(mConOut.TextOutMode.MaxMode),\r
2428 &(mConOut.TextOutMode.Mode)\r
2429 );\r
2430 if (mConOut.TextOutMode.Mode < 0) {\r
2431 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);\r
2432 }\r
2433\r
2434 ConSplitterGetIntersection (\r
2435 StdErrModeMap,\r
2436 StdErrMapTable,\r
2437 mStdErr.TextOutListCount,\r
2438 1,\r
2439 &(mStdErr.TextOutMode.MaxMode),\r
2440 &(mStdErr.TextOutMode.Mode)\r
2441 );\r
2442 if (mStdErr.TextOutMode.Mode < 0) {\r
2443 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);\r
2444 }\r
2445\r
2446 FreePool (ConOutMapTable);\r
2447 FreePool (StdErrMapTable);\r
2448\r
2449 return EFI_SUCCESS;\r
2450}\r
2451\r
2452STATIC\r
2453EFI_STATUS\r
2454ConSplitterAddGraphicsOutputMode (\r
2455 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2456 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2457 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2458 )\r
2459/*++\r
2460\r
2461Routine Description:\r
2462\r
2463Arguments:\r
2464\r
2465Returns:\r
2466\r
2467 None\r
2468\r
2469--*/\r
2470{\r
2471 EFI_STATUS Status;\r
2472 UINTN Index;\r
aec072ad 2473 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;\r
95276127 2474 UINTN SizeOfInfo;\r
2475 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
2476 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;\r
aec072ad 2477 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;\r
2478 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;\r
95276127 2479 UINTN NumberIndex;\r
2480 BOOLEAN Match;\r
aec072ad 2481 BOOLEAN AlreadyExist;\r
95276127 2482\r
2483 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2484 return EFI_UNSUPPORTED;\r
2485 }\r
2486\r
2487 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
2488\r
aec072ad 2489 Index = 0;\r
2490\r
2491 if (Private->CurrentNumberOfUgaDraw != 0) {\r
2492 //\r
2493 // If any UGA device has already been added, then there is no need to\r
2494 // calculate intersection of display mode of different GOP/UGA device,\r
2495 // since only one display mode will be exported (i.e. user-defined mode)\r
2496 //\r
2497 goto Done;\r
2498 }\r
2499\r
95276127 2500 if (GraphicsOutput != NULL) {\r
2501 if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
2502 //\r
2503 // This is the first Graphics Output device added\r
2504 //\r
2505 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;\r
2506 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;\r
2507 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);\r
2508 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;\r
2509 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;\r
2510 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;\r
2511\r
2512 //\r
2513 // Allocate resource for the private mode buffer\r
2514 //\r
aec072ad 2515 ModeBuffer = AllocatePool (GraphicsOutput->Mode->SizeOfInfo * GraphicsOutput->Mode->MaxMode);\r
95276127 2516 if (ModeBuffer == NULL) {\r
2517 return EFI_OUT_OF_RESOURCES;\r
2518 }\r
2519 FreePool (Private->GraphicsOutputModeBuffer);\r
2520 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2521\r
2522 //\r
2523 // Store all supported display modes to the private mode buffer\r
2524 //\r
2525 Mode = ModeBuffer;\r
2526 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {\r
2527 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);\r
2528 if (EFI_ERROR (Status)) {\r
2529 return Status;\r
2530 }\r
aec072ad 2531 CopyMem (Mode, Info, SizeOfInfo);\r
95276127 2532 Mode++;\r
2533 FreePool (Info);\r
2534 }\r
2535 } else {\r
2536 //\r
2537 // Check intersection of display mode\r
2538 //\r
aec072ad 2539 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);\r
95276127 2540 if (ModeBuffer == NULL) {\r
2541 return EFI_OUT_OF_RESOURCES;\r
2542 }\r
2543\r
2544 MatchedMode = ModeBuffer;\r
2545 Mode = &Private->GraphicsOutputModeBuffer[0];\r
2546 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2547 Match = FALSE;\r
2548\r
2549 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {\r
2550 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
2551 if (EFI_ERROR (Status)) {\r
2552 return Status;\r
2553 }\r
2554 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
aec072ad 2555 (Info->VerticalResolution == Mode->VerticalResolution)) {\r
95276127 2556 Match = TRUE;\r
2557 FreePool (Info);\r
2558 break;\r
2559 }\r
2560 FreePool (Info);\r
2561 }\r
2562\r
2563 if (Match) {\r
aec072ad 2564 AlreadyExist = FALSE;\r
2565\r
2566 for (Info = ModeBuffer; Info < MatchedMode; Info++) {\r
2567 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
2568 (Info->VerticalResolution == Mode->VerticalResolution)) {\r
2569 AlreadyExist = TRUE;\r
2570 break;\r
2571 }\r
2572 }\r
2573\r
2574 if (!AlreadyExist) {\r
2575 CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
2576\r
2577 //\r
2578 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly\r
2579 //\r
2580 MatchedMode->Version = 0;\r
2581 MatchedMode->PixelFormat = PixelBltOnly;\r
2582 ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2583\r
2584 MatchedMode++;\r
2585 }\r
95276127 2586 }\r
2587\r
2588 Mode++;\r
2589 }\r
2590\r
2591 //\r
2592 // Drop the old mode buffer, assign it to a new one\r
2593 //\r
2594 FreePool (Private->GraphicsOutputModeBuffer);\r
2595 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2596\r
2597 //\r
2598 // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
2599 //\r
aec072ad 2600 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
95276127 2601 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2602 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2603 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2604 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2605 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2606 }\r
2607\r
2608 //\r
2609 // Select a prefered Display mode 800x600\r
2610 //\r
2611 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2612 Mode = &Private->GraphicsOutputModeBuffer[Index];\r
2613 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
2614 break;\r
2615 }\r
2616 }\r
2617 //\r
2618 // Prefered mode is not found, set to mode 0\r
2619 //\r
2620 if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
2621 Index = 0;\r
2622 }\r
2623\r
aec072ad 2624 }\r
2625 if (UgaDraw != NULL) {\r
95276127 2626 //\r
2627 // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
2628 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\r
2629 //\r
2630 CurrentGraphicsOutputMode->MaxMode = 1;\r
aec072ad 2631 Info = CurrentGraphicsOutputMode->Info;\r
2632 Info->Version = 0;\r
2633 Info->HorizontalResolution = 800;\r
2634 Info->VerticalResolution = 600;\r
2635 Info->PixelFormat = PixelBltOnly;\r
2636 Info->PixelsPerScanLine = 800;\r
95276127 2637 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2638 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2639 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2640\r
2641 //\r
2642 // Update the private mode buffer\r
2643 //\r
aec072ad 2644 CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
95276127 2645\r
2646 //\r
aec072ad 2647 // Only mode 0 is available to be set\r
95276127 2648 //\r
95276127 2649 Index = 0;\r
2650 }\r
2651\r
aec072ad 2652Done:\r
2653\r
2654 if (GraphicsOutput != NULL) {\r
2655 Private->CurrentNumberOfGraphicsOutput++;\r
2656 }\r
2657 if (UgaDraw != NULL) {\r
2658 Private->CurrentNumberOfUgaDraw++;\r
2659 }\r
2660\r
95276127 2661 //\r
2662 // Force GraphicsOutput mode to be set,\r
2663 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
2664 //\r
2665 Private->HardwareNeedsStarting = TRUE;\r
aec072ad 2666 //\r
2667 // Current mode number may need update now, so set it to an invalid mode number\r
2668 //\r
95276127 2669 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
2670\r
95276127 2671 return Status;\r
2672}\r
2673\r
2674EFI_STATUS\r
2675ConSplitterTextOutAddDevice (\r
2676 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2677 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,\r
2678 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2679 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2680 )\r
2681/*++\r
2682\r
2683Routine Description:\r
2684\r
2685Arguments:\r
2686\r
2687Returns:\r
2688\r
2689 None\r
2690\r
2691--*/\r
2692{\r
2693 EFI_STATUS Status;\r
2694 UINTN CurrentNumOfConsoles;\r
2695 INT32 CurrentMode;\r
2696 INT32 MaxMode;\r
2697 TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
2698\r
2699 Status = EFI_SUCCESS;\r
2700 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2701\r
2702 //\r
2703 // If the Text Out List is full, enlarge it by calling growbuffer().\r
2704 //\r
2705 while (CurrentNumOfConsoles >= Private->TextOutListCount) {\r
2706 Status = ConSplitterGrowBuffer (\r
2707 sizeof (TEXT_OUT_AND_GOP_DATA),\r
2708 &Private->TextOutListCount,\r
2709 (VOID **) &Private->TextOutList\r
2710 );\r
2711 if (EFI_ERROR (Status)) {\r
2712 return EFI_OUT_OF_RESOURCES;\r
2713 }\r
2714 //\r
2715 // Also need to reallocate the TextOutModeMap table\r
2716 //\r
2717 Status = ConSplitterGrowMapTable (Private);\r
2718 if (EFI_ERROR (Status)) {\r
2719 return EFI_OUT_OF_RESOURCES;\r
2720 }\r
2721 }\r
2722\r
2723 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];\r
2724\r
2725 TextAndGop->TextOut = TextOut;\r
2726 TextAndGop->GraphicsOutput = GraphicsOutput;\r
2727 TextAndGop->UgaDraw = UgaDraw;\r
2728\r
2729 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2730 //\r
2731 // If No UGA device then use the ConOut device\r
2732 //\r
2733 TextAndGop->TextOutEnabled = TRUE;\r
2734 } else {\r
2735 //\r
2736 // If UGA device use ConOut device only used if UGA screen is in Text mode\r
2737 //\r
2738 TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
2739 }\r
2740\r
2741 if (CurrentNumOfConsoles == 0) {\r
2742 //\r
2743 // Add the first device's output mode to console splitter's mode list\r
2744 //\r
2745 Status = ConSplitterAddOutputMode (Private, TextOut);\r
2746 } else {\r
2747 ConSplitterSyncOutputMode (Private, TextOut);\r
2748 }\r
2749\r
2750 Private->CurrentNumberOfConsoles++;\r
2751\r
2752 //\r
2753 // Scan both TextOutList, for the intersection TextOut device\r
2754 // maybe both ConOut and StdErr incorporate the same Text Out\r
2755 // device in them, thus the output of both should be synced.\r
2756 //\r
2757 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2758\r
2759 CurrentMode = Private->TextOutMode.Mode;\r
2760 MaxMode = Private->TextOutMode.MaxMode;\r
2761 ASSERT (MaxMode >= 1);\r
2762\r
d0c64728 2763 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2764 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
2765 ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
2766 }\r
95276127 2767 }\r
2768\r
2769 if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
2770 //\r
2771 // We just added a new UGA device in graphics mode\r
2772 //\r
d0c64728 2773 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2774 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2775 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
2776 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2777 }\r
95276127 2778 } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
2779 //\r
2780 // The new console supports the same mode of the current console so sync up\r
2781 //\r
aec072ad 2782 DevNullSyncStdOut (Private);\r
95276127 2783 } else {\r
2784 //\r
2785 // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
2786 //\r
2787 Private->TextOut.SetMode (&Private->TextOut, 0);\r
2788 }\r
2789\r
2790 return Status;\r
2791}\r
2792\r
2793EFI_STATUS\r
2794ConSplitterTextOutDeleteDevice (\r
2795 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2796 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
2797 )\r
2798/*++\r
2799\r
2800Routine Description:\r
2801\r
2802Arguments:\r
2803\r
2804Returns:\r
2805\r
2806 None\r
2807\r
2808--*/\r
2809{\r
2810 INT32 Index;\r
2811 UINTN CurrentNumOfConsoles;\r
2812 TEXT_OUT_AND_GOP_DATA *TextOutList;\r
2813 EFI_STATUS Status;\r
2814\r
2815 //\r
2816 // Remove the specified text-out device data structure from the Text out List,\r
2817 // and rearrange the remaining data structures in the Text out List.\r
2818 //\r
2819 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2820 Index = (INT32) CurrentNumOfConsoles - 1;\r
2821 TextOutList = Private->TextOutList;\r
2822 while (Index >= 0) {\r
2823 if (TextOutList->TextOut == TextOut) {\r
2824 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
2825 CurrentNumOfConsoles--;\r
aec072ad 2826 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2827 if (TextOutList->UgaDraw != NULL) {\r
2828 Private->CurrentNumberOfUgaDraw--;\r
2829 }\r
2830 if (TextOutList->GraphicsOutput != NULL) {\r
2831 Private->CurrentNumberOfGraphicsOutput--;\r
2832 }\r
2833 }\r
95276127 2834 break;\r
2835 }\r
2836\r
2837 Index--;\r
2838 TextOutList++;\r
2839 }\r
2840 //\r
2841 // The specified TextOut is not managed by the ConSplitter driver\r
2842 //\r
2843 if (Index < 0) {\r
2844 return EFI_NOT_FOUND;\r
2845 }\r
2846\r
2847 if (CurrentNumOfConsoles == 0) {\r
2848 //\r
2849 // If the number of consoles is zero clear the Dev NULL device\r
2850 //\r
2851 Private->CurrentNumberOfConsoles = 0;\r
2852 Private->TextOutMode.MaxMode = 1;\r
2853 Private->TextOutQueryData[0].Columns = 80;\r
2854 Private->TextOutQueryData[0].Rows = 25;\r
2855 DevNullTextOutSetMode (Private, 0);\r
2856\r
2857 return EFI_SUCCESS;\r
2858 }\r
2859 //\r
2860 // Max Mode is realy an intersection of the QueryMode command to all\r
2861 // devices. So we must copy the QueryMode of the first device to\r
2862 // QueryData.\r
2863 //\r
2864 ZeroMem (\r
2865 Private->TextOutQueryData,\r
2866 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)\r
2867 );\r
2868\r
2869 FreePool (Private->TextOutModeMap);\r
2870 Private->TextOutModeMap = NULL;\r
2871 TextOutList = Private->TextOutList;\r
2872\r
2873 //\r
2874 // Add the first TextOut to the QueryData array and ModeMap table\r
2875 //\r
2876 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);\r
2877\r
2878 //\r
2879 // Now add one by one\r
2880 //\r
2881 Index = 1;\r
2882 Private->CurrentNumberOfConsoles = 1;\r
2883 TextOutList++;\r
2884 while ((UINTN) Index < CurrentNumOfConsoles) {\r
2885 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);\r
2886 Index++;\r
2887 Private->CurrentNumberOfConsoles++;\r
2888 TextOutList++;\r
2889 }\r
2890\r
2891 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2892\r
2893 return Status;\r
2894}\r
2895//\r
2896// ConSplitter TextIn member functions\r
2897//\r
2898EFI_STATUS\r
2899EFIAPI\r
2900ConSplitterTextInReset (\r
2901 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
2902 IN BOOLEAN ExtendedVerification\r
2903 )\r
2904/*++\r
2905\r
2906 Routine Description:\r
2907 Reset the input device and optionaly run diagnostics\r
2908\r
2909 Arguments:\r
2910 This - Protocol instance pointer.\r
2911 ExtendedVerification - Driver may perform diagnostics on reset.\r
2912\r
2913 Returns:\r
2914 EFI_SUCCESS - The device was reset.\r
2915 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
2916 not be reset.\r
2917\r
2918--*/\r
2919{\r
2920 EFI_STATUS Status;\r
2921 EFI_STATUS ReturnStatus;\r
2922 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2923 UINTN Index;\r
2924\r
2925 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2926\r
2927 Private->KeyEventSignalState = FALSE;\r
2928\r
2929 //\r
2930 // return the worst status met\r
2931 //\r
2932 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2933 Status = Private->TextInList[Index]->Reset (\r
2934 Private->TextInList[Index],\r
2935 ExtendedVerification\r
2936 );\r
2937 if (EFI_ERROR (Status)) {\r
2938 ReturnStatus = Status;\r
2939 }\r
2940 }\r
2941\r
2942 return ReturnStatus;\r
2943}\r
2944\r
2945EFI_STATUS\r
2946EFIAPI\r
2947ConSplitterTextInPrivateReadKeyStroke (\r
2948 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2949 OUT EFI_INPUT_KEY *Key\r
2950 )\r
2951/*++\r
2952\r
2953 Routine Description:\r
2954 Reads the next keystroke from the input device. The WaitForKey Event can\r
2955 be used to test for existance of a keystroke via WaitForEvent () call.\r
2956\r
2957 Arguments:\r
2958 This - Protocol instance pointer.\r
2959 Key - Driver may perform diagnostics on reset.\r
2960\r
2961 Returns:\r
2962 EFI_SUCCESS - The keystroke information was returned.\r
2963 EFI_NOT_READY - There was no keystroke data availiable.\r
2964 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2965 hardware errors.\r
2966\r
2967--*/\r
2968{\r
2969 EFI_STATUS Status;\r
2970 UINTN Index;\r
2971 EFI_INPUT_KEY CurrentKey;\r
2972\r
2973 Key->UnicodeChar = 0;\r
2974 Key->ScanCode = SCAN_NULL;\r
2975\r
2976 //\r
2977 // if no physical console input device exists, return EFI_NOT_READY;\r
2978 // if any physical console input device has key input,\r
2979 // return the key and EFI_SUCCESS.\r
2980 //\r
2981 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2982 Status = Private->TextInList[Index]->ReadKeyStroke (\r
2983 Private->TextInList[Index],\r
2984 &CurrentKey\r
2985 );\r
2986 if (!EFI_ERROR (Status)) {\r
2987 *Key = CurrentKey;\r
2988 return Status;\r
2989 }\r
2990 }\r
2991\r
2992 return EFI_NOT_READY;\r
2993}\r
2994\r
2995BOOLEAN\r
2996ConSpliterConssoleControlStdInLocked (\r
2997 VOID\r
2998 )\r
2999/*++\r
3000\r
3001Routine Description:\r
3002 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is\r
3003 the only device locked.\r
3004\r
3005Arguments:\r
3006 NONE\r
3007\r
3008Returns:\r
3009 TRUE - StdIn locked\r
3010 FALSE - StdIn working normally\r
3011\r
3012--*/\r
3013{\r
3014 return mConIn.PasswordEnabled;\r
3015}\r
3016\r
3017VOID\r
3018EFIAPI\r
3019ConSpliterConsoleControlLockStdInEvent (\r
3020 IN EFI_EVENT Event,\r
3021 IN VOID *Context\r
3022 )\r
3023/*++\r
3024\r
3025Routine Description:\r
3026 This timer event will fire when StdIn is locked. It will check the key\r
3027 sequence on StdIn to see if it matches the password. Any error in the\r
3028 password will cause the check to reset. As long a mConIn.PasswordEnabled is\r
3029 TRUE the StdIn splitter will not report any input.\r
3030\r
3031Arguments:\r
3032 (Standard EFI_EVENT_NOTIFY)\r
3033\r
3034Returns:\r
3035 None\r
3036\r
3037--*/\r
3038{\r
3039 EFI_STATUS Status;\r
3040 EFI_INPUT_KEY Key;\r
3041 CHAR16 BackSpaceString[2];\r
3042 CHAR16 SpaceString[2];\r
3043\r
3044 do {\r
3045 Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);\r
3046 if (!EFI_ERROR (Status)) {\r
3047 //\r
3048 // if it's an ENTER, match password\r
3049 //\r
3050 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {\r
3051 mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;\r
3052 if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {\r
3053 //\r
3054 // Password not match\r
3055 //\r
3056 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");\r
3057 mConIn.PwdIndex = 0;\r
3058 } else {\r
3059 //\r
3060 // Key matches password sequence\r
3061 //\r
3062 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);\r
3063 mConIn.PasswordEnabled = FALSE;\r
3064 Status = EFI_NOT_READY;\r
3065 }\r
3066 } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {\r
3067 //\r
3068 // BackSpace met\r
3069 //\r
3070 if (mConIn.PwdIndex > 0) {\r
3071 BackSpaceString[0] = CHAR_BACKSPACE;\r
3072 BackSpaceString[1] = 0;\r
3073\r
3074 SpaceString[0] = ' ';\r
3075 SpaceString[1] = 0;\r
3076\r
3077 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3078 ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);\r
3079 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3080\r
3081 mConIn.PwdIndex--;\r
3082 }\r
3083 } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {\r
3084 //\r
3085 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input\r
3086 //\r
3087 if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {\r
3088 if (mConIn.PwdIndex == 0) {\r
3089 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");\r
3090 }\r
3091\r
3092 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");\r
3093 mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;\r
3094 mConIn.PwdIndex++;\r
3095 }\r
3096 }\r
3097 }\r
3098 } while (!EFI_ERROR (Status));\r
3099}\r
3100\r
3101EFI_STATUS\r
3102EFIAPI\r
3103ConSpliterConsoleControlLockStdIn (\r
3104 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
3105 IN CHAR16 *Password\r
3106 )\r
3107/*++\r
3108\r
3109Routine Description:\r
3110 If Password is NULL unlock the password state variable and set the event\r
3111 timer. If the Password is too big return an error. If the Password is valid\r
3112 Copy the Password and enable state variable and then arm the periodic timer\r
3113\r
3114Arguments:\r
3115\r
3116Returns:\r
3117 EFI_SUCCESS - Lock the StdIn device\r
3118 EFI_INVALID_PARAMETER - Password is NULL\r
3119 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails\r
3120\r
3121--*/\r
3122{\r
3123 if (Password == NULL) {\r
3124 return EFI_INVALID_PARAMETER;\r
3125 }\r
3126\r
3127 if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {\r
3128 //\r
3129 // Currently have a max password size\r
3130 //\r
3131 return EFI_OUT_OF_RESOURCES;\r
3132 }\r
3133 //\r
3134 // Save the password, initialize state variables and arm event timer\r
3135 //\r
3136 StrCpy (mConIn.Password, Password);\r
3137 mConIn.PasswordEnabled = TRUE;\r
3138 mConIn.PwdIndex = 0;\r
3139 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));\r
3140\r
3141 return EFI_SUCCESS;\r
3142}\r
3143\r
3144EFI_STATUS\r
3145EFIAPI\r
3146ConSplitterTextInReadKeyStroke (\r
3147 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
3148 OUT EFI_INPUT_KEY *Key\r
3149 )\r
3150/*++\r
3151\r
3152 Routine Description:\r
3153 Reads the next keystroke from the input device. The WaitForKey Event can\r
3154 be used to test for existance of a keystroke via WaitForEvent () call.\r
3155 If the ConIn is password locked make it look like no keystroke is availible\r
3156\r
3157 Arguments:\r
3158 This - Protocol instance pointer.\r
3159 Key - Driver may perform diagnostics on reset.\r
3160\r
3161 Returns:\r
3162 EFI_SUCCESS - The keystroke information was returned.\r
3163 EFI_NOT_READY - There was no keystroke data availiable.\r
3164 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
3165 hardware errors.\r
3166\r
3167--*/\r
3168{\r
3169 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3170\r
3171 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3172 if (Private->PasswordEnabled) {\r
3173 //\r
3174 // If StdIn Locked return not ready\r
3175 //\r
3176 return EFI_NOT_READY;\r
3177 }\r
3178\r
3179 Private->KeyEventSignalState = FALSE;\r
3180\r
3181 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
3182}\r
3183\r
3184VOID\r
3185EFIAPI\r
3186ConSplitterTextInWaitForKey (\r
3187 IN EFI_EVENT Event,\r
3188 IN VOID *Context\r
3189 )\r
3190/*++\r
3191\r
3192Routine Description:\r
3193 This event agregates all the events of the ConIn devices in the spliter.\r
3194 If the ConIn is password locked then return.\r
3195 If any events of physical ConIn devices are signaled, signal the ConIn\r
3196 spliter event. This will cause the calling code to call\r
3197 ConSplitterTextInReadKeyStroke ().\r
3198\r
3199Arguments:\r
3200 Event - The Event assoicated with callback.\r
3201 Context - Context registered when Event was created.\r
3202\r
3203Returns:\r
3204 None\r
3205\r
3206--*/\r
3207{\r
3208 EFI_STATUS Status;\r
3209 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3210 UINTN Index;\r
3211\r
3212 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
3213 if (Private->PasswordEnabled) {\r
3214 //\r
3215 // If StdIn Locked return not ready\r
3216 //\r
3217 return ;\r
3218 }\r
3219\r
3220 //\r
3221 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
3222 //\r
3223 if (Private->KeyEventSignalState) {\r
3224 gBS->SignalEvent (Event);\r
3225 return ;\r
3226 }\r
3227 //\r
3228 // if any physical console input device has key input, signal the event.\r
3229 //\r
3230 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3231 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);\r
3232 if (!EFI_ERROR (Status)) {\r
3233 gBS->SignalEvent (Event);\r
3234 Private->KeyEventSignalState = TRUE;\r
3235 }\r
3236 }\r
3237}\r
3238\r
66aa04e4 3239\r
3240STATIC\r
3241BOOLEAN\r
3242IsKeyRegistered (\r
3243 IN EFI_KEY_DATA *RegsiteredData,\r
3244 IN EFI_KEY_DATA *InputData\r
3245 )\r
3246/*++\r
3247\r
3248Routine Description:\r
3249\r
3250Arguments:\r
3251\r
7a5064ce 3252 RegsiteredData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 3253 state data for the key that was registered.\r
7a5064ce 3254 InputData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 3255 state data for the key that was pressed.\r
3256\r
3257Returns:\r
3258 TRUE - Key be pressed matches a registered key.\r
7a5064ce 3259 FLASE - Match failed.\r
3260\r
66aa04e4 3261--*/\r
3262{\r
3263 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
7a5064ce 3264\r
66aa04e4 3265 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
3266 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
7a5064ce 3267 return FALSE;\r
3268 }\r
3269\r
66aa04e4 3270 //\r
3271 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
3272 //\r
3273 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
3274 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
7a5064ce 3275 return FALSE;\r
3276 }\r
66aa04e4 3277 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
3278 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
7a5064ce 3279 return FALSE;\r
3280 }\r
3281\r
66aa04e4 3282 return TRUE;\r
3283\r
3284}\r
3285\r
3286//\r
3287// Simple Text Input Ex protocol functions\r
3288//\r
3289\r
3290EFI_STATUS\r
3291EFIAPI\r
3292ConSplitterTextInResetEx (\r
3293 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3294 IN BOOLEAN ExtendedVerification\r
3295 )\r
3296/*++\r
3297\r
3298 Routine Description:\r
3299 Reset the input device and optionaly run diagnostics\r
3300\r
3301 Arguments:\r
3302 This - Protocol instance pointer.\r
3303 ExtendedVerification - Driver may perform diagnostics on reset.\r
3304\r
3305 Returns:\r
3306 EFI_SUCCESS - The device was reset.\r
7a5064ce 3307 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
66aa04e4 3308 not be reset.\r
3309\r
3310--*/\r
3311{\r
3312 EFI_STATUS Status;\r
3313 EFI_STATUS ReturnStatus;\r
3314 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3315 UINTN Index;\r
3316\r
3317 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3318\r
3319 Private->KeyEventSignalState = FALSE;\r
3320\r
3321 //\r
3322 // return the worst status met\r
3323 //\r
3324 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3325 Status = Private->TextInExList[Index]->Reset (\r
3326 Private->TextInExList[Index],\r
3327 ExtendedVerification\r
3328 );\r
3329 if (EFI_ERROR (Status)) {\r
3330 ReturnStatus = Status;\r
3331 }\r
3332 }\r
3333\r
3334 return ReturnStatus;\r
3335\r
3336}\r
3337\r
3338EFI_STATUS\r
3339EFIAPI\r
3340ConSplitterTextInReadKeyStrokeEx (\r
3341 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3342 OUT EFI_KEY_DATA *KeyData\r
3343 )\r
3344/*++\r
3345\r
3346 Routine Description:\r
7a5064ce 3347 Reads the next keystroke from the input device. The WaitForKey Event can\r
66aa04e4 3348 be used to test for existance of a keystroke via WaitForEvent () call.\r
3349\r
3350 Arguments:\r
3351 This - Protocol instance pointer.\r
7a5064ce 3352 KeyData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 3353 state data for the key that was pressed.\r
3354\r
3355 Returns:\r
3356 EFI_SUCCESS - The keystroke information was returned.\r
3357 EFI_NOT_READY - There was no keystroke data availiable.\r
7a5064ce 3358 EFI_DEVICE_ERROR - The keystroke information was not returned due to\r
66aa04e4 3359 hardware errors.\r
7a5064ce 3360 EFI_INVALID_PARAMETER - KeyData is NULL.\r
66aa04e4 3361\r
3362--*/\r
3363{\r
3364 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3365 EFI_STATUS Status;\r
3366 UINTN Index;\r
3367 EFI_KEY_DATA CurrentKeyData;\r
3368\r
7a5064ce 3369\r
66aa04e4 3370 if (KeyData == NULL) {\r
3371 return EFI_INVALID_PARAMETER;\r
3372 }\r
3373\r
3374 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3375 if (Private->PasswordEnabled) {\r
3376 //\r
3377 // If StdIn Locked return not ready\r
3378 //\r
3379 return EFI_NOT_READY;\r
3380 }\r
3381\r
3382 Private->KeyEventSignalState = FALSE;\r
3383\r
3384 KeyData->Key.UnicodeChar = 0;\r
3385 KeyData->Key.ScanCode = SCAN_NULL;\r
3386\r
3387 //\r
3388 // if no physical console input device exists, return EFI_NOT_READY;\r
3389 // if any physical console input device has key input,\r
3390 // return the key and EFI_SUCCESS.\r
3391 //\r
3392 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3393 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
3394 Private->TextInExList[Index],\r
3395 &CurrentKeyData\r
3396 );\r
3397 if (!EFI_ERROR (Status)) {\r
3398 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
3399 return Status;\r
3400 }\r
3401 }\r
3402\r
7a5064ce 3403 return EFI_NOT_READY;\r
66aa04e4 3404}\r
3405\r
3406EFI_STATUS\r
3407EFIAPI\r
3408ConSplitterTextInSetState (\r
3409 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3410 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
3411 )\r
3412/*++\r
3413\r
3414 Routine Description:\r
3415 Set certain state for the input device.\r
3416\r
3417 Arguments:\r
3418 This - Protocol instance pointer.\r
7a5064ce 3419 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
66aa04e4 3420 state for the input device.\r
7a5064ce 3421\r
3422 Returns:\r
66aa04e4 3423 EFI_SUCCESS - The device state was set successfully.\r
7a5064ce 3424 EFI_DEVICE_ERROR - The device is not functioning correctly and could\r
66aa04e4 3425 not have the setting adjusted.\r
3426 EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
7a5064ce 3427 EFI_INVALID_PARAMETER - KeyToggleState is NULL.\r
66aa04e4 3428\r
7a5064ce 3429--*/\r
66aa04e4 3430{\r
3431 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3432 EFI_STATUS Status;\r
3433 UINTN Index;\r
3434\r
3435 if (KeyToggleState == NULL) {\r
3436 return EFI_INVALID_PARAMETER;\r
3437 }\r
3438\r
3439 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3440\r
3441 //\r
3442 // if no physical console input device exists, return EFI_SUCCESS;\r
3443 // otherwise return the status of setting state of physical console input device\r
3444 //\r
3445 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3446 Status = Private->TextInExList[Index]->SetState (\r
3447 Private->TextInExList[Index],\r
3448 KeyToggleState\r
3449 );\r
3450 if (EFI_ERROR (Status)) {\r
3451 return Status;\r
3452 }\r
3453 }\r
3454\r
7a5064ce 3455 return EFI_SUCCESS;\r
66aa04e4 3456\r
3457}\r
3458\r
3459EFI_STATUS\r
3460EFIAPI\r
3461ConSplitterTextInRegisterKeyNotify (\r
3462 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3463 IN EFI_KEY_DATA *KeyData,\r
3464 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
3465 OUT EFI_HANDLE *NotifyHandle\r
3466 )\r
3467/*++\r
3468\r
3469 Routine Description:\r
3470 Register a notification function for a particular keystroke for the input device.\r
3471\r
3472 Arguments:\r
3473 This - Protocol instance pointer.\r
7a5064ce 3474 KeyData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 3475 information data for the key that was pressed.\r
7a5064ce 3476 KeyNotificationFunction - Points to the function to be called when the key\r
3477 sequence is typed specified by KeyData.\r
3478 NotifyHandle - Points to the unique handle assigned to the registered notification.\r
66aa04e4 3479\r
3480 Returns:\r
3481 EFI_SUCCESS - The notification function was registered successfully.\r
3482 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
7a5064ce 3483 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.\r
3484\r
3485--*/\r
66aa04e4 3486{\r
3487 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3488 EFI_STATUS Status;\r
3489 UINTN Index;\r
3490 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
3491 LIST_ENTRY *Link;\r
7a5064ce 3492 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
3493\r
66aa04e4 3494\r
3495 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
3496 return EFI_INVALID_PARAMETER;\r
3497 }\r
3498\r
3499 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3500\r
3501 //\r
7a5064ce 3502 // if no physical console input device exists,\r
66aa04e4 3503 // return EFI_SUCCESS directly.\r
3504 //\r
3505 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3506 return EFI_SUCCESS;\r
3507 }\r
3508\r
3509 //\r
3510 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
3511 //\r
3512 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3513 CurrentNotify = CR (\r
7a5064ce 3514 Link,\r
3515 TEXT_IN_EX_SPLITTER_NOTIFY,\r
3516 NotifyEntry,\r
66aa04e4 3517 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
3518 );\r
7a5064ce 3519 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 3520 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
7a5064ce 3521 *NotifyHandle = CurrentNotify->NotifyHandle;\r
66aa04e4 3522 return EFI_SUCCESS;\r
3523 }\r
3524 }\r
3525 }\r
7a5064ce 3526\r
66aa04e4 3527 //\r
3528 // Allocate resource to save the notification function\r
7a5064ce 3529 //\r
66aa04e4 3530 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
3531 if (NewNotify == NULL) {\r
3532 return EFI_OUT_OF_RESOURCES;\r
3533 }\r
3534 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
3535 if (NewNotify->NotifyHandleList == NULL) {\r
3536 gBS->FreePool (NewNotify);\r
3537 return EFI_OUT_OF_RESOURCES;\r
3538 }\r
7a5064ce 3539 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;\r
66aa04e4 3540 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
3541 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
7a5064ce 3542\r
66aa04e4 3543 //\r
7a5064ce 3544 // Return the wrong status of registering key notify of\r
66aa04e4 3545 // physical console input device if meet problems\r
3546 //\r
3547 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3548 Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
3549 Private->TextInExList[Index],\r
3550 KeyData,\r
3551 KeyNotificationFunction,\r
3552 &NewNotify->NotifyHandleList[Index]\r
3553 );\r
3554 if (EFI_ERROR (Status)) {\r
3555 gBS->FreePool (NewNotify->NotifyHandleList);\r
3556 gBS->FreePool (NewNotify);\r
3557 return Status;\r
3558 }\r
3559 }\r
3560\r
3561 //\r
3562 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
7a5064ce 3563 //\r
66aa04e4 3564 Status = gBS->InstallMultipleProtocolInterfaces (\r
3565 &NewNotify->NotifyHandle,\r
3566 &gSimpleTextInExNotifyGuid,\r
3567 NULL,\r
3568 NULL\r
3569 );\r
3570 ASSERT_EFI_ERROR (Status);\r
3571\r
3572 InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
7a5064ce 3573\r
3574 *NotifyHandle = NewNotify->NotifyHandle;\r
3575\r
3576 return EFI_SUCCESS;\r
3577\r
66aa04e4 3578}\r
3579\r
3580EFI_STATUS\r
3581EFIAPI\r
3582ConSplitterTextInUnregisterKeyNotify (\r
3583 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3584 IN EFI_HANDLE NotificationHandle\r
3585 )\r
3586/*++\r
3587\r
3588 Routine Description:\r
3589 Remove a registered notification function from a particular keystroke.\r
3590\r
3591 Arguments:\r
7a5064ce 3592 This - Protocol instance pointer.\r
66aa04e4 3593 NotificationHandle - The handle of the notification function being unregistered.\r
3594\r
3595 Returns:\r
3596 EFI_SUCCESS - The notification function was unregistered successfully.\r
3597 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
7a5064ce 3598 EFI_NOT_FOUND - Can not find the matching entry in database.\r
3599\r
3600--*/\r
66aa04e4 3601{\r
3602 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3603 EFI_STATUS Status;\r
3604 UINTN Index;\r
3605 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
7a5064ce 3606 LIST_ENTRY *Link;\r
66aa04e4 3607\r
3608 if (NotificationHandle == NULL) {\r
3609 return EFI_INVALID_PARAMETER;\r
3610 }\r
3611\r
3612 Status = gBS->OpenProtocol (\r
3613 NotificationHandle,\r
3614 &gSimpleTextInExNotifyGuid,\r
3615 NULL,\r
3616 NULL,\r
3617 NULL,\r
3618 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
3619 );\r
3620 if (EFI_ERROR (Status)) {\r
3621 return EFI_INVALID_PARAMETER;\r
3622 }\r
3623\r
3624 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3625\r
3626 //\r
7a5064ce 3627 // if no physical console input device exists,\r
66aa04e4 3628 // return EFI_SUCCESS directly.\r
3629 //\r
3630 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3631 return EFI_SUCCESS;\r
3632 }\r
3633\r
3634 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3635 CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
3636 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
3637 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3638 Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
7a5064ce 3639 Private->TextInExList[Index],\r
66aa04e4 3640 CurrentNotify->NotifyHandleList[Index]\r
3641 );\r
3642 if (EFI_ERROR (Status)) {\r
3643 return Status;\r
7a5064ce 3644 }\r
66aa04e4 3645 }\r
7a5064ce 3646 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
66aa04e4 3647 Status = gBS->UninstallMultipleProtocolInterfaces (\r
3648 CurrentNotify->NotifyHandle,\r
3649 &gSimpleTextInExNotifyGuid,\r
3650 NULL,\r
3651 NULL\r
3652 );\r
3653 ASSERT_EFI_ERROR (Status);\r
3654 gBS->FreePool (CurrentNotify->NotifyHandleList);\r
3655 gBS->FreePool (CurrentNotify);\r
7a5064ce 3656 return EFI_SUCCESS;\r
3657 }\r
66aa04e4 3658 }\r
3659\r
7a5064ce 3660 return EFI_NOT_FOUND;\r
3661\r
66aa04e4 3662}\r
3663\r
95276127 3664EFI_STATUS\r
3665EFIAPI\r
3666ConSplitterSimplePointerReset (\r
3667 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
3668 IN BOOLEAN ExtendedVerification\r
3669 )\r
3670/*++\r
3671\r
3672 Routine Description:\r
3673 Reset the input device and optionaly run diagnostics\r
3674\r
3675 Arguments:\r
3676 This - Protocol instance pointer.\r
3677 ExtendedVerification - Driver may perform diagnostics on reset.\r
3678\r
3679 Returns:\r
3680 EFI_SUCCESS - The device was reset.\r
3681 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
3682 not be reset.\r
3683\r
3684--*/\r
3685{\r
3686 EFI_STATUS Status;\r
3687 EFI_STATUS ReturnStatus;\r
3688 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3689 UINTN Index;\r
3690\r
3691 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
3692\r
3693 Private->InputEventSignalState = FALSE;\r
3694\r
3695 if (Private->CurrentNumberOfPointers == 0) {\r
3696 return EFI_SUCCESS;\r
3697 }\r
3698 //\r
3699 // return the worst status met\r
3700 //\r
3701 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
3702 Status = Private->PointerList[Index]->Reset (\r
3703 Private->PointerList[Index],\r
3704 ExtendedVerification\r
3705 );\r
3706 if (EFI_ERROR (Status)) {\r
3707 ReturnStatus = Status;\r
3708 }\r
3709 }\r
3710\r
3711 return ReturnStatus;\r
3712}\r
3713\r
3714STATIC\r
3715EFI_STATUS\r
3716EFIAPI\r
3717ConSplitterSimplePointerPrivateGetState (\r
3718 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
3719 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
3720 )\r
3721/*++\r
3722\r
3723 Routine Description:\r
3724 Reads the next keystroke from the input device. The WaitForKey Event can\r
3725 be used to test for existance of a keystroke via WaitForEvent () call.\r
3726\r
3727 Arguments:\r
3728 This - Protocol instance pointer.\r
3729 State -\r
3730\r
3731 Returns:\r
3732 EFI_SUCCESS - The keystroke information was returned.\r
3733 EFI_NOT_READY - There was no keystroke data availiable.\r
3734 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
3735 hardware errors.\r
3736\r
3737--*/\r
3738{\r
3739 EFI_STATUS Status;\r
3740 EFI_STATUS ReturnStatus;\r
3741 UINTN Index;\r
3742 EFI_SIMPLE_POINTER_STATE CurrentState;\r
3743\r
3744 State->RelativeMovementX = 0;\r
3745 State->RelativeMovementY = 0;\r
3746 State->RelativeMovementZ = 0;\r
3747 State->LeftButton = FALSE;\r
3748 State->RightButton = FALSE;\r
3749\r
3750 //\r
3751 // if no physical console input device exists, return EFI_NOT_READY;\r
3752 // if any physical console input device has key input,\r
3753 // return the key and EFI_SUCCESS.\r
3754 //\r
3755 ReturnStatus = EFI_NOT_READY;\r
3756 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
3757\r
3758 Status = Private->PointerList[Index]->GetState (\r
3759 Private->PointerList[Index],\r
3760 &CurrentState\r
3761 );\r
3762 if (!EFI_ERROR (Status)) {\r
3763 if (ReturnStatus == EFI_NOT_READY) {\r
3764 ReturnStatus = EFI_SUCCESS;\r
3765 }\r
3766\r
3767 if (CurrentState.LeftButton) {\r
3768 State->LeftButton = TRUE;\r
3769 }\r
3770\r
3771 if (CurrentState.RightButton) {\r
3772 State->RightButton = TRUE;\r
3773 }\r
3774\r
3775 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
3776 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
3777 }\r
3778\r
3779 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
3780 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
3781 }\r
3782\r
3783 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
3784 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
3785 }\r
3786 } else if (Status == EFI_DEVICE_ERROR) {\r
3787 ReturnStatus = EFI_DEVICE_ERROR;\r
3788 }\r
3789 }\r
3790\r
3791 return ReturnStatus;\r
3792}\r
3793\r
3794EFI_STATUS\r
3795EFIAPI\r
3796ConSplitterSimplePointerGetState (\r
3797 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
3798 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
3799 )\r
3800/*++\r
3801\r
3802 Routine Description:\r
3803 Reads the next keystroke from the input device. The WaitForKey Event can\r
3804 be used to test for existance of a keystroke via WaitForEvent () call.\r
3805 If the ConIn is password locked make it look like no keystroke is availible\r
3806\r
3807 Arguments:\r
3808 This - Protocol instance pointer.\r
3809 State -\r
3810\r
3811 Returns:\r
3812 EFI_SUCCESS - The keystroke information was returned.\r
3813 EFI_NOT_READY - There was no keystroke data availiable.\r
3814 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
3815 hardware errors.\r
3816\r
3817--*/\r
3818{\r
3819 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3820\r
3821 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
3822 if (Private->PasswordEnabled) {\r
3823 //\r
3824 // If StdIn Locked return not ready\r
3825 //\r
3826 return EFI_NOT_READY;\r
3827 }\r
3828\r
3829 Private->InputEventSignalState = FALSE;\r
3830\r
3831 return ConSplitterSimplePointerPrivateGetState (Private, State);\r
3832}\r
3833\r
3834VOID\r
3835EFIAPI\r
3836ConSplitterSimplePointerWaitForInput (\r
3837 IN EFI_EVENT Event,\r
3838 IN VOID *Context\r
3839 )\r
3840/*++\r
3841\r
3842Routine Description:\r
3843 This event agregates all the events of the ConIn devices in the spliter.\r
3844 If the ConIn is password locked then return.\r
3845 If any events of physical ConIn devices are signaled, signal the ConIn\r
3846 spliter event. This will cause the calling code to call\r
3847 ConSplitterTextInReadKeyStroke ().\r
3848\r
3849Arguments:\r
3850 Event - The Event assoicated with callback.\r
3851 Context - Context registered when Event was created.\r
3852\r
3853Returns:\r
3854 None\r
3855\r
3856--*/\r
3857{\r
3858 EFI_STATUS Status;\r
3859 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3860 UINTN Index;\r
3861\r
3862 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
3863 if (Private->PasswordEnabled) {\r
3864 //\r
3865 // If StdIn Locked return not ready\r
3866 //\r
3867 return ;\r
3868 }\r
3869\r
3870 //\r
3871 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
3872 //\r
3873 if (Private->InputEventSignalState) {\r
3874 gBS->SignalEvent (Event);\r
3875 return ;\r
3876 }\r
3877 //\r
3878 // if any physical console input device has key input, signal the event.\r
3879 //\r
3880 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
3881 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);\r
3882 if (!EFI_ERROR (Status)) {\r
3883 gBS->SignalEvent (Event);\r
3884 Private->InputEventSignalState = TRUE;\r
3885 }\r
3886 }\r
3887}\r
3888\r
8ae0b360 3889//\r
3890// Absolute Pointer Protocol functions\r
3891//\r
3892\r
3893EFI_STATUS\r
3894EFIAPI\r
3895ConSplitterAbsolutePointerReset (\r
3896 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
3897 IN BOOLEAN ExtendedVerification\r
3898 )\r
3899/*++\r
3900\r
3901 Routine Description:\r
3902 Resets the pointer device hardware.\r
3903\r
3904 Arguments:\r
3905 This - Protocol instance pointer.\r
3906 ExtendedVerification - Driver may perform diagnostics on reset.\r
3907\r
3908 Returns:\r
3909 EFI_SUCCESS - The device was reset.\r
7a5064ce 3910 EFI_DEVICE_ERROR - The device is not functioning correctly and could\r
8ae0b360 3911 not be reset.\r
7a5064ce 3912\r
8ae0b360 3913--*/\r
3914{\r
3915 EFI_STATUS Status;\r
3916 EFI_STATUS ReturnStatus;\r
3917 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3918 UINTN Index;\r
3919\r
3920 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
3921\r
3922 Private->AbsoluteInputEventSignalState = FALSE;\r
7a5064ce 3923\r
8ae0b360 3924 if (Private->CurrentNumberOfAbsolutePointers == 0) {\r
3925 return EFI_SUCCESS;\r
3926 }\r
3927 //\r
3928 // return the worst status met\r
3929 //\r
3930 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
3931 Status = Private->AbsolutePointerList[Index]->Reset (\r
3932 Private->AbsolutePointerList[Index],\r
3933 ExtendedVerification\r
3934 );\r
3935 if (EFI_ERROR (Status)) {\r
3936 ReturnStatus = Status;\r
3937 }\r
3938 }\r
3939\r
3940 return ReturnStatus;\r
3941}\r
3942\r
3943EFI_STATUS\r
7a5064ce 3944EFIAPI\r
8ae0b360 3945ConSplitterAbsolutePointerGetState (\r
3946 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
3947 IN OUT EFI_ABSOLUTE_POINTER_STATE *State\r
3948 )\r
3949/*++\r
3950\r
3951 Routine Description:\r
3952 Retrieves the current state of a pointer device.\r
3953\r
3954 Arguments:\r
3955 This - Protocol instance pointer.\r
3956 State - A pointer to the state information on the pointer device.\r
3957\r
3958 Returns:\r
3959 EFI_SUCCESS - The state of the pointer device was returned in State..\r
3960 EFI_NOT_READY - The state of the pointer device has not changed since the last call to\r
7a5064ce 3961 GetState().\r
8ae0b360 3962 EFI_DEVICE_ERROR - A device error occurred while attempting to retrieve the pointer\r
7a5064ce 3963 device's current state.\r
8ae0b360 3964--*/\r
3965{\r
3966 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3967 EFI_STATUS Status;\r
3968 EFI_STATUS ReturnStatus;\r
3969 UINTN Index;\r
3970 EFI_ABSOLUTE_POINTER_STATE CurrentState;\r
3971\r
3972\r
3973 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
3974 if (Private->PasswordEnabled) {\r
3975 //\r
3976 // If StdIn Locked return not ready\r
3977 //\r
3978 return EFI_NOT_READY;\r
3979 }\r
3980\r
3981 Private->AbsoluteInputEventSignalState = FALSE;\r
3982\r
3983 State->CurrentX = 0;\r
3984 State->CurrentY = 0;\r
3985 State->CurrentZ = 0;\r
3986 State->ActiveButtons = 0;\r
7a5064ce 3987\r
8ae0b360 3988 //\r
3989 // if no physical pointer device exists, return EFI_NOT_READY;\r
3990 // if any physical pointer device has changed state,\r
3991 // return the state and EFI_SUCCESS.\r
3992 //\r
3993 ReturnStatus = EFI_NOT_READY;\r
3994 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
3995\r
3996 Status = Private->AbsolutePointerList[Index]->GetState (\r
3997 Private->AbsolutePointerList[Index],\r
3998 &CurrentState\r
3999 );\r
4000 if (!EFI_ERROR (Status)) {\r
4001 if (ReturnStatus == EFI_NOT_READY) {\r
4002 ReturnStatus = EFI_SUCCESS;\r
4003 }\r
4004\r
4005 State->ActiveButtons = CurrentState.ActiveButtons;\r
4006\r
4007 if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
4008 State->CurrentX = CurrentState.CurrentX;\r
4009 }\r
4010 if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
4011 State->CurrentY = CurrentState.CurrentY;\r
4012 }\r
4013 if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
4014 State->CurrentZ = CurrentState.CurrentZ;\r
4015 }\r
7a5064ce 4016\r
8ae0b360 4017 } else if (Status == EFI_DEVICE_ERROR) {\r
4018 ReturnStatus = EFI_DEVICE_ERROR;\r
4019 }\r
4020 }\r
4021\r
4022 return ReturnStatus;\r
4023}\r
4024\r
4025VOID\r
4026EFIAPI\r
4027ConSplitterAbsolutePointerWaitForInput (\r
4028 IN EFI_EVENT Event,\r
4029 IN VOID *Context\r
4030 )\r
4031/*++\r
4032\r
4033Routine Description:\r
4034 This event agregates all the events of the pointer devices in the splitter.\r
4035 If the ConIn is password locked then return.\r
4036 If any events of physical pointer devices are signaled, signal the pointer\r
4037 splitter event. This will cause the calling code to call\r
4038 ConSplitterAbsolutePointerGetState ().\r
4039\r
4040Arguments:\r
4041 Event - The Event assoicated with callback.\r
4042 Context - Context registered when Event was created.\r
4043\r
4044Returns:\r
4045 None\r
4046\r
4047--*/\r
4048{\r
4049 EFI_STATUS Status;\r
4050 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4051 UINTN Index;\r
4052\r
4053 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
4054 if (Private->PasswordEnabled) {\r
4055 //\r
4056 // If StdIn Locked return not ready\r
4057 //\r
4058 return ;\r
4059 }\r
4060\r
4061 //\r
7a5064ce 4062 // if AbsoluteInputEventSignalState is flagged before,\r
8ae0b360 4063 // and not cleared by Reset() or GetState(), signal it\r
4064 //\r
4065 if (Private->AbsoluteInputEventSignalState) {\r
4066 gBS->SignalEvent (Event);\r
4067 return ;\r
4068 }\r
4069 //\r
4070 // if any physical console input device has key input, signal the event.\r
4071 //\r
4072 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
4073 Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);\r
4074 if (!EFI_ERROR (Status)) {\r
4075 gBS->SignalEvent (Event);\r
4076 Private->AbsoluteInputEventSignalState = TRUE;\r
4077 }\r
4078 }\r
4079}\r
4080\r
95276127 4081EFI_STATUS\r
4082EFIAPI\r
4083ConSplitterTextOutReset (\r
4084 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4085 IN BOOLEAN ExtendedVerification\r
4086 )\r
4087/*++\r
4088\r
4089 Routine Description:\r
4090 Reset the text output device hardware and optionaly run diagnostics\r
4091\r
4092 Arguments:\r
4093 This - Protocol instance pointer.\r
4094 ExtendedVerification - Driver may perform more exhaustive verfication\r
4095 operation of the device during reset.\r
4096\r
4097 Returns:\r
4098 EFI_SUCCESS - The text output device was reset.\r
4099 EFI_DEVICE_ERROR - The text output device is not functioning correctly and\r
4100 could not be reset.\r
4101\r
4102--*/\r
4103{\r
4104 EFI_STATUS Status;\r
4105 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4106 UINTN Index;\r
4107 EFI_STATUS ReturnStatus;\r
4108\r
4109 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4110\r
4111 //\r
4112 // return the worst status met\r
4113 //\r
4114 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4115\r
4116 if (Private->TextOutList[Index].TextOutEnabled) {\r
4117\r
4118 Status = Private->TextOutList[Index].TextOut->Reset (\r
4119 Private->TextOutList[Index].TextOut,\r
4120 ExtendedVerification\r
4121 );\r
4122 if (EFI_ERROR (Status)) {\r
4123 ReturnStatus = Status;\r
4124 }\r
4125 }\r
4126 }\r
4127\r
4128 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
4129\r
4130 Status = DevNullTextOutSetMode (Private, 0);\r
4131 if (EFI_ERROR (Status)) {\r
4132 ReturnStatus = Status;\r
4133 }\r
4134\r
4135 return ReturnStatus;\r
4136}\r
4137\r
4138EFI_STATUS\r
4139EFIAPI\r
4140ConSplitterTextOutOutputString (\r
4141 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4142 IN CHAR16 *WString\r
4143 )\r
4144/*++\r
4145\r
4146 Routine Description:\r
4147 Write a Unicode string to the output device.\r
4148\r
4149 Arguments:\r
4150 This - Protocol instance pointer.\r
4151 String - The NULL-terminated Unicode string to be displayed on the output\r
4152 device(s). All output devices must also support the Unicode\r
4153 drawing defined in this file.\r
4154\r
4155 Returns:\r
4156 EFI_SUCCESS - The string was output to the device.\r
4157 EFI_DEVICE_ERROR - The device reported an error while attempting to output\r
4158 the text.\r
4159 EFI_UNSUPPORTED - The output device's mode is not currently in a\r
4160 defined text mode.\r
4161 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the\r
4162 characters in the Unicode string could not be\r
4163 rendered and were skipped.\r
4164\r
4165--*/\r
4166{\r
4167 EFI_STATUS Status;\r
4168 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4169 UINTN Index;\r
4170 UINTN BackSpaceCount;\r
4171 EFI_STATUS ReturnStatus;\r
4172 CHAR16 *TargetString;\r
4173\r
4174 This->SetAttribute (This, This->Mode->Attribute);\r
4175\r
4176 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4177\r
4178 BackSpaceCount = 0;\r
4179 for (TargetString = WString; *TargetString; TargetString++) {\r
4180 if (*TargetString == CHAR_BACKSPACE) {\r
4181 BackSpaceCount++;\r
4182 }\r
4183\r
4184 }\r
4185\r
4186 if (BackSpaceCount == 0) {\r
4187 TargetString = WString;\r
4188 } else {\r
4189 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
4190 StrCpy (TargetString, WString);\r
4191 }\r
4192 //\r
4193 // return the worst status met\r
4194 //\r
4195 Status = DevNullTextOutOutputString (Private, TargetString);\r
4196 if (EFI_ERROR (Status)) {\r
4197 ReturnStatus = Status;\r
4198 }\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 Status = Private->TextOutList[Index].TextOut->OutputString (\r
4204 Private->TextOutList[Index].TextOut,\r
4205 TargetString\r
4206 );\r
4207 if (EFI_ERROR (Status)) {\r
4208 ReturnStatus = Status;\r
4209 }\r
4210 }\r
4211 }\r
4212\r
4213 if (BackSpaceCount) {\r
4214 FreePool (TargetString);\r
4215 }\r
4216\r
4217 return ReturnStatus;\r
4218}\r
4219\r
4220EFI_STATUS\r
4221EFIAPI\r
4222ConSplitterTextOutTestString (\r
4223 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4224 IN CHAR16 *WString\r
4225 )\r
4226/*++\r
4227\r
4228 Routine Description:\r
4229 Verifies that all characters in a Unicode string can be output to the\r
4230 target device.\r
4231\r
4232 Arguments:\r
4233 This - Protocol instance pointer.\r
4234 String - The NULL-terminated Unicode string to be examined for the output\r
4235 device(s).\r
4236\r
4237 Returns:\r
4238 EFI_SUCCESS - The device(s) are capable of rendering the output string.\r
4239 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be\r
4240 rendered by one or more of the output devices mapped\r
4241 by the EFI handle.\r
4242\r
4243--*/\r
4244{\r
4245 EFI_STATUS Status;\r
4246 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4247 UINTN Index;\r
4248 EFI_STATUS ReturnStatus;\r
4249\r
4250 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4251\r
4252 //\r
4253 // return the worst status met\r
4254 //\r
4255 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4256 if (Private->TextOutList[Index].TextOutEnabled) {\r
4257 Status = Private->TextOutList[Index].TextOut->TestString (\r
4258 Private->TextOutList[Index].TextOut,\r
4259 WString\r
4260 );\r
4261 if (EFI_ERROR (Status)) {\r
4262 ReturnStatus = Status;\r
4263 }\r
4264 }\r
4265 }\r
4266 //\r
4267 // There is no DevNullTextOutTestString () since a Unicode buffer would\r
4268 // always return EFI_SUCCESS.\r
4269 // ReturnStatus will be EFI_SUCCESS if no consoles are present\r
4270 //\r
4271 return ReturnStatus;\r
4272}\r
4273\r
4274EFI_STATUS\r
4275EFIAPI\r
4276ConSplitterTextOutQueryMode (\r
4277 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4278 IN UINTN ModeNumber,\r
4279 OUT UINTN *Columns,\r
4280 OUT UINTN *Rows\r
4281 )\r
4282/*++\r
4283\r
4284 Routine Description:\r
4285 Returns information for an available text mode that the output device(s)\r
4286 supports.\r
4287\r
4288 Arguments:\r
4289 This - Protocol instance pointer.\r
4290 ModeNumber - The mode number to return information on.\r
4291 Columns, Rows - Returns the geometry of the text output device for the\r
4292 requested ModeNumber.\r
4293\r
4294 Returns:\r
4295 EFI_SUCCESS - The requested mode information was returned.\r
4296 EFI_DEVICE_ERROR - The device had an error and could not\r
4297 complete the request.\r
4298 EFI_UNSUPPORTED - The mode number was not valid.\r
4299\r
4300--*/\r
4301{\r
4302 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4303\r
4304 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4305\r
4306 //\r
4307 // Check whether param ModeNumber is valid.\r
4308 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
4309 //\r
4310 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
4311 return EFI_UNSUPPORTED;\r
4312 }\r
4313\r
4314 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
4315 return EFI_UNSUPPORTED;\r
4316 }\r
4317\r
4318 *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
4319 *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
4320\r
4321 if (*Columns <= 0 && *Rows <= 0) {\r
4322 return EFI_UNSUPPORTED;\r
4323\r
4324 }\r
4325\r
4326 return EFI_SUCCESS;\r
4327}\r
4328\r
4329EFI_STATUS\r
4330EFIAPI\r
4331ConSplitterTextOutSetMode (\r
4332 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4333 IN UINTN ModeNumber\r
4334 )\r
4335/*++\r
4336\r
4337 Routine Description:\r
4338 Sets the output device(s) to a specified mode.\r
4339\r
4340 Arguments:\r
4341 This - Protocol instance pointer.\r
4342 ModeNumber - The mode number to set.\r
4343\r
4344 Returns:\r
4345 EFI_SUCCESS - The requested text mode was set.\r
4346 EFI_DEVICE_ERROR - The device had an error and\r
4347 could not complete the request.\r
4348 EFI_UNSUPPORTED - The mode number was not valid.\r
4349\r
4350--*/\r
4351{\r
4352 EFI_STATUS Status;\r
4353 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4354 UINTN Index;\r
4355 INT32 *TextOutModeMap;\r
4356 EFI_STATUS ReturnStatus;\r
4357\r
4358 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4359\r
4360 //\r
4361 // Check whether param ModeNumber is valid.\r
4362 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
4363 //\r
4364 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
4365 return EFI_UNSUPPORTED;\r
4366 }\r
4367\r
4368 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
4369 return EFI_UNSUPPORTED;\r
4370 }\r
4371 //\r
4372 // If the mode is being set to the curent mode, then just clear the screen and return.\r
4373 //\r
4374 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {\r
4375 return ConSplitterTextOutClearScreen (This);\r
4376 }\r
4377 //\r
4378 // return the worst status met\r
4379 //\r
4380 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4381 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4382\r
4383 if (Private->TextOutList[Index].TextOutEnabled) {\r
4384 Status = Private->TextOutList[Index].TextOut->SetMode (\r
4385 Private->TextOutList[Index].TextOut,\r
4386 TextOutModeMap[Index]\r
4387 );\r
4388 //\r
4389 // If this console device is based on a UGA device, then sync up the bitmap from\r
4390 // the UGA splitter and reclear the text portion of the display in the new mode.\r
4391 //\r
4392 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
4393 Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
4394 }\r
4395\r
4396 if (EFI_ERROR (Status)) {\r
4397 ReturnStatus = Status;\r
4398 }\r
4399 }\r
4400 }\r
4401 //\r
4402 // The DevNull Console will support any possible mode as it allocates memory\r
4403 //\r
4404 Status = DevNullTextOutSetMode (Private, ModeNumber);\r
4405 if (EFI_ERROR (Status)) {\r
4406 ReturnStatus = Status;\r
4407 }\r
4408\r
4409 return ReturnStatus;\r
4410}\r
4411\r
4412EFI_STATUS\r
4413EFIAPI\r
4414ConSplitterTextOutSetAttribute (\r
4415 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4416 IN UINTN Attribute\r
4417 )\r
4418/*++\r
4419\r
4420 Routine Description:\r
4421 Sets the background and foreground colors for the OutputString () and\r
4422 ClearScreen () functions.\r
4423\r
4424 Arguments:\r
4425 This - Protocol instance pointer.\r
4426 Attribute - The attribute to set. Bits 0..3 are the foreground color, and\r
4427 bits 4..6 are the background color. All other bits are undefined\r
4428 and must be zero. The valid Attributes are defined in this file.\r
4429\r
4430 Returns:\r
4431 EFI_SUCCESS - The attribute was set.\r
4432 EFI_DEVICE_ERROR - The device had an error and\r
4433 could not complete the request.\r
4434 EFI_UNSUPPORTED - The attribute requested is not defined.\r
4435\r
4436--*/\r
4437{\r
4438 EFI_STATUS Status;\r
4439 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4440 UINTN Index;\r
4441 EFI_STATUS ReturnStatus;\r
4442\r
4443 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4444\r
4445 //\r
4446 // Check whether param Attribute is valid.\r
4447 //\r
4448 if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {\r
4449 return EFI_UNSUPPORTED;\r
4450 }\r
4451\r
4452 //\r
4453 // return the worst status met\r
4454 //\r
4455 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4456\r
4457 if (Private->TextOutList[Index].TextOutEnabled) {\r
4458 Status = Private->TextOutList[Index].TextOut->SetAttribute (\r
4459 Private->TextOutList[Index].TextOut,\r
4460 Attribute\r
4461 );\r
4462 if (EFI_ERROR (Status)) {\r
4463 ReturnStatus = Status;\r
4464 }\r
4465 }\r
4466 }\r
4467\r
4468 Private->TextOutMode.Attribute = (INT32) Attribute;\r
4469\r
4470 return ReturnStatus;\r
4471}\r
4472\r
4473EFI_STATUS\r
4474EFIAPI\r
4475ConSplitterTextOutClearScreen (\r
4476 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
4477 )\r
4478/*++\r
4479\r
4480 Routine Description:\r
4481 Clears the output device(s) display to the currently selected background\r
4482 color.\r
4483\r
4484 Arguments:\r
4485 This - Protocol instance pointer.\r
4486\r
4487 Returns:\r
4488 EFI_SUCCESS - The operation completed successfully.\r
4489 EFI_DEVICE_ERROR - The device had an error and\r
4490 could not complete the request.\r
4491 EFI_UNSUPPORTED - The output device is not in a valid text mode.\r
4492\r
4493--*/\r
4494{\r
4495 EFI_STATUS Status;\r
4496 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4497 UINTN Index;\r
4498 EFI_STATUS ReturnStatus;\r
4499\r
4500 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4501\r
4502 //\r
4503 // return the worst status met\r
4504 //\r
4505 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4506\r
4507 if (Private->TextOutList[Index].TextOutEnabled) {\r
4508 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
4509 if (EFI_ERROR (Status)) {\r
4510 ReturnStatus = Status;\r
4511 }\r
4512 }\r
4513 }\r
4514\r
4515 Status = DevNullTextOutClearScreen (Private);\r
4516 if (EFI_ERROR (Status)) {\r
4517 ReturnStatus = Status;\r
4518 }\r
4519\r
4520 return ReturnStatus;\r
4521}\r
4522\r
4523EFI_STATUS\r
4524EFIAPI\r
4525ConSplitterTextOutSetCursorPosition (\r
4526 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4527 IN UINTN Column,\r
4528 IN UINTN Row\r
4529 )\r
4530/*++\r
4531\r
4532 Routine Description:\r
4533 Sets the current coordinates of the cursor position\r
4534\r
4535 Arguments:\r
4536 This - Protocol instance pointer.\r
4537 Column, Row - the position to set the cursor to. Must be greater than or\r
4538 equal to zero and less than the number of columns and rows\r
4539 by QueryMode ().\r
4540\r
4541 Returns:\r
4542 EFI_SUCCESS - The operation completed successfully.\r
4543 EFI_DEVICE_ERROR - The device had an error and\r
4544 could not complete the request.\r
4545 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the\r
4546 cursor position is invalid for the current mode.\r
4547\r
4548--*/\r
4549{\r
4550 EFI_STATUS Status;\r
4551 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4552 UINTN Index;\r
4553 EFI_STATUS ReturnStatus;\r
4554 UINTN MaxColumn;\r
4555 UINTN MaxRow;\r
de8fe2c2 4556 INT32 *TextOutModeMap;\r
4557 INT32 ModeNumber;\r
4558 INT32 CurrentMode;\r
95276127 4559\r
4560 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
de8fe2c2 4561 TextOutModeMap = NULL;\r
4562 ModeNumber = Private->TextOutMode.Mode;\r
7a5064ce 4563\r
de8fe2c2 4564 //\r
4565 // Get current MaxColumn and MaxRow from intersection map\r
4566 //\r
4567 if (Private->TextOutModeMap != NULL) {\r
4568 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4569 CurrentMode = *TextOutModeMap;\r
4570 } else {\r
4571 CurrentMode = ModeNumber;\r
4572 }\r
7a5064ce 4573\r
de8fe2c2 4574 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;\r
4575 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;\r
95276127 4576\r
4577 if (Column >= MaxColumn || Row >= MaxRow) {\r
4578 return EFI_UNSUPPORTED;\r
4579 }\r
4580 //\r
4581 // return the worst status met\r
4582 //\r
4583 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4584\r
4585 if (Private->TextOutList[Index].TextOutEnabled) {\r
4586 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (\r
4587 Private->TextOutList[Index].TextOut,\r
4588 Column,\r
4589 Row\r
4590 );\r
4591 if (EFI_ERROR (Status)) {\r
4592 ReturnStatus = Status;\r
4593 }\r
4594 }\r
4595 }\r
4596\r
4597 DevNullTextOutSetCursorPosition (Private, Column, Row);\r
4598\r
4599 return ReturnStatus;\r
4600}\r
4601\r
4602EFI_STATUS\r
4603EFIAPI\r
4604ConSplitterTextOutEnableCursor (\r
4605 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4606 IN BOOLEAN Visible\r
4607 )\r
4608/*++\r
4609\r
4610 Routine Description:\r
4611 Makes the cursor visible or invisible\r
4612\r
4613 Arguments:\r
4614 This - Protocol instance pointer.\r
4615 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is\r
4616 set to be invisible.\r
4617\r
4618 Returns:\r
4619 EFI_SUCCESS - The operation completed successfully.\r
4620 EFI_DEVICE_ERROR - The device had an error and could not complete the\r
4621 request, or the device does not support changing\r
4622 the cursor mode.\r
4623 EFI_UNSUPPORTED - The output device is not in a valid text mode.\r
4624\r
4625--*/\r
4626{\r
4627 EFI_STATUS Status;\r
4628 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4629 UINTN Index;\r
4630 EFI_STATUS ReturnStatus;\r
4631\r
4632 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4633\r
4634 //\r
4635 // return the worst status met\r
4636 //\r
4637 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4638\r
4639 if (Private->TextOutList[Index].TextOutEnabled) {\r
4640 Status = Private->TextOutList[Index].TextOut->EnableCursor (\r
4641 Private->TextOutList[Index].TextOut,\r
4642 Visible\r
4643 );\r
4644 if (EFI_ERROR (Status)) {\r
4645 ReturnStatus = Status;\r
4646 }\r
4647 }\r
4648 }\r
4649\r
4650 DevNullTextOutEnableCursor (Private, Visible);\r
4651\r
4652 return ReturnStatus;\r
4653}\r