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