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