]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
ECC clean up.
[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
1752 UINTN NewSize;\r
1753 UINTN OldSize;\r
1754 VOID *Ptr;\r
1755\r
1756 //\r
1757 // grow the buffer to new buffer size,\r
1758 // copy the old buffer's content to the new-size buffer,\r
1759 // then free the old buffer.\r
1760 //\r
1761 OldSize = *Count * SizeOfCount;\r
1762 *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
1763 NewSize = *Count * SizeOfCount;\r
1764\r
1765 Ptr = AllocateZeroPool (NewSize);\r
1766 if (Ptr == NULL) {\r
1767 return EFI_OUT_OF_RESOURCES;\r
1768 }\r
1769\r
1770 CopyMem (Ptr, *Buffer, OldSize);\r
1771\r
1772 if (*Buffer != NULL) {\r
1773 FreePool (*Buffer);\r
1774 }\r
1775\r
1776 *Buffer = Ptr;\r
1777\r
1778 return EFI_SUCCESS;\r
1779}\r
1780\r
a4d608d1 1781\r
1782/**\r
415df2a3 1783 Add Text Input Device in Consplitter Text Input list.\r
a4d608d1 1784\r
415df2a3 1785 @param Private Text In Splitter pointer.\r
1786 @param TextIn Simple Text Input protocol pointer.\r
a4d608d1 1787\r
415df2a3 1788 @retval EFI_SUCCESS Text Input Device added successfully.\r
1789 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
a4d608d1 1790\r
1791**/\r
95276127 1792EFI_STATUS\r
1793ConSplitterTextInAddDevice (\r
1794 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1795 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1796 )\r
95276127 1797{\r
1798 EFI_STATUS Status;\r
1799\r
1800 //\r
1801 // If the Text In List is full, enlarge it by calling growbuffer().\r
1802 //\r
1803 if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {\r
1804 Status = ConSplitterGrowBuffer (\r
1805 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
1806 &Private->TextInListCount,\r
1807 (VOID **) &Private->TextInList\r
1808 );\r
1809 if (EFI_ERROR (Status)) {\r
1810 return EFI_OUT_OF_RESOURCES;\r
1811 }\r
1812 }\r
1813 //\r
1814 // Add the new text-in device data structure into the Text In List.\r
1815 //\r
1816 Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;\r
1817 Private->CurrentNumberOfConsoles++;\r
1818\r
1819 //\r
1820 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1821 //\r
1822 gBS->CheckEvent (TextIn->WaitForKey);\r
1823\r
1824 return EFI_SUCCESS;\r
1825}\r
1826\r
a4d608d1 1827\r
1828/**\r
415df2a3 1829 Remove Simple Text Device in Consplitter Absolute Pointer list.\r
a4d608d1 1830\r
415df2a3 1831 @param Private Text In Splitter pointer.\r
1832 @param TextIn Simple Text protocol pointer.\r
a4d608d1 1833\r
415df2a3 1834 @retval EFI_SUCCESS Simple Text Device removed successfully.\r
1835 @retval EFI_NOT_FOUND No Simple Text Device found.\r
a4d608d1 1836\r
1837**/\r
95276127 1838EFI_STATUS\r
1839ConSplitterTextInDeleteDevice (\r
1840 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1841 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1842 )\r
95276127 1843{\r
1844 UINTN Index;\r
1845 //\r
1846 // Remove the specified text-in device data structure from the Text In List,\r
1847 // and rearrange the remaining data structures in the Text In List.\r
1848 //\r
1849 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
1850 if (Private->TextInList[Index] == TextIn) {\r
1851 for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
1852 Private->TextInList[Index] = Private->TextInList[Index + 1];\r
1853 }\r
1854\r
1855 Private->CurrentNumberOfConsoles--;\r
1856 return EFI_SUCCESS;\r
1857 }\r
1858 }\r
1859\r
1860 return EFI_NOT_FOUND;\r
1861}\r
1862\r
415df2a3 1863/**\r
1864 Add Text Input Ex Device in Consplitter Text Input Ex list.\r
1865\r
1866 @param Private Text In Splitter pointer.\r
1867 @param TextInEx Simple Text Ex Input protocol pointer.\r
1868\r
1869 @retval EFI_SUCCESS Text Input Ex Device added successfully.\r
1870 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
1871\r
1872**/\r
66aa04e4 1873EFI_STATUS\r
1874ConSplitterTextInExAddDevice (\r
1875 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1876 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
1877 )\r
1878{\r
1879 EFI_STATUS Status;\r
1880\r
1881 //\r
1882 // If the TextInEx List is full, enlarge it by calling growbuffer().\r
1883 //\r
1884 if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
1885 Status = ConSplitterGrowBuffer (\r
1886 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
1887 &Private->TextInExListCount,\r
1888 (VOID **) &Private->TextInExList\r
1889 );\r
1890 if (EFI_ERROR (Status)) {\r
1891 return EFI_OUT_OF_RESOURCES;\r
1892 }\r
1893 }\r
1894 //\r
1895 // Add the new text-in device data structure into the Text In List.\r
1896 //\r
1897 Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
1898 Private->CurrentNumberOfExConsoles++;\r
1899\r
1900 //\r
1901 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1902 //\r
1903 gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
1904\r
1905 return EFI_SUCCESS;\r
1906}\r
1907\r
415df2a3 1908/**\r
1909 Remove Simple Text Ex Device in Consplitter Absolute Pointer list.\r
1910\r
1911 @param Private Text In Splitter pointer.\r
1912 @param TextInEx Simple Text Ex protocol pointer.\r
1913\r
1914 @retval EFI_SUCCESS Simple Text Ex Device removed successfully.\r
1915 @retval EFI_NOT_FOUND No Simple Text Ex Device found.\r
1916\r
1917**/\r
66aa04e4 1918EFI_STATUS\r
1919ConSplitterTextInExDeleteDevice (\r
1920 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1921 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
1922 )\r
1923{\r
1924 UINTN Index;\r
1925 //\r
1926 // Remove the specified text-in device data structure from the Text In List,\r
1927 // and rearrange the remaining data structures in the Text In List.\r
1928 //\r
1929 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
1930 if (Private->TextInExList[Index] == TextInEx) {\r
1931 for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
1932 Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
1933 }\r
1934\r
1935 Private->CurrentNumberOfExConsoles--;\r
1936 return EFI_SUCCESS;\r
1937 }\r
1938 }\r
1939\r
1940 return EFI_NOT_FOUND;\r
1941}\r
1942\r
a4d608d1 1943\r
1944/**\r
415df2a3 1945 Add Simple Pointer Device in Consplitter Simple Pointer list.\r
a4d608d1 1946\r
415df2a3 1947 @param Private Text In Splitter pointer.\r
1948 @param SimplePointer Simple Pointer protocol pointer.\r
a4d608d1 1949\r
415df2a3 1950 @retval EFI_SUCCESS Simple Pointer Device added successfully.\r
1951 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
a4d608d1 1952\r
1953**/\r
95276127 1954EFI_STATUS\r
1955ConSplitterSimplePointerAddDevice (\r
1956 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1957 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1958 )\r
95276127 1959{\r
1960 EFI_STATUS Status;\r
1961\r
1962 //\r
1963 // If the Text In List is full, enlarge it by calling growbuffer().\r
1964 //\r
1965 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {\r
1966 Status = ConSplitterGrowBuffer (\r
1967 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
1968 &Private->PointerListCount,\r
1969 (VOID **) &Private->PointerList\r
1970 );\r
1971 if (EFI_ERROR (Status)) {\r
1972 return EFI_OUT_OF_RESOURCES;\r
1973 }\r
1974 }\r
1975 //\r
1976 // Add the new text-in device data structure into the Text In List.\r
1977 //\r
1978 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;\r
1979 Private->CurrentNumberOfPointers++;\r
1980 return EFI_SUCCESS;\r
1981}\r
1982\r
a4d608d1 1983\r
1984/**\r
415df2a3 1985 Remove Simple Pointer Device in Consplitter Absolute Pointer list.\r
a4d608d1 1986\r
415df2a3 1987 @param Private Text In Splitter pointer.\r
1988 @param SimplePointer Simple Pointer protocol pointer.\r
a4d608d1 1989\r
415df2a3 1990 @retval EFI_SUCCESS Simple Pointer Device removed successfully.\r
1991 @retval EFI_NOT_FOUND No Simple Pointer Device found.\r
a4d608d1 1992\r
1993**/\r
95276127 1994EFI_STATUS\r
1995ConSplitterSimplePointerDeleteDevice (\r
1996 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1997 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1998 )\r
95276127 1999{\r
2000 UINTN Index;\r
2001 //\r
2002 // Remove the specified text-in device data structure from the Text In List,\r
2003 // and rearrange the remaining data structures in the Text In List.\r
2004 //\r
2005 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
2006 if (Private->PointerList[Index] == SimplePointer) {\r
2007 for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
2008 Private->PointerList[Index] = Private->PointerList[Index + 1];\r
2009 }\r
2010\r
2011 Private->CurrentNumberOfPointers--;\r
2012 return EFI_SUCCESS;\r
2013 }\r
2014 }\r
2015\r
2016 return EFI_NOT_FOUND;\r
2017}\r
2018\r
a4d608d1 2019\r
2020/**\r
415df2a3 2021 Add Absolute Pointer Device in Consplitter Absolute Pointer list.\r
a4d608d1 2022\r
415df2a3 2023 @param Private Text In Splitter pointer.\r
2024 @param AbsolutePointer Absolute Pointer protocol pointer.\r
a4d608d1 2025\r
415df2a3 2026 @retval EFI_SUCCESS Absolute Pointer Device added successfully.\r
2027 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
a4d608d1 2028\r
2029**/\r
8ae0b360 2030EFI_STATUS\r
2031ConSplitterAbsolutePointerAddDevice (\r
2032 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2033 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer\r
2034 )\r
8ae0b360 2035{\r
2036 EFI_STATUS Status;\r
2037\r
2038 //\r
2039 // If the Absolute Pointer List is full, enlarge it by calling growbuffer().\r
2040 //\r
2041 if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) {\r
2042 Status = ConSplitterGrowBuffer (\r
2043 sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *),\r
2044 &Private->AbsolutePointerListCount,\r
2045 (VOID **) &Private->AbsolutePointerList\r
2046 );\r
2047 if (EFI_ERROR (Status)) {\r
2048 return EFI_OUT_OF_RESOURCES;\r
2049 }\r
2050 }\r
2051 //\r
2052 // Add the new text-in device data structure into the Text In List.\r
2053 //\r
2054 Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer;\r
2055 Private->CurrentNumberOfAbsolutePointers++;\r
2056 return EFI_SUCCESS;\r
2057}\r
2058\r
a4d608d1 2059\r
2060/**\r
415df2a3 2061 Remove Absolute Pointer Device in Consplitter Absolute Pointer list.\r
a4d608d1 2062\r
415df2a3 2063 @param Private Text In Splitter pointer.\r
2064 @param AbsolutePointer Absolute Pointer protocol pointer.\r
a4d608d1 2065\r
415df2a3 2066 @retval EFI_SUCCESS Absolute Pointer Device removed successfully.\r
2067 @retval EFI_NOT_FOUND No Absolute Pointer Device found.\r
a4d608d1 2068\r
2069**/\r
8ae0b360 2070EFI_STATUS\r
2071ConSplitterAbsolutePointerDeleteDevice (\r
2072 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2073 IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer\r
2074 )\r
8ae0b360 2075{\r
2076 UINTN Index;\r
2077 //\r
2078 // Remove the specified text-in device data structure from the Text In List,\r
2079 // and rearrange the remaining data structures in the Text In List.\r
2080 //\r
2081 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
2082 if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
2083 for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
2084 Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
2085 }\r
2086\r
2087 Private->CurrentNumberOfAbsolutePointers--;\r
2088 return EFI_SUCCESS;\r
2089 }\r
2090 }\r
2091\r
2092 return EFI_NOT_FOUND;\r
2093}\r
2094\r
33019a71 2095/**\r
2096 Reallocate Text Out mode map.\r
2097\r
2098 @param Private Consplitter Text Out pointer.\r
2099\r
2100 @retval EFI_SUCCESS Buffer size has grown\r
2101 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
2102\r
2103**/\r
a4d608d1 2104EFI_STATUS\r
2105ConSplitterGrowMapTable (\r
2106 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
2107 )\r
95276127 2108{\r
2109 UINTN Size;\r
2110 UINTN NewSize;\r
2111 UINTN TotalSize;\r
2112 INT32 *TextOutModeMap;\r
2113 INT32 *OldTextOutModeMap;\r
2114 INT32 *SrcAddress;\r
2115 INT32 Index;\r
2116\r
2117 NewSize = Private->TextOutListCount * sizeof (INT32);\r
2118 OldTextOutModeMap = Private->TextOutModeMap;\r
2119 TotalSize = NewSize * Private->TextOutQueryDataCount;\r
2120\r
2121 TextOutModeMap = AllocateZeroPool (TotalSize);\r
2122 if (TextOutModeMap == NULL) {\r
2123 return EFI_OUT_OF_RESOURCES;\r
2124 }\r
2125\r
2126 SetMem (TextOutModeMap, TotalSize, 0xFF);\r
2127 Private->TextOutModeMap = TextOutModeMap;\r
2128\r
2129 //\r
2130 // If TextOutList has been enlarged, need to realloc the mode map table\r
2131 // The mode map table is regarded as a two dimension array.\r
2132 //\r
2133 // Old New\r
2134 // 0 ---------> TextOutListCount ----> TextOutListCount\r
2135 // | -------------------------------------------\r
2136 // | | | |\r
2137 // | | | |\r
2138 // | | | |\r
2139 // | | | |\r
2140 // | | | |\r
2141 // \/ | | |\r
2142 // -------------------------------------------\r
2143 // QueryDataCount\r
2144 //\r
2145 if (OldTextOutModeMap != NULL) {\r
2146\r
2147 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
2148 Index = 0;\r
2149 SrcAddress = OldTextOutModeMap;\r
2150\r
2151 //\r
2152 // Copy the old data to the new one\r
2153 //\r
2154 while (Index < Private->TextOutMode.MaxMode) {\r
2155 CopyMem (TextOutModeMap, SrcAddress, Size);\r
2156 TextOutModeMap += NewSize;\r
2157 SrcAddress += Size;\r
2158 Index++;\r
2159 }\r
2160 //\r
2161 // Free the old buffer\r
2162 //\r
2163 FreePool (OldTextOutModeMap);\r
2164 }\r
2165\r
2166 return EFI_SUCCESS;\r
2167}\r
2168\r
a4d608d1 2169\r
2170/**\r
415df2a3 2171 Add the device's output mode to console splitter's mode list.\r
a4d608d1 2172\r
415df2a3 2173 @param Private Text Out Splitter pointer\r
2174 @param TextOut Simple Text Output protocol pointer.\r
2175 \r
2176 @retval EFI_SUCCESS Device added successfully.\r
2177 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
a4d608d1 2178\r
2179**/\r
95276127 2180EFI_STATUS\r
2181ConSplitterAddOutputMode (\r
2182 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2183 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
2184 )\r
95276127 2185{\r
2186 EFI_STATUS Status;\r
2187 INT32 MaxMode;\r
2188 INT32 Mode;\r
2189 UINTN Index;\r
2190\r
2191 MaxMode = TextOut->Mode->MaxMode;\r
2192 Private->TextOutMode.MaxMode = MaxMode;\r
2193\r
2194 //\r
2195 // Grow the buffer if query data buffer is not large enough to\r
2196 // hold all the mode supported by the first console.\r
2197 //\r
2198 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {\r
2199 Status = ConSplitterGrowBuffer (\r
2200 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
2201 &Private->TextOutQueryDataCount,\r
2202 (VOID **) &Private->TextOutQueryData\r
2203 );\r
2204 if (EFI_ERROR (Status)) {\r
2205 return EFI_OUT_OF_RESOURCES;\r
2206 }\r
2207 }\r
2208 //\r
2209 // Allocate buffer for the output mode map\r
2210 //\r
2211 Status = ConSplitterGrowMapTable (Private);\r
2212 if (EFI_ERROR (Status)) {\r
2213 return EFI_OUT_OF_RESOURCES;\r
2214 }\r
2215 //\r
2216 // As the first textout device, directly add the mode in to QueryData\r
2217 // and at the same time record the mapping between QueryData and TextOut.\r
2218 //\r
2219 Mode = 0;\r
2220 Index = 0;\r
2221 while (Mode < MaxMode) {\r
7347d5d6 2222 Status = TextOut->QueryMode (\r
2223 TextOut,\r
2224 Mode,\r
2225 &Private->TextOutQueryData[Mode].Columns,\r
2226 &Private->TextOutQueryData[Mode].Rows\r
2227 );\r
2228 //\r
2229 // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData\r
2230 // is clear to 0x0.\r
2231 //\r
2232 if ((EFI_ERROR(Status)) && (Mode == 1)) {\r
2233 Private->TextOutQueryData[Mode].Columns = 0;\r
2234 Private->TextOutQueryData[Mode].Rows = 0;\r
2235 }\r
95276127 2236 Private->TextOutModeMap[Index] = Mode;\r
2237 Mode++;\r
2238 Index += Private->TextOutListCount;\r
2239 }\r
2240\r
2241 return EFI_SUCCESS;\r
2242}\r
2243\r
7347d5d6 2244/**\r
9e604fe4 2245 Reconstruct TextOutModeMap to get intersection of modes.\r
7347d5d6 2246\r
2247 This routine reconstruct TextOutModeMap to get the intersection\r
2248 of modes for all console out devices. Because EFI/UEFI spec require\r
2249 mode 0 is 80x25, mode 1 is 80x50, this routine will not check the\r
2250 intersection for mode 0 and mode 1.\r
2251\r
a4d608d1 2252 @param TextOutModeMap Current text out mode map, begin with the mode 80x25\r
2253 @param NewlyAddedMap New text out mode map, begin with the mode 80x25\r
2254 @param MapStepSize Mode step size for one console device\r
2255 @param NewMapStepSize Mode step size for one console device\r
2256 @param MaxMode Current max text mode\r
2257 @param CurrentMode Current text mode\r
7347d5d6 2258\r
7347d5d6 2259**/\r
95276127 2260VOID\r
2261ConSplitterGetIntersection (\r
2262 IN INT32 *TextOutModeMap,\r
2263 IN INT32 *NewlyAddedMap,\r
2264 IN UINTN MapStepSize,\r
2265 IN UINTN NewMapStepSize,\r
2266 OUT INT32 *MaxMode,\r
2267 OUT INT32 *CurrentMode\r
2268 )\r
2269{\r
2270 INT32 Index;\r
2271 INT32 *CurrentMapEntry;\r
2272 INT32 *NextMapEntry;\r
2273 INT32 CurrentMaxMode;\r
2274 INT32 Mode;\r
2275\r
7347d5d6 2276 //\r
2277 // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved\r
2278 // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection\r
2279 // for mode 0 and mode 1, mode number starts from 2.\r
2280 //\r
2281 Index = 2;\r
2282 CurrentMapEntry = &TextOutModeMap[MapStepSize * 2];\r
2283 NextMapEntry = &TextOutModeMap[MapStepSize * 2];\r
2284 NewlyAddedMap = &NewlyAddedMap[NewMapStepSize * 2];\r
2285\r
95276127 2286 CurrentMaxMode = *MaxMode;\r
2287 Mode = *CurrentMode;\r
2288\r
2289 while (Index < CurrentMaxMode) {\r
2290 if (*NewlyAddedMap == -1) {\r
2291 //\r
2292 // This mode is not supported any more. Remove it. Special care\r
2293 // must be taken as this remove will also affect current mode;\r
2294 //\r
2295 if (Index == *CurrentMode) {\r
2296 Mode = -1;\r
2297 } else if (Index < *CurrentMode) {\r
2298 Mode--;\r
2299 }\r
2300 (*MaxMode)--;\r
2301 } else {\r
2302 if (CurrentMapEntry != NextMapEntry) {\r
2303 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));\r
2304 }\r
2305\r
2306 NextMapEntry += MapStepSize;\r
2307 }\r
2308\r
2309 CurrentMapEntry += MapStepSize;\r
2310 NewlyAddedMap += NewMapStepSize;\r
2311 Index++;\r
2312 }\r
2313\r
2314 *CurrentMode = Mode;\r
2315\r
2316 return ;\r
2317}\r
2318\r
a4d608d1 2319\r
2320/**\r
415df2a3 2321 Add the device's output mode to console splitter's mode list.\r
a4d608d1 2322\r
33019a71 2323 @param Private Text Out Splitter pointer.\r
415df2a3 2324 @param TextOut Simple Text Output protocol pointer.\r
2325 \r
33019a71 2326 @return None\r
a4d608d1 2327\r
2328**/\r
95276127 2329VOID\r
2330ConSplitterSyncOutputMode (\r
2331 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2332 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
2333 )\r
95276127 2334{\r
2335 INT32 CurrentMaxMode;\r
2336 INT32 Mode;\r
2337 INT32 Index;\r
2338 INT32 *TextOutModeMap;\r
2339 INT32 *MapTable;\r
3012ce5c 2340 INT32 QueryMode;\r
95276127 2341 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;\r
2342 UINTN Rows;\r
2343 UINTN Columns;\r
2344 UINTN StepSize;\r
7347d5d6 2345 EFI_STATUS Status;\r
95276127 2346\r
2347 //\r
2348 // Must make sure that current mode won't change even if mode number changes\r
2349 //\r
2350 CurrentMaxMode = Private->TextOutMode.MaxMode;\r
2351 TextOutModeMap = Private->TextOutModeMap;\r
2352 StepSize = Private->TextOutListCount;\r
2353 TextOutQueryData = Private->TextOutQueryData;\r
2354\r
2355 //\r
2356 // Query all the mode that the newly added TextOut supports\r
2357 //\r
2358 Mode = 0;\r
2359 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
2360 while (Mode < TextOut->Mode->MaxMode) {\r
7347d5d6 2361 Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
2362 if (EFI_ERROR(Status)) {\r
2363 if (Mode == 1) {\r
3012ce5c 2364 MapTable[StepSize] = Mode;\r
7347d5d6 2365 TextOutQueryData[Mode].Columns = 0;\r
2366 TextOutQueryData[Mode].Rows = 0;\r
2367 }\r
2368 Mode++;\r
2369 continue;\r
2370 }\r
95276127 2371 //\r
3012ce5c 2372 // Search the intersection map and QueryData database to see if they intersects\r
95276127 2373 //\r
2374 Index = 0;\r
2375 while (Index < CurrentMaxMode) {\r
3012ce5c 2376 QueryMode = *(TextOutModeMap + Index * StepSize);\r
2377 if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) {\r
95276127 2378 MapTable[Index * StepSize] = Mode;\r
2379 break;\r
2380 }\r
2381\r
2382 Index++;\r
2383 }\r
2384\r
2385 Mode++;\r
2386 }\r
2387 //\r
2388 // Now search the TextOutModeMap table to find the intersection of supported\r
2389 // mode between ConSplitter and the newly added device.\r
2390 //\r
2391 ConSplitterGetIntersection (\r
2392 TextOutModeMap,\r
2393 MapTable,\r
2394 StepSize,\r
2395 StepSize,\r
2396 &Private->TextOutMode.MaxMode,\r
2397 &Private->TextOutMode.Mode\r
2398 );\r
2399\r
2400 return ;\r
2401}\r
2402\r
95276127 2403\r
a4d608d1 2404/**\r
415df2a3 2405 Sync output device between ConOut and StdErr output.\r
95276127 2406\r
415df2a3 2407 @retval EFI_SUCCESS Sync implemented successfully.\r
2408 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
95276127 2409\r
a4d608d1 2410**/\r
2411EFI_STATUS\r
2412ConSplitterGetIntersectionBetweenConOutAndStrErr (\r
2413 VOID\r
2414 )\r
95276127 2415{\r
2416 UINTN ConOutNumOfConsoles;\r
2417 UINTN StdErrNumOfConsoles;\r
2418 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;\r
2419 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;\r
2420 UINTN Indexi;\r
2421 UINTN Indexj;\r
3012ce5c 2422 UINTN ConOutRows;\r
2423 UINTN ConOutColumns;\r
2424 UINTN StdErrRows;\r
2425 UINTN StdErrColumns;\r
95276127 2426 INT32 ConOutMaxMode;\r
2427 INT32 StdErrMaxMode;\r
3012ce5c 2428 INT32 ConOutMode;\r
2429 INT32 StdErrMode;\r
95276127 2430 INT32 Mode;\r
2431 INT32 Index;\r
2432 INT32 *ConOutModeMap;\r
2433 INT32 *StdErrModeMap;\r
2434 INT32 *ConOutMapTable;\r
2435 INT32 *StdErrMapTable;\r
2436 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;\r
2437 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;\r
3012ce5c 2438 UINTN ConOutStepSize;\r
2439 UINTN StdErrStepSize;\r
95276127 2440 BOOLEAN FoundTheSameTextOut;\r
2441 UINTN ConOutMapTableSize;\r
2442 UINTN StdErrMapTableSize;\r
2443\r
2444 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;\r
2445 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;\r
2446 ConOutTextOutList = mConOut.TextOutList;\r
2447 StdErrTextOutList = mStdErr.TextOutList;\r
2448\r
2449 Indexi = 0;\r
2450 FoundTheSameTextOut = FALSE;\r
2451 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {\r
2452 Indexj = 0;\r
2453 while (Indexj < StdErrNumOfConsoles) {\r
2454 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {\r
2455 FoundTheSameTextOut = TRUE;\r
2456 break;\r
2457 }\r
2458\r
2459 Indexj++;\r
2460 StdErrTextOutList++;\r
2461 }\r
2462\r
2463 Indexi++;\r
2464 ConOutTextOutList++;\r
2465 }\r
2466\r
2467 if (!FoundTheSameTextOut) {\r
2468 return EFI_SUCCESS;\r
2469 }\r
2470 //\r
2471 // Must make sure that current mode won't change even if mode number changes\r
2472 //\r
2473 ConOutMaxMode = mConOut.TextOutMode.MaxMode;\r
2474 ConOutModeMap = mConOut.TextOutModeMap;\r
3012ce5c 2475 ConOutStepSize = mConOut.TextOutListCount;\r
95276127 2476 ConOutQueryData = mConOut.TextOutQueryData;\r
2477\r
2478 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;\r
2479 StdErrModeMap = mStdErr.TextOutModeMap;\r
3012ce5c 2480 StdErrStepSize = mStdErr.TextOutListCount;\r
95276127 2481 StdErrQueryData = mStdErr.TextOutQueryData;\r
2482\r
2483 //\r
2484 // Allocate the map table and set the map table's index to -1.\r
2485 //\r
2486 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);\r
2487 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);\r
2488 if (ConOutMapTable == NULL) {\r
2489 return EFI_OUT_OF_RESOURCES;\r
2490 }\r
2491\r
2492 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);\r
2493\r
2494 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);\r
2495 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);\r
2496 if (StdErrMapTable == NULL) {\r
2497 return EFI_OUT_OF_RESOURCES;\r
2498 }\r
2499\r
2500 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);\r
2501\r
2502 //\r
2503 // Find the intersection of the two set of modes. If they actually intersect, the\r
2504 // correponding entry in the map table is set to 1.\r
2505 //\r
2506 Mode = 0;\r
2507 while (Mode < ConOutMaxMode) {\r
2508 //\r
3012ce5c 2509 // Search the intersection map and QueryData database to see if they intersect\r
95276127 2510 //\r
3012ce5c 2511 Index = 0;\r
2512 ConOutMode = *(ConOutModeMap + Mode * ConOutStepSize);\r
2513 ConOutRows = ConOutQueryData[ConOutMode].Rows;\r
2514 ConOutColumns = ConOutQueryData[ConOutMode].Columns;\r
95276127 2515 while (Index < StdErrMaxMode) {\r
3012ce5c 2516 StdErrMode = *(StdErrModeMap + Index * StdErrStepSize);\r
2517 StdErrRows = StdErrQueryData[StdErrMode].Rows;\r
2518 StdErrColumns = StdErrQueryData[StdErrMode].Columns;\r
2519 if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) {\r
95276127 2520 ConOutMapTable[Mode] = 1;\r
2521 StdErrMapTable[Index] = 1;\r
2522 break;\r
2523 }\r
2524\r
2525 Index++;\r
2526 }\r
2527\r
2528 Mode++;\r
2529 }\r
2530 //\r
2531 // Now search the TextOutModeMap table to find the intersection of supported\r
2532 // mode between ConSplitter and the newly added device.\r
2533 //\r
2534 ConSplitterGetIntersection (\r
2535 ConOutModeMap,\r
2536 ConOutMapTable,\r
2537 mConOut.TextOutListCount,\r
2538 1,\r
2539 &(mConOut.TextOutMode.MaxMode),\r
2540 &(mConOut.TextOutMode.Mode)\r
2541 );\r
2542 if (mConOut.TextOutMode.Mode < 0) {\r
2543 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);\r
2544 }\r
2545\r
2546 ConSplitterGetIntersection (\r
2547 StdErrModeMap,\r
2548 StdErrMapTable,\r
2549 mStdErr.TextOutListCount,\r
2550 1,\r
2551 &(mStdErr.TextOutMode.MaxMode),\r
2552 &(mStdErr.TextOutMode.Mode)\r
2553 );\r
2554 if (mStdErr.TextOutMode.Mode < 0) {\r
2555 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);\r
2556 }\r
2557\r
2558 FreePool (ConOutMapTable);\r
2559 FreePool (StdErrMapTable);\r
2560\r
2561 return EFI_SUCCESS;\r
2562}\r
2563\r
a4d608d1 2564\r
2565/**\r
415df2a3 2566 Add GOP or UGA output mode into Consplitter Text Out list.\r
a4d608d1 2567\r
415df2a3 2568 @param Private Text Out Splitter pointer.\r
2569 @param GraphicsOutput Graphics Output protocol pointer.\r
2570 @param UgaDraw UGA Draw protocol pointer.\r
a4d608d1 2571\r
415df2a3 2572 @retval EFI_SUCCESS Output mode added successfully.\r
2573 @retval other Failed to add output mode.\r
a4d608d1 2574\r
2575**/\r
95276127 2576EFI_STATUS\r
2577ConSplitterAddGraphicsOutputMode (\r
2578 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2579 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2580 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2581 )\r
95276127 2582{\r
2583 EFI_STATUS Status;\r
2584 UINTN Index;\r
3012ce5c 2585 UINTN CurrentIndex;\r
aec072ad 2586 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;\r
95276127 2587 UINTN SizeOfInfo;\r
2588 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
2589 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;\r
aec072ad 2590 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer;\r
2591 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode;\r
95276127 2592 UINTN NumberIndex;\r
2593 BOOLEAN Match;\r
aec072ad 2594 BOOLEAN AlreadyExist;\r
3012ce5c 2595 UINT32 UgaHorizontalResolution;\r
2596 UINT32 UgaVerticalResolution;\r
2597 UINT32 UgaColorDepth;\r
2598 UINT32 UgaRefreshRate;\r
95276127 2599\r
2600 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2601 return EFI_UNSUPPORTED;\r
2602 }\r
2603\r
2604 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
2605\r
aec072ad 2606 Index = 0;\r
3012ce5c 2607 CurrentIndex = 0;\r
aec072ad 2608\r
2609 if (Private->CurrentNumberOfUgaDraw != 0) {\r
2610 //\r
2611 // If any UGA device has already been added, then there is no need to\r
2612 // calculate intersection of display mode of different GOP/UGA device,\r
2613 // since only one display mode will be exported (i.e. user-defined mode)\r
2614 //\r
2615 goto Done;\r
2616 }\r
2617\r
95276127 2618 if (GraphicsOutput != NULL) {\r
2619 if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
2620 //\r
2621 // This is the first Graphics Output device added\r
2622 //\r
2623 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;\r
2624 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;\r
2625 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);\r
2626 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;\r
2627 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;\r
2628 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;\r
2629\r
2630 //\r
2631 // Allocate resource for the private mode buffer\r
2632 //\r
aec072ad 2633 ModeBuffer = AllocatePool (GraphicsOutput->Mode->SizeOfInfo * GraphicsOutput->Mode->MaxMode);\r
95276127 2634 if (ModeBuffer == NULL) {\r
2635 return EFI_OUT_OF_RESOURCES;\r
2636 }\r
2637 FreePool (Private->GraphicsOutputModeBuffer);\r
2638 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2639\r
2640 //\r
2641 // Store all supported display modes to the private mode buffer\r
2642 //\r
2643 Mode = ModeBuffer;\r
2644 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {\r
2645 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);\r
2646 if (EFI_ERROR (Status)) {\r
2647 return Status;\r
2648 }\r
aec072ad 2649 CopyMem (Mode, Info, SizeOfInfo);\r
95276127 2650 Mode++;\r
2651 FreePool (Info);\r
2652 }\r
2653 } else {\r
2654 //\r
2655 // Check intersection of display mode\r
2656 //\r
aec072ad 2657 ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode);\r
95276127 2658 if (ModeBuffer == NULL) {\r
2659 return EFI_OUT_OF_RESOURCES;\r
2660 }\r
2661\r
2662 MatchedMode = ModeBuffer;\r
2663 Mode = &Private->GraphicsOutputModeBuffer[0];\r
2664 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2665 Match = FALSE;\r
2666\r
2667 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {\r
2668 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
2669 if (EFI_ERROR (Status)) {\r
2670 return Status;\r
2671 }\r
2672 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
aec072ad 2673 (Info->VerticalResolution == Mode->VerticalResolution)) {\r
95276127 2674 Match = TRUE;\r
2675 FreePool (Info);\r
2676 break;\r
2677 }\r
2678 FreePool (Info);\r
2679 }\r
2680\r
2681 if (Match) {\r
aec072ad 2682 AlreadyExist = FALSE;\r
2683\r
2684 for (Info = ModeBuffer; Info < MatchedMode; Info++) {\r
2685 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
2686 (Info->VerticalResolution == Mode->VerticalResolution)) {\r
2687 AlreadyExist = TRUE;\r
2688 break;\r
2689 }\r
2690 }\r
2691\r
2692 if (!AlreadyExist) {\r
2693 CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
2694\r
2695 //\r
2696 // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly\r
2697 //\r
2698 MatchedMode->Version = 0;\r
2699 MatchedMode->PixelFormat = PixelBltOnly;\r
2700 ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2701\r
2702 MatchedMode++;\r
2703 }\r
95276127 2704 }\r
2705\r
2706 Mode++;\r
2707 }\r
2708\r
2709 //\r
2710 // Drop the old mode buffer, assign it to a new one\r
2711 //\r
2712 FreePool (Private->GraphicsOutputModeBuffer);\r
2713 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2714\r
2715 //\r
2716 // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
2717 //\r
aec072ad 2718 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
95276127 2719 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2720 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2721 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1be0dda6 2722 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;\r
95276127 2723 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2724 }\r
2725\r
2726 //\r
3012ce5c 2727 // Graphics console driver can ensure the same mode for all GOP devices\r
95276127 2728 //\r
2729 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2730 Mode = &Private->GraphicsOutputModeBuffer[Index];\r
3012ce5c 2731 if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) &&\r
2732 (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) {\r
2733 CurrentIndex = Index;\r
95276127 2734 break;\r
2735 }\r
2736 }\r
95276127 2737 if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
3012ce5c 2738 //\r
2739 // if user defined mode is not found, set to default mode 800x600\r
2740 //\r
2741 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2742 Mode = &Private->GraphicsOutputModeBuffer[Index];\r
2743 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
2744 CurrentIndex = Index;\r
2745 break;\r
2746 }\r
2747 }\r
95276127 2748 }\r
aec072ad 2749 }\r
8541adab 2750 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
95276127 2751 //\r
3012ce5c 2752 // Graphics console driver can ensure the same mode for all GOP devices\r
2753 // so we can get the current mode from this video device\r
95276127 2754 //\r
3012ce5c 2755 UgaDraw->GetMode (\r
2756 UgaDraw,\r
2757 &UgaHorizontalResolution,\r
2758 &UgaVerticalResolution,\r
2759 &UgaColorDepth,\r
2760 &UgaRefreshRate\r
2761 );\r
2762\r
95276127 2763 CurrentGraphicsOutputMode->MaxMode = 1;\r
aec072ad 2764 Info = CurrentGraphicsOutputMode->Info;\r
2765 Info->Version = 0;\r
3012ce5c 2766 Info->HorizontalResolution = UgaHorizontalResolution;\r
2767 Info->VerticalResolution = UgaVerticalResolution;\r
aec072ad 2768 Info->PixelFormat = PixelBltOnly;\r
3012ce5c 2769 Info->PixelsPerScanLine = UgaHorizontalResolution;\r
95276127 2770 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1be0dda6 2771 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;\r
95276127 2772 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2773\r
2774 //\r
2775 // Update the private mode buffer\r
2776 //\r
aec072ad 2777 CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
95276127 2778\r
2779 //\r
aec072ad 2780 // Only mode 0 is available to be set\r
95276127 2781 //\r
3012ce5c 2782 CurrentIndex = 0;\r
95276127 2783 }\r
2784\r
aec072ad 2785Done:\r
2786\r
2787 if (GraphicsOutput != NULL) {\r
2788 Private->CurrentNumberOfGraphicsOutput++;\r
2789 }\r
8541adab 2790 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
aec072ad 2791 Private->CurrentNumberOfUgaDraw++;\r
2792 }\r
2793\r
95276127 2794 //\r
2795 // Force GraphicsOutput mode to be set,\r
2796 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
2797 //\r
2798 Private->HardwareNeedsStarting = TRUE;\r
aec072ad 2799 //\r
2800 // Current mode number may need update now, so set it to an invalid mode number\r
2801 //\r
3012ce5c 2802 CurrentGraphicsOutputMode->Mode = 0xffff;\r
2803 //\r
2804 // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode.\r
2805 //\r
2806 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex);\r
2807\r
2808 //\r
2809 // If user defined mode is not valid for UGA, set to the default mode 800x600.\r
2810 //\r
2811 if (EFI_ERROR(Status)) {\r
2812 (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800;\r
2813 (Private->GraphicsOutputModeBuffer[0]).VerticalResolution = 600;\r
2814 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0);\r
2815 }\r
95276127 2816\r
95276127 2817 return Status;\r
2818}\r
2819\r
189eac21 2820\r
a4d608d1 2821/**\r
189eac21 2822 This routine will get the current console mode information (column, row)\r
2823 from ConsoleOutMode variable and set it; if the variable does not exist,\r
2824 set to user defined console mode.\r
2825\r
33019a71 2826 @param Private Consplitter Text Out pointer.\r
189eac21 2827\r
a4d608d1 2828 @return None\r
189eac21 2829\r
a4d608d1 2830**/\r
2831VOID\r
2832ConsplitterSetConsoleOutMode (\r
2833 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
2834 )\r
189eac21 2835{\r
2836 UINTN Col;\r
2837 UINTN Row;\r
2838 UINTN Mode;\r
2839 UINTN PreferMode;\r
2840 UINTN BaseMode;\r
2841 UINTN ModeInfoSize;\r
2842 UINTN MaxMode;\r
2843 EFI_STATUS Status;\r
2844 CONSOLE_OUT_MODE *ModeInfo;\r
2845 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
8541adab 2846\r
189eac21 2847 PreferMode = 0xFF;\r
2848 BaseMode = 0xFF;\r
2849 TextOut = &Private->TextOut;\r
2850 MaxMode = (UINTN) (TextOut->Mode->MaxMode);\r
2851 ModeInfoSize = sizeof (CONSOLE_OUT_MODE);\r
2852\r
2853 ModeInfo = AllocateZeroPool (sizeof(CONSOLE_OUT_MODE));\r
2854 ASSERT(ModeInfo != NULL);\r
2855\r
2856 Status = gRT->GetVariable (\r
a4d608d1 2857 VARCONOUTMODE,\r
189eac21 2858 &gEfiGenericPlatformVariableGuid,\r
2859 NULL,\r
2860 &ModeInfoSize,\r
2861 ModeInfo\r
2862 );\r
2863\r
2864 //\r
8541adab 2865 // Set to the default mode 80 x 25 required by EFI/UEFI spec;\r
189eac21 2866 // user can also define other valid default console mode here.\r
8541adab 2867 //\r
189eac21 2868 if (EFI_ERROR(Status)) {\r
2869 ModeInfo->Column = 80;\r
2870 ModeInfo->Row = 25;\r
2871 Status = gRT->SetVariable (\r
a4d608d1 2872 VARCONOUTMODE,\r
189eac21 2873 &gEfiGenericPlatformVariableGuid,\r
2874 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
2875 sizeof (CONSOLE_OUT_MODE),\r
2876 ModeInfo\r
8541adab 2877 );\r
189eac21 2878 }\r
8541adab 2879\r
189eac21 2880 for (Mode = 0; Mode < MaxMode; Mode++) {\r
2881 Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);\r
2882 if (!EFI_ERROR(Status)) {\r
2883 if (Col == ModeInfo->Column && Row == ModeInfo->Row) {\r
2884 PreferMode = Mode;\r
2885 }\r
2886 if (Col == 80 && Row == 25) {\r
2887 BaseMode = Mode;\r
2888 }\r
2889 }\r
2890 }\r
8541adab 2891\r
189eac21 2892 Status = TextOut->SetMode (TextOut, PreferMode);\r
8541adab 2893\r
189eac21 2894 //\r
2895 // if current mode setting is failed, default 80x25 mode will be set.\r
2896 //\r
2897 if (EFI_ERROR(Status)) {\r
2898 Status = TextOut->SetMode (TextOut, BaseMode);\r
2899 ASSERT(!EFI_ERROR(Status));\r
8541adab 2900\r
189eac21 2901 ModeInfo->Column = 80;\r
2902 ModeInfo->Row = 25;\r
8541adab 2903\r
189eac21 2904 //\r
2905 // Update ConOutMode variable\r
2906 //\r
2907 Status = gRT->SetVariable (\r
a4d608d1 2908 VARCONOUTMODE,\r
189eac21 2909 &gEfiGenericPlatformVariableGuid,\r
2910 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
2911 sizeof (CONSOLE_OUT_MODE),\r
2912 ModeInfo\r
8541adab 2913 );\r
189eac21 2914 }\r
2915\r
2916 gBS->FreePool (ModeInfo);\r
2917}\r
2918\r
2919\r
a4d608d1 2920/**\r
415df2a3 2921 Add Text Output Device in Consplitter Text Output list.\r
a4d608d1 2922\r
415df2a3 2923 @param Private Text Out Splitter pointer.\r
2924 @param TextOut Simple Text Output protocol pointer.\r
2925 @param GraphicsOutput Graphics Output protocol pointer.\r
2926 @param UgaDraw UGA Draw protocol pointer.\r
a4d608d1 2927\r
415df2a3 2928 @retval EFI_SUCCESS Text Output Device added successfully.\r
2929 @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.\r
a4d608d1 2930\r
2931**/\r
95276127 2932EFI_STATUS\r
2933ConSplitterTextOutAddDevice (\r
2934 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2935 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,\r
2936 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2937 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2938 )\r
95276127 2939{\r
2940 EFI_STATUS Status;\r
2941 UINTN CurrentNumOfConsoles;\r
2942 INT32 CurrentMode;\r
2943 INT32 MaxMode;\r
3012ce5c 2944 UINT32 UgaHorizontalResolution;\r
2945 UINT32 UgaVerticalResolution;\r
2946 UINT32 UgaColorDepth;\r
2947 UINT32 UgaRefreshRate;\r
95276127 2948 TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
2949\r
2950 Status = EFI_SUCCESS;\r
2951 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2952\r
2953 //\r
2954 // If the Text Out List is full, enlarge it by calling growbuffer().\r
2955 //\r
2956 while (CurrentNumOfConsoles >= Private->TextOutListCount) {\r
2957 Status = ConSplitterGrowBuffer (\r
2958 sizeof (TEXT_OUT_AND_GOP_DATA),\r
2959 &Private->TextOutListCount,\r
2960 (VOID **) &Private->TextOutList\r
2961 );\r
2962 if (EFI_ERROR (Status)) {\r
2963 return EFI_OUT_OF_RESOURCES;\r
2964 }\r
2965 //\r
2966 // Also need to reallocate the TextOutModeMap table\r
2967 //\r
2968 Status = ConSplitterGrowMapTable (Private);\r
2969 if (EFI_ERROR (Status)) {\r
2970 return EFI_OUT_OF_RESOURCES;\r
2971 }\r
2972 }\r
2973\r
2974 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];\r
2975\r
2976 TextAndGop->TextOut = TextOut;\r
2977 TextAndGop->GraphicsOutput = GraphicsOutput;\r
2978 TextAndGop->UgaDraw = UgaDraw;\r
2979\r
2980 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2981 //\r
3012ce5c 2982 // If No GOP/UGA device then use the ConOut device\r
95276127 2983 //\r
2984 TextAndGop->TextOutEnabled = TRUE;\r
2985 } else {\r
2986 //\r
3012ce5c 2987 // If GOP/UGA device use ConOut device only used if screen is in Text mode\r
95276127 2988 //\r
2989 TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
2990 }\r
2991\r
2992 if (CurrentNumOfConsoles == 0) {\r
2993 //\r
2994 // Add the first device's output mode to console splitter's mode list\r
2995 //\r
2996 Status = ConSplitterAddOutputMode (Private, TextOut);\r
2997 } else {\r
2998 ConSplitterSyncOutputMode (Private, TextOut);\r
2999 }\r
3000\r
3001 Private->CurrentNumberOfConsoles++;\r
3002\r
3003 //\r
3004 // Scan both TextOutList, for the intersection TextOut device\r
3005 // maybe both ConOut and StdErr incorporate the same Text Out\r
3006 // device in them, thus the output of both should be synced.\r
3007 //\r
3008 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
3009\r
3010 CurrentMode = Private->TextOutMode.Mode;\r
3011 MaxMode = Private->TextOutMode.MaxMode;\r
3012 ASSERT (MaxMode >= 1);\r
3013\r
3012ce5c 3014 //\r
3015 // Update DevNull mode according to current video device\r
3016 //\r
d0c64728 3017 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
3018 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
3019 ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
3020 }\r
95276127 3021 }\r
3012ce5c 3022 if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
8541adab 3023 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
3012ce5c 3024 Status = UgaDraw->GetMode (\r
3025 UgaDraw,\r
3026 &UgaHorizontalResolution,\r
3027 &UgaVerticalResolution,\r
3028 &UgaColorDepth,\r
3029 &UgaRefreshRate\r
3030 );\r
3031 if (!EFI_ERROR (Status)) {\r
3032 Status = ConSpliterUgaDrawSetMode (\r
3033 &Private->UgaDraw,\r
3034 UgaHorizontalResolution,\r
3035 UgaVerticalResolution,\r
3036 UgaColorDepth,\r
3037 UgaRefreshRate\r
3038 );\r
3039 }\r
3040 //\r
3041 // If GetMode/SetMode is failed, set to 800x600 mode\r
3042 //\r
3043 if(EFI_ERROR (Status)) {\r
3044 Status = ConSpliterUgaDrawSetMode (\r
3045 &Private->UgaDraw,\r
3046 800,\r
3047 600,\r
3048 32,\r
3049 60\r
3050 );\r
3051 }\r
3052 }\r
3053 }\r
95276127 3054\r
3055 if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
3056 //\r
3012ce5c 3057 // We just added a new GOP or UGA device in graphics mode\r
95276127 3058 //\r
d0c64728 3059 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
3060 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
3061 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
3062 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
3063 }\r
95276127 3064 } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
3065 //\r
3066 // The new console supports the same mode of the current console so sync up\r
3067 //\r
aec072ad 3068 DevNullSyncStdOut (Private);\r
95276127 3069 } else {\r
3070 //\r
3071 // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
3072 //\r
3073 Private->TextOut.SetMode (&Private->TextOut, 0);\r
3074 }\r
3075\r
189eac21 3076 //\r
8541adab 3077 // After adding new console device, all existing console devices should be\r
189eac21 3078 // synced to the current shared mode.\r
3079 //\r
3080 ConsplitterSetConsoleOutMode (Private);\r
3081\r
95276127 3082 return Status;\r
3083}\r
3084\r
a4d608d1 3085\r
3086/**\r
415df2a3 3087 Remove Text Out Device in Consplitter Text Out list.\r
a4d608d1 3088\r
415df2a3 3089 @param Private Text Out Splitter pointer.\r
3090 @param TextOut Simple Text Output Pointer protocol pointer.\r
a4d608d1 3091\r
415df2a3 3092 @retval EFI_SUCCESS Text Out Device removed successfully.\r
3093 @retval EFI_NOT_FOUND No Text Out Device found.\r
a4d608d1 3094\r
3095**/\r
95276127 3096EFI_STATUS\r
3097ConSplitterTextOutDeleteDevice (\r
3098 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
3099 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
3100 )\r
95276127 3101{\r
3102 INT32 Index;\r
3103 UINTN CurrentNumOfConsoles;\r
3104 TEXT_OUT_AND_GOP_DATA *TextOutList;\r
3105 EFI_STATUS Status;\r
3106\r
3107 //\r
3108 // Remove the specified text-out device data structure from the Text out List,\r
3109 // and rearrange the remaining data structures in the Text out List.\r
3110 //\r
3111 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
3112 Index = (INT32) CurrentNumOfConsoles - 1;\r
3113 TextOutList = Private->TextOutList;\r
3114 while (Index >= 0) {\r
3115 if (TextOutList->TextOut == TextOut) {\r
3116 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
3117 CurrentNumOfConsoles--;\r
8541adab 3118 if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
aec072ad 3119 Private->CurrentNumberOfUgaDraw--;\r
3120 }\r
3121 if (TextOutList->GraphicsOutput != NULL) {\r
3122 Private->CurrentNumberOfGraphicsOutput--;\r
3123 }\r
95276127 3124 break;\r
3125 }\r
3126\r
3127 Index--;\r
3128 TextOutList++;\r
3129 }\r
3130 //\r
3131 // The specified TextOut is not managed by the ConSplitter driver\r
3132 //\r
3133 if (Index < 0) {\r
3134 return EFI_NOT_FOUND;\r
3135 }\r
3136\r
3137 if (CurrentNumOfConsoles == 0) {\r
3138 //\r
3139 // If the number of consoles is zero clear the Dev NULL device\r
3140 //\r
3141 Private->CurrentNumberOfConsoles = 0;\r
3142 Private->TextOutMode.MaxMode = 1;\r
3143 Private->TextOutQueryData[0].Columns = 80;\r
3144 Private->TextOutQueryData[0].Rows = 25;\r
3145 DevNullTextOutSetMode (Private, 0);\r
3146\r
3147 return EFI_SUCCESS;\r
3148 }\r
3149 //\r
3150 // Max Mode is realy an intersection of the QueryMode command to all\r
3151 // devices. So we must copy the QueryMode of the first device to\r
3152 // QueryData.\r
3153 //\r
3154 ZeroMem (\r
3155 Private->TextOutQueryData,\r
3156 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)\r
3157 );\r
3158\r
3159 FreePool (Private->TextOutModeMap);\r
3160 Private->TextOutModeMap = NULL;\r
3161 TextOutList = Private->TextOutList;\r
3162\r
3163 //\r
3164 // Add the first TextOut to the QueryData array and ModeMap table\r
3165 //\r
3166 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);\r
3167\r
3168 //\r
3169 // Now add one by one\r
3170 //\r
3171 Index = 1;\r
3172 Private->CurrentNumberOfConsoles = 1;\r
3173 TextOutList++;\r
3174 while ((UINTN) Index < CurrentNumOfConsoles) {\r
3175 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);\r
3176 Index++;\r
3177 Private->CurrentNumberOfConsoles++;\r
3178 TextOutList++;\r
3179 }\r
3180\r
3181 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
3182\r
3183 return Status;\r
3184}\r
4b5c4fba 3185\r
a4d608d1 3186\r
3187/**\r
3188 Reset the input device and optionaly run diagnostics\r
3189\r
3190 @param This Protocol instance pointer.\r
3191 @param ExtendedVerification Driver may perform diagnostics on reset.\r
3192\r
3193 @retval EFI_SUCCESS The device was reset.\r
3194 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
3195 not be reset.\r
3196\r
3197**/\r
95276127 3198EFI_STATUS\r
3199EFIAPI\r
3200ConSplitterTextInReset (\r
3201 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
3202 IN BOOLEAN ExtendedVerification\r
3203 )\r
95276127 3204{\r
3205 EFI_STATUS Status;\r
3206 EFI_STATUS ReturnStatus;\r
3207 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3208 UINTN Index;\r
3209\r
3210 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3211\r
3212 Private->KeyEventSignalState = FALSE;\r
3213\r
3214 //\r
3215 // return the worst status met\r
3216 //\r
3217 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3218 Status = Private->TextInList[Index]->Reset (\r
3219 Private->TextInList[Index],\r
3220 ExtendedVerification\r
3221 );\r
3222 if (EFI_ERROR (Status)) {\r
3223 ReturnStatus = Status;\r
3224 }\r
3225 }\r
3226\r
3227 return ReturnStatus;\r
3228}\r
3229\r
a4d608d1 3230\r
3231/**\r
3232 Reads the next keystroke from the input device. The WaitForKey Event can\r
3233 be used to test for existance of a keystroke via WaitForEvent () call.\r
3234\r
33019a71 3235 @param Private Protocol instance pointer.\r
a4d608d1 3236 @param Key Driver may perform diagnostics on reset.\r
3237\r
3238 @retval EFI_SUCCESS The keystroke information was returned.\r
3239 @retval EFI_NOT_READY There was no keystroke data availiable.\r
3240 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due\r
3241 to hardware errors.\r
3242\r
3243**/\r
95276127 3244EFI_STATUS\r
3245EFIAPI\r
3246ConSplitterTextInPrivateReadKeyStroke (\r
3247 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
3248 OUT EFI_INPUT_KEY *Key\r
3249 )\r
95276127 3250{\r
3251 EFI_STATUS Status;\r
3252 UINTN Index;\r
3253 EFI_INPUT_KEY CurrentKey;\r
3254\r
3255 Key->UnicodeChar = 0;\r
3256 Key->ScanCode = SCAN_NULL;\r
3257\r
3258 //\r
3259 // if no physical console input device exists, return EFI_NOT_READY;\r
3260 // if any physical console input device has key input,\r
3261 // return the key and EFI_SUCCESS.\r
3262 //\r
3263 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3264 Status = Private->TextInList[Index]->ReadKeyStroke (\r
3265 Private->TextInList[Index],\r
3266 &CurrentKey\r
3267 );\r
3268 if (!EFI_ERROR (Status)) {\r
3269 *Key = CurrentKey;\r
3270 return Status;\r
3271 }\r
3272 }\r
3273\r
3274 return EFI_NOT_READY;\r
3275}\r
3276\r
95276127 3277\r
a4d608d1 3278/**\r
95276127 3279 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is\r
3280 the only device locked.\r
3281\r
95276127 3282 NONE\r
3283\r
a4d608d1 3284 @retval TRUE StdIn locked\r
3285 @retval FALSE StdIn working normally\r
95276127 3286\r
a4d608d1 3287**/\r
3288BOOLEAN\r
3289ConSpliterConssoleControlStdInLocked (\r
3290 VOID\r
3291 )\r
95276127 3292{\r
3293 return mConIn.PasswordEnabled;\r
3294}\r
3295\r
95276127 3296\r
a4d608d1 3297/**\r
95276127 3298 This timer event will fire when StdIn is locked. It will check the key\r
3299 sequence on StdIn to see if it matches the password. Any error in the\r
3300 password will cause the check to reset. As long a mConIn.PasswordEnabled is\r
3301 TRUE the StdIn splitter will not report any input.\r
3302\r
415df2a3 3303 @param Event The Event this notify function registered to.\r
3304 @param Context Pointer to the context data registerd to the\r
3305 Event.\r
95276127 3306\r
a4d608d1 3307 @return None\r
95276127 3308\r
a4d608d1 3309**/\r
3310VOID\r
3311EFIAPI\r
3312ConSpliterConsoleControlLockStdInEvent (\r
3313 IN EFI_EVENT Event,\r
3314 IN VOID *Context\r
3315 )\r
95276127 3316{\r
3317 EFI_STATUS Status;\r
3318 EFI_INPUT_KEY Key;\r
3319 CHAR16 BackSpaceString[2];\r
3320 CHAR16 SpaceString[2];\r
3321\r
3322 do {\r
3323 Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);\r
3324 if (!EFI_ERROR (Status)) {\r
3325 //\r
3326 // if it's an ENTER, match password\r
3327 //\r
3328 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {\r
3329 mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;\r
3330 if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {\r
3331 //\r
3332 // Password not match\r
3333 //\r
3334 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");\r
3335 mConIn.PwdIndex = 0;\r
3336 } else {\r
3337 //\r
3338 // Key matches password sequence\r
3339 //\r
3340 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);\r
3341 mConIn.PasswordEnabled = FALSE;\r
3342 Status = EFI_NOT_READY;\r
3343 }\r
3344 } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {\r
3345 //\r
3346 // BackSpace met\r
3347 //\r
3348 if (mConIn.PwdIndex > 0) {\r
3349 BackSpaceString[0] = CHAR_BACKSPACE;\r
3350 BackSpaceString[1] = 0;\r
3351\r
4b5c4fba 3352 SpaceString[0] = L' ';\r
95276127 3353 SpaceString[1] = 0;\r
3354\r
3355 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3356 ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);\r
3357 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
3358\r
3359 mConIn.PwdIndex--;\r
3360 }\r
3361 } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {\r
3362 //\r
3363 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input\r
3364 //\r
3365 if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {\r
3366 if (mConIn.PwdIndex == 0) {\r
3367 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");\r
3368 }\r
3369\r
3370 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");\r
3371 mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;\r
3372 mConIn.PwdIndex++;\r
3373 }\r
3374 }\r
a4d608d1 3375 }\r
3376 } while (!EFI_ERROR (Status));\r
3377}\r
3378\r
95276127 3379\r
a4d608d1 3380/**\r
95276127 3381 If Password is NULL unlock the password state variable and set the event\r
3382 timer. If the Password is too big return an error. If the Password is valid\r
3383 Copy the Password and enable state variable and then arm the periodic timer\r
3384\r
33019a71 3385 @param This Console Control protocol pointer.\r
3386 @param Password The password input.\r
95276127 3387\r
a4d608d1 3388 @retval EFI_SUCCESS Lock the StdIn device\r
3389 @retval EFI_INVALID_PARAMETER Password is NULL\r
3390 @retval EFI_OUT_OF_RESOURCES Buffer allocation to store the password fails\r
95276127 3391\r
a4d608d1 3392**/\r
3393EFI_STATUS\r
3394EFIAPI\r
3395ConSpliterConsoleControlLockStdIn (\r
3396 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
3397 IN CHAR16 *Password\r
3398 )\r
95276127 3399{\r
3400 if (Password == NULL) {\r
3401 return EFI_INVALID_PARAMETER;\r
3402 }\r
3403\r
3404 if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {\r
3405 //\r
3406 // Currently have a max password size\r
3407 //\r
3408 return EFI_OUT_OF_RESOURCES;\r
3409 }\r
3410 //\r
3411 // Save the password, initialize state variables and arm event timer\r
3412 //\r
3413 StrCpy (mConIn.Password, Password);\r
3414 mConIn.PasswordEnabled = TRUE;\r
3415 mConIn.PwdIndex = 0;\r
3416 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));\r
3417\r
3418 return EFI_SUCCESS;\r
3419}\r
3420\r
a4d608d1 3421\r
3422/**\r
3423 Reads the next keystroke from the input device. The WaitForKey Event can\r
3424 be used to test for existance of a keystroke via WaitForEvent () call.\r
3425 If the ConIn is password locked make it look like no keystroke is availible\r
3426\r
3427 @param This Protocol instance pointer.\r
3428 @param Key Driver may perform diagnostics on reset.\r
3429\r
3430 @retval EFI_SUCCESS The keystroke information was returned.\r
3431 @retval EFI_NOT_READY There was no keystroke data availiable.\r
3432 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due\r
3433 to hardware errors.\r
3434\r
3435**/\r
95276127 3436EFI_STATUS\r
3437EFIAPI\r
3438ConSplitterTextInReadKeyStroke (\r
3439 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
3440 OUT EFI_INPUT_KEY *Key\r
3441 )\r
95276127 3442{\r
3443 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3444\r
3445 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3446 if (Private->PasswordEnabled) {\r
3447 //\r
3448 // If StdIn Locked return not ready\r
3449 //\r
3450 return EFI_NOT_READY;\r
3451 }\r
3452\r
3453 Private->KeyEventSignalState = FALSE;\r
3454\r
3455 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
3456}\r
3457\r
95276127 3458\r
a4d608d1 3459/**\r
95276127 3460 This event agregates all the events of the ConIn devices in the spliter.\r
3461 If the ConIn is password locked then return.\r
3462 If any events of physical ConIn devices are signaled, signal the ConIn\r
3463 spliter event. This will cause the calling code to call\r
3464 ConSplitterTextInReadKeyStroke ().\r
3465\r
a4d608d1 3466 @param Event The Event assoicated with callback.\r
3467 @param Context Context registered when Event was created.\r
95276127 3468\r
a4d608d1 3469 @return None\r
95276127 3470\r
a4d608d1 3471**/\r
3472VOID\r
3473EFIAPI\r
3474ConSplitterTextInWaitForKey (\r
3475 IN EFI_EVENT Event,\r
3476 IN VOID *Context\r
3477 )\r
95276127 3478{\r
3479 EFI_STATUS Status;\r
3480 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3481 UINTN Index;\r
3482\r
3483 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
3484 if (Private->PasswordEnabled) {\r
3485 //\r
3486 // If StdIn Locked return not ready\r
3487 //\r
3488 return ;\r
3489 }\r
3490\r
3491 //\r
3492 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
3493 //\r
3494 if (Private->KeyEventSignalState) {\r
3495 gBS->SignalEvent (Event);\r
3496 return ;\r
3497 }\r
3498 //\r
3499 // if any physical console input device has key input, signal the event.\r
3500 //\r
3501 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3502 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);\r
3503 if (!EFI_ERROR (Status)) {\r
3504 gBS->SignalEvent (Event);\r
3505 Private->KeyEventSignalState = TRUE;\r
3506 }\r
3507 }\r
3508}\r
3509\r
66aa04e4 3510\r
a4d608d1 3511\r
3512/**\r
4b5c4fba 3513 Test if the key has been registered on input device.\r
a4d608d1 3514\r
3515 @param RegsiteredData A pointer to a buffer that is filled in with the\r
3516 keystroke state data for the key that was\r
3517 registered.\r
3518 @param InputData A pointer to a buffer that is filled in with the\r
3519 keystroke state data for the key that was\r
3520 pressed.\r
3521\r
3522 @retval TRUE Key be pressed matches a registered key.\r
3523 @retval FLASE Match failed.\r
3524\r
3525**/\r
66aa04e4 3526BOOLEAN\r
3527IsKeyRegistered (\r
3528 IN EFI_KEY_DATA *RegsiteredData,\r
3529 IN EFI_KEY_DATA *InputData\r
3530 )\r
66aa04e4 3531{\r
3532 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
7a5064ce 3533\r
66aa04e4 3534 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
3535 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
7a5064ce 3536 return FALSE;\r
3537 }\r
3538\r
66aa04e4 3539 //\r
3540 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
3541 //\r
3542 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
3543 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
7a5064ce 3544 return FALSE;\r
3545 }\r
66aa04e4 3546 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
3547 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
7a5064ce 3548 return FALSE;\r
3549 }\r
3550\r
66aa04e4 3551 return TRUE;\r
3552\r
3553}\r
3554\r
a4d608d1 3555\r
3556/**\r
3557 Reset the input device and optionaly run diagnostics\r
3558\r
3559 @param This Protocol instance pointer.\r
3560 @param ExtendedVerification Driver may perform diagnostics on reset.\r
3561\r
3562 @retval EFI_SUCCESS The device was reset.\r
3563 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
3564 not be reset.\r
3565\r
3566**/\r
66aa04e4 3567EFI_STATUS\r
3568EFIAPI\r
3569ConSplitterTextInResetEx (\r
3570 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3571 IN BOOLEAN ExtendedVerification\r
3572 )\r
66aa04e4 3573{\r
3574 EFI_STATUS Status;\r
3575 EFI_STATUS ReturnStatus;\r
3576 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3577 UINTN Index;\r
3578\r
3579 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3580\r
3581 Private->KeyEventSignalState = FALSE;\r
3582\r
3583 //\r
3584 // return the worst status met\r
3585 //\r
3586 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3587 Status = Private->TextInExList[Index]->Reset (\r
3588 Private->TextInExList[Index],\r
3589 ExtendedVerification\r
3590 );\r
3591 if (EFI_ERROR (Status)) {\r
3592 ReturnStatus = Status;\r
3593 }\r
3594 }\r
3595\r
3596 return ReturnStatus;\r
3597\r
3598}\r
3599\r
a4d608d1 3600\r
3601/**\r
3602 Reads the next keystroke from the input device. The WaitForKey Event can\r
3603 be used to test for existance of a keystroke via WaitForEvent () call.\r
3604\r
3605 @param This Protocol instance pointer.\r
3606 @param KeyData A pointer to a buffer that is filled in with the\r
3607 keystroke state data for the key that was\r
3608 pressed.\r
3609\r
3610 @retval EFI_SUCCESS The keystroke information was returned.\r
3611 @retval EFI_NOT_READY There was no keystroke data availiable.\r
3612 @retval EFI_DEVICE_ERROR The keystroke information was not returned due\r
3613 to hardware errors.\r
3614 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
3615\r
3616**/\r
66aa04e4 3617EFI_STATUS\r
3618EFIAPI\r
3619ConSplitterTextInReadKeyStrokeEx (\r
3620 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3621 OUT EFI_KEY_DATA *KeyData\r
3622 )\r
66aa04e4 3623{\r
3624 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3625 EFI_STATUS Status;\r
3626 UINTN Index;\r
3627 EFI_KEY_DATA CurrentKeyData;\r
3628\r
7a5064ce 3629\r
66aa04e4 3630 if (KeyData == NULL) {\r
3631 return EFI_INVALID_PARAMETER;\r
3632 }\r
3633\r
3634 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3635 if (Private->PasswordEnabled) {\r
3636 //\r
3637 // If StdIn Locked return not ready\r
3638 //\r
3639 return EFI_NOT_READY;\r
3640 }\r
3641\r
3642 Private->KeyEventSignalState = FALSE;\r
3643\r
3644 KeyData->Key.UnicodeChar = 0;\r
3645 KeyData->Key.ScanCode = SCAN_NULL;\r
3646\r
3647 //\r
3648 // if no physical console input device exists, return EFI_NOT_READY;\r
3649 // if any physical console input device has key input,\r
3650 // return the key and EFI_SUCCESS.\r
3651 //\r
3652 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3653 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
3654 Private->TextInExList[Index],\r
3655 &CurrentKeyData\r
3656 );\r
3657 if (!EFI_ERROR (Status)) {\r
3658 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
3659 return Status;\r
3660 }\r
3661 }\r
3662\r
7a5064ce 3663 return EFI_NOT_READY;\r
66aa04e4 3664}\r
3665\r
a4d608d1 3666\r
3667/**\r
3668 Set certain state for the input device.\r
3669\r
3670 @param This Protocol instance pointer.\r
3671 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
3672 state for the input device.\r
3673\r
3674 @retval EFI_SUCCESS The device state was set successfully.\r
3675 @retval EFI_DEVICE_ERROR The device is not functioning correctly and\r
3676 could not have the setting adjusted.\r
3677 @retval EFI_UNSUPPORTED The device does not have the ability to set its\r
3678 state.\r
3679 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
3680\r
3681**/\r
66aa04e4 3682EFI_STATUS\r
3683EFIAPI\r
3684ConSplitterTextInSetState (\r
3685 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3686 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
3687 )\r
66aa04e4 3688{\r
3689 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3690 EFI_STATUS Status;\r
3691 UINTN Index;\r
3692\r
3693 if (KeyToggleState == NULL) {\r
3694 return EFI_INVALID_PARAMETER;\r
3695 }\r
3696\r
3697 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3698\r
3699 //\r
3700 // if no physical console input device exists, return EFI_SUCCESS;\r
3701 // otherwise return the status of setting state of physical console input device\r
3702 //\r
3703 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3704 Status = Private->TextInExList[Index]->SetState (\r
3705 Private->TextInExList[Index],\r
3706 KeyToggleState\r
3707 );\r
3708 if (EFI_ERROR (Status)) {\r
3709 return Status;\r
3710 }\r
3711 }\r
3712\r
7a5064ce 3713 return EFI_SUCCESS;\r
66aa04e4 3714\r
3715}\r
3716\r
a4d608d1 3717\r
3718/**\r
3719 Register a notification function for a particular keystroke for the input device.\r
3720\r
3721 @param This Protocol instance pointer.\r
3722 @param KeyData A pointer to a buffer that is filled in with the\r
3723 keystroke information data for the key that was\r
3724 pressed.\r
3725 @param KeyNotificationFunction Points to the function to be called when the key\r
3726 sequence is typed specified by KeyData.\r
3727 @param NotifyHandle Points to the unique handle assigned to the\r
3728 registered notification.\r
3729\r
3730 @retval EFI_SUCCESS The notification function was registered\r
3731 successfully.\r
3732 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data\r
3733 structures.\r
3734 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
3735\r
3736**/\r
66aa04e4 3737EFI_STATUS\r
3738EFIAPI\r
3739ConSplitterTextInRegisterKeyNotify (\r
3740 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3741 IN EFI_KEY_DATA *KeyData,\r
3742 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
3743 OUT EFI_HANDLE *NotifyHandle\r
3744 )\r
66aa04e4 3745{\r
3746 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3747 EFI_STATUS Status;\r
3748 UINTN Index;\r
3749 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
3750 LIST_ENTRY *Link;\r
7a5064ce 3751 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
3752\r
66aa04e4 3753\r
3754 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
3755 return EFI_INVALID_PARAMETER;\r
3756 }\r
3757\r
3758 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3759\r
3760 //\r
7a5064ce 3761 // if no physical console input device exists,\r
66aa04e4 3762 // return EFI_SUCCESS directly.\r
3763 //\r
3764 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3765 return EFI_SUCCESS;\r
3766 }\r
3767\r
3768 //\r
3769 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
3770 //\r
3771 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3772 CurrentNotify = CR (\r
7a5064ce 3773 Link,\r
3774 TEXT_IN_EX_SPLITTER_NOTIFY,\r
3775 NotifyEntry,\r
66aa04e4 3776 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
3777 );\r
7a5064ce 3778 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 3779 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
7a5064ce 3780 *NotifyHandle = CurrentNotify->NotifyHandle;\r
66aa04e4 3781 return EFI_SUCCESS;\r
3782 }\r
3783 }\r
3784 }\r
7a5064ce 3785\r
66aa04e4 3786 //\r
3787 // Allocate resource to save the notification function\r
7a5064ce 3788 //\r
66aa04e4 3789 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
3790 if (NewNotify == NULL) {\r
3791 return EFI_OUT_OF_RESOURCES;\r
3792 }\r
3793 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
3794 if (NewNotify->NotifyHandleList == NULL) {\r
3795 gBS->FreePool (NewNotify);\r
3796 return EFI_OUT_OF_RESOURCES;\r
3797 }\r
7a5064ce 3798 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;\r
66aa04e4 3799 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
3800 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
7a5064ce 3801\r
66aa04e4 3802 //\r
7a5064ce 3803 // Return the wrong status of registering key notify of\r
66aa04e4 3804 // physical console input device if meet problems\r
3805 //\r
3806 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3807 Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
3808 Private->TextInExList[Index],\r
3809 KeyData,\r
3810 KeyNotificationFunction,\r
3811 &NewNotify->NotifyHandleList[Index]\r
3812 );\r
3813 if (EFI_ERROR (Status)) {\r
3814 gBS->FreePool (NewNotify->NotifyHandleList);\r
3815 gBS->FreePool (NewNotify);\r
3816 return Status;\r
3817 }\r
3818 }\r
3819\r
3820 //\r
3821 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
7a5064ce 3822 //\r
66aa04e4 3823 Status = gBS->InstallMultipleProtocolInterfaces (\r
3824 &NewNotify->NotifyHandle,\r
3825 &gSimpleTextInExNotifyGuid,\r
3826 NULL,\r
3827 NULL\r
3828 );\r
3829 ASSERT_EFI_ERROR (Status);\r
3830\r
3831 InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
7a5064ce 3832\r
3833 *NotifyHandle = NewNotify->NotifyHandle;\r
3834\r
3835 return EFI_SUCCESS;\r
3836\r
66aa04e4 3837}\r
3838\r
a4d608d1 3839\r
3840/**\r
3841 Remove a registered notification function from a particular keystroke.\r
3842\r
3843 @param This Protocol instance pointer.\r
3844 @param NotificationHandle The handle of the notification function being\r
3845 unregistered.\r
3846\r
3847 @retval EFI_SUCCESS The notification function was unregistered\r
3848 successfully.\r
3849 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
3850 @retval EFI_NOT_FOUND Can not find the matching entry in database.\r
3851\r
3852**/\r
66aa04e4 3853EFI_STATUS\r
3854EFIAPI\r
3855ConSplitterTextInUnregisterKeyNotify (\r
3856 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3857 IN EFI_HANDLE NotificationHandle\r
3858 )\r
66aa04e4 3859{\r
3860 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3861 EFI_STATUS Status;\r
3862 UINTN Index;\r
3863 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
7a5064ce 3864 LIST_ENTRY *Link;\r
66aa04e4 3865\r
3866 if (NotificationHandle == NULL) {\r
3867 return EFI_INVALID_PARAMETER;\r
3868 }\r
3869\r
3870 Status = gBS->OpenProtocol (\r
3871 NotificationHandle,\r
3872 &gSimpleTextInExNotifyGuid,\r
3873 NULL,\r
3874 NULL,\r
3875 NULL,\r
3876 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
3877 );\r
3878 if (EFI_ERROR (Status)) {\r
3879 return EFI_INVALID_PARAMETER;\r
3880 }\r
3881\r
3882 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3883\r
3884 //\r
7a5064ce 3885 // if no physical console input device exists,\r
66aa04e4 3886 // return EFI_SUCCESS directly.\r
3887 //\r
3888 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3889 return EFI_SUCCESS;\r
3890 }\r
3891\r
3892 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3893 CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
3894 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
3895 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3896 Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
7a5064ce 3897 Private->TextInExList[Index],\r
66aa04e4 3898 CurrentNotify->NotifyHandleList[Index]\r
3899 );\r
3900 if (EFI_ERROR (Status)) {\r
3901 return Status;\r
7a5064ce 3902 }\r
66aa04e4 3903 }\r
7a5064ce 3904 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
66aa04e4 3905 Status = gBS->UninstallMultipleProtocolInterfaces (\r
3906 CurrentNotify->NotifyHandle,\r
3907 &gSimpleTextInExNotifyGuid,\r
3908 NULL,\r
3909 NULL\r
3910 );\r
3911 ASSERT_EFI_ERROR (Status);\r
3912 gBS->FreePool (CurrentNotify->NotifyHandleList);\r
3913 gBS->FreePool (CurrentNotify);\r
7a5064ce 3914 return EFI_SUCCESS;\r
3915 }\r
66aa04e4 3916 }\r
3917\r
7a5064ce 3918 return EFI_NOT_FOUND;\r
3919\r
66aa04e4 3920}\r
3921\r
a4d608d1 3922\r
3923/**\r
3924 Reset the input device and optionaly run diagnostics\r
3925\r
3926 @param This Protocol instance pointer.\r
3927 @param ExtendedVerification Driver may perform diagnostics on reset.\r
3928\r
3929 @retval EFI_SUCCESS The device was reset.\r
3930 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
3931 not be reset.\r
3932\r
3933**/\r
95276127 3934EFI_STATUS\r
3935EFIAPI\r
3936ConSplitterSimplePointerReset (\r
3937 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
3938 IN BOOLEAN ExtendedVerification\r
3939 )\r
95276127 3940{\r
3941 EFI_STATUS Status;\r
3942 EFI_STATUS ReturnStatus;\r
3943 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3944 UINTN Index;\r
3945\r
3946 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
3947\r
3948 Private->InputEventSignalState = FALSE;\r
3949\r
3950 if (Private->CurrentNumberOfPointers == 0) {\r
3951 return EFI_SUCCESS;\r
3952 }\r
3953 //\r
3954 // return the worst status met\r
3955 //\r
3956 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
3957 Status = Private->PointerList[Index]->Reset (\r
3958 Private->PointerList[Index],\r
3959 ExtendedVerification\r
3960 );\r
3961 if (EFI_ERROR (Status)) {\r
3962 ReturnStatus = Status;\r
3963 }\r
3964 }\r
3965\r
3966 return ReturnStatus;\r
3967}\r
3968\r
a4d608d1 3969\r
3970/**\r
3971 Reads the next keystroke from the input device. The WaitForKey Event can\r
3972 be used to test for existance of a keystroke via WaitForEvent () call.\r
3973\r
33019a71 3974 @param Private Protocol instance pointer.\r
3975 @param State The state information of simple pointer device.\r
a4d608d1 3976\r
3977 @retval EFI_SUCCESS The keystroke information was returned.\r
3978 @retval EFI_NOT_READY There was no keystroke data availiable.\r
3979 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due\r
3980 to hardware errors.\r
3981\r
3982**/\r
95276127 3983EFI_STATUS\r
3984EFIAPI\r
3985ConSplitterSimplePointerPrivateGetState (\r
3986 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
3987 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
3988 )\r
95276127 3989{\r
3990 EFI_STATUS Status;\r
3991 EFI_STATUS ReturnStatus;\r
3992 UINTN Index;\r
3993 EFI_SIMPLE_POINTER_STATE CurrentState;\r
3994\r
3995 State->RelativeMovementX = 0;\r
3996 State->RelativeMovementY = 0;\r
3997 State->RelativeMovementZ = 0;\r
3998 State->LeftButton = FALSE;\r
3999 State->RightButton = FALSE;\r
4000\r
4001 //\r
4002 // if no physical console input device exists, return EFI_NOT_READY;\r
4003 // if any physical console input device has key input,\r
4004 // return the key and EFI_SUCCESS.\r
4005 //\r
4006 ReturnStatus = EFI_NOT_READY;\r
4007 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
4008\r
4009 Status = Private->PointerList[Index]->GetState (\r
4010 Private->PointerList[Index],\r
4011 &CurrentState\r
4012 );\r
4013 if (!EFI_ERROR (Status)) {\r
4014 if (ReturnStatus == EFI_NOT_READY) {\r
4015 ReturnStatus = EFI_SUCCESS;\r
4016 }\r
4017\r
4018 if (CurrentState.LeftButton) {\r
4019 State->LeftButton = TRUE;\r
4020 }\r
4021\r
4022 if (CurrentState.RightButton) {\r
4023 State->RightButton = TRUE;\r
4024 }\r
4025\r
4026 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
4027 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
4028 }\r
4029\r
4030 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
4031 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
4032 }\r
4033\r
4034 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
4035 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
4036 }\r
4037 } else if (Status == EFI_DEVICE_ERROR) {\r
4038 ReturnStatus = EFI_DEVICE_ERROR;\r
4039 }\r
4040 }\r
4041\r
4042 return ReturnStatus;\r
4043}\r
4044\r
a4d608d1 4045\r
4046/**\r
4047 Reads the next keystroke from the input device. The WaitForKey Event can\r
4048 be used to test for existance of a keystroke via WaitForEvent () call.\r
4049 If the ConIn is password locked make it look like no keystroke is availible\r
4050\r
415df2a3 4051 @param This A pointer to protocol instance.\r
4052 @param State A pointer to state information on the pointer device\r
a4d608d1 4053\r
415df2a3 4054 @retval EFI_SUCCESS The keystroke information was returned in State.\r
a4d608d1 4055 @retval EFI_NOT_READY There was no keystroke data availiable.\r
4056 @retval EFI_DEVICE_ERROR The keydtroke information was not returned due\r
4057 to hardware errors.\r
4058\r
4059**/\r
95276127 4060EFI_STATUS\r
4061EFIAPI\r
4062ConSplitterSimplePointerGetState (\r
4063 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
4064 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
4065 )\r
95276127 4066{\r
4067 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4068\r
4069 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
4070 if (Private->PasswordEnabled) {\r
4071 //\r
4072 // If StdIn Locked return not ready\r
4073 //\r
4074 return EFI_NOT_READY;\r
4075 }\r
4076\r
4077 Private->InputEventSignalState = FALSE;\r
4078\r
4079 return ConSplitterSimplePointerPrivateGetState (Private, State);\r
4080}\r
4081\r
95276127 4082\r
a4d608d1 4083/**\r
95276127 4084 This event agregates all the events of the ConIn devices in the spliter.\r
4085 If the ConIn is password locked then return.\r
4086 If any events of physical ConIn devices are signaled, signal the ConIn\r
4087 spliter event. This will cause the calling code to call\r
4088 ConSplitterTextInReadKeyStroke ().\r
4089\r
a4d608d1 4090 @param Event The Event assoicated with callback.\r
4091 @param Context Context registered when Event was created.\r
95276127 4092\r
a4d608d1 4093 @return None\r
95276127 4094\r
a4d608d1 4095**/\r
4096VOID\r
4097EFIAPI\r
4098ConSplitterSimplePointerWaitForInput (\r
4099 IN EFI_EVENT Event,\r
4100 IN VOID *Context\r
4101 )\r
95276127 4102{\r
4103 EFI_STATUS Status;\r
4104 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4105 UINTN Index;\r
4106\r
4107 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
4108 if (Private->PasswordEnabled) {\r
4109 //\r
4110 // If StdIn Locked return not ready\r
4111 //\r
4112 return ;\r
4113 }\r
4114\r
4115 //\r
4116 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
4117 //\r
4118 if (Private->InputEventSignalState) {\r
4119 gBS->SignalEvent (Event);\r
4120 return ;\r
4121 }\r
4122 //\r
4123 // if any physical console input device has key input, signal the event.\r
4124 //\r
4125 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
4126 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);\r
4127 if (!EFI_ERROR (Status)) {\r
4128 gBS->SignalEvent (Event);\r
4129 Private->InputEventSignalState = TRUE;\r
4130 }\r
4131 }\r
4132}\r
4133\r
a4d608d1 4134/**\r
4135 Resets the pointer device hardware.\r
4136\r
4137 @param This Protocol instance pointer.\r
4138 @param ExtendedVerification Driver may perform diagnostics on reset.\r
4139\r
4140 @retval EFI_SUCCESS The device was reset.\r
4141 @retval EFI_DEVICE_ERROR The device is not functioning correctly and\r
4142 could not be reset.\r
4143\r
4144**/\r
8ae0b360 4145EFI_STATUS\r
4146EFIAPI\r
4147ConSplitterAbsolutePointerReset (\r
4148 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
4149 IN BOOLEAN ExtendedVerification\r
4150 )\r
8ae0b360 4151{\r
4152 EFI_STATUS Status;\r
4153 EFI_STATUS ReturnStatus;\r
4154 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4155 UINTN Index;\r
4156\r
4157 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
4158\r
4159 Private->AbsoluteInputEventSignalState = FALSE;\r
7a5064ce 4160\r
8ae0b360 4161 if (Private->CurrentNumberOfAbsolutePointers == 0) {\r
4162 return EFI_SUCCESS;\r
4163 }\r
4164 //\r
4165 // return the worst status met\r
4166 //\r
4167 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
4168 Status = Private->AbsolutePointerList[Index]->Reset (\r
4169 Private->AbsolutePointerList[Index],\r
4170 ExtendedVerification\r
4171 );\r
4172 if (EFI_ERROR (Status)) {\r
4173 ReturnStatus = Status;\r
4174 }\r
4175 }\r
4176\r
4177 return ReturnStatus;\r
4178}\r
4179\r
a4d608d1 4180\r
4181/**\r
4182 Retrieves the current state of a pointer device.\r
4183\r
4184 @param This Protocol instance pointer.\r
4185 @param State A pointer to the state information on the\r
4186 pointer device.\r
4187\r
4188 @retval EFI_SUCCESS The state of the pointer device was returned in\r
4189 State..\r
4190 @retval EFI_NOT_READY The state of the pointer device has not changed\r
4191 since the last call to GetState().\r
4192 @retval EFI_DEVICE_ERROR A device error occurred while attempting to\r
4193 retrieve the pointer device's current state.\r
4194\r
4195**/\r
8ae0b360 4196EFI_STATUS\r
7a5064ce 4197EFIAPI\r
8ae0b360 4198ConSplitterAbsolutePointerGetState (\r
4199 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
4200 IN OUT EFI_ABSOLUTE_POINTER_STATE *State\r
4201 )\r
8ae0b360 4202{\r
4203 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4204 EFI_STATUS Status;\r
4205 EFI_STATUS ReturnStatus;\r
4206 UINTN Index;\r
4207 EFI_ABSOLUTE_POINTER_STATE CurrentState;\r
4208\r
4209\r
4210 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
4211 if (Private->PasswordEnabled) {\r
4212 //\r
4213 // If StdIn Locked return not ready\r
4214 //\r
4215 return EFI_NOT_READY;\r
4216 }\r
4217\r
4218 Private->AbsoluteInputEventSignalState = FALSE;\r
4219\r
4220 State->CurrentX = 0;\r
4221 State->CurrentY = 0;\r
4222 State->CurrentZ = 0;\r
4223 State->ActiveButtons = 0;\r
7a5064ce 4224\r
8ae0b360 4225 //\r
4226 // if no physical pointer device exists, return EFI_NOT_READY;\r
4227 // if any physical pointer device has changed state,\r
4228 // return the state and EFI_SUCCESS.\r
4229 //\r
4230 ReturnStatus = EFI_NOT_READY;\r
4231 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
4232\r
4233 Status = Private->AbsolutePointerList[Index]->GetState (\r
4234 Private->AbsolutePointerList[Index],\r
4235 &CurrentState\r
4236 );\r
4237 if (!EFI_ERROR (Status)) {\r
4238 if (ReturnStatus == EFI_NOT_READY) {\r
4239 ReturnStatus = EFI_SUCCESS;\r
4240 }\r
4241\r
4242 State->ActiveButtons = CurrentState.ActiveButtons;\r
4243\r
4244 if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
4245 State->CurrentX = CurrentState.CurrentX;\r
4246 }\r
4247 if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
4248 State->CurrentY = CurrentState.CurrentY;\r
4249 }\r
4250 if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
4251 State->CurrentZ = CurrentState.CurrentZ;\r
4252 }\r
7a5064ce 4253\r
8ae0b360 4254 } else if (Status == EFI_DEVICE_ERROR) {\r
4255 ReturnStatus = EFI_DEVICE_ERROR;\r
4256 }\r
4257 }\r
4258\r
4259 return ReturnStatus;\r
4260}\r
4261\r
8ae0b360 4262\r
a4d608d1 4263/**\r
8ae0b360 4264 This event agregates all the events of the pointer devices in the splitter.\r
4265 If the ConIn is password locked then return.\r
4266 If any events of physical pointer devices are signaled, signal the pointer\r
4267 splitter event. This will cause the calling code to call\r
4268 ConSplitterAbsolutePointerGetState ().\r
4269\r
a4d608d1 4270 @param Event The Event assoicated with callback.\r
4271 @param Context Context registered when Event was created.\r
8ae0b360 4272\r
a4d608d1 4273 @return None\r
8ae0b360 4274\r
a4d608d1 4275**/\r
4276VOID\r
4277EFIAPI\r
4278ConSplitterAbsolutePointerWaitForInput (\r
4279 IN EFI_EVENT Event,\r
4280 IN VOID *Context\r
4281 )\r
8ae0b360 4282{\r
4283 EFI_STATUS Status;\r
4284 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
4285 UINTN Index;\r
4286\r
4287 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
4288 if (Private->PasswordEnabled) {\r
4289 //\r
4290 // If StdIn Locked return not ready\r
4291 //\r
4292 return ;\r
4293 }\r
4294\r
4295 //\r
7a5064ce 4296 // if AbsoluteInputEventSignalState is flagged before,\r
8ae0b360 4297 // and not cleared by Reset() or GetState(), signal it\r
4298 //\r
4299 if (Private->AbsoluteInputEventSignalState) {\r
4300 gBS->SignalEvent (Event);\r
4301 return ;\r
4302 }\r
4303 //\r
4304 // if any physical console input device has key input, signal the event.\r
4305 //\r
4306 for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
4307 Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput);\r
4308 if (!EFI_ERROR (Status)) {\r
4309 gBS->SignalEvent (Event);\r
4310 Private->AbsoluteInputEventSignalState = TRUE;\r
4311 }\r
4312 }\r
4313}\r
4314\r
a4d608d1 4315\r
4316/**\r
4317 Reset the text output device hardware and optionaly run diagnostics\r
4318\r
4319 @param This Protocol instance pointer.\r
4320 @param ExtendedVerification Driver may perform more exhaustive verfication\r
4321 operation of the device during reset.\r
4322\r
4323 @retval EFI_SUCCESS The text output device was reset.\r
4324 @retval EFI_DEVICE_ERROR The text output device is not functioning\r
4325 correctly and could not be reset.\r
4326\r
4327**/\r
95276127 4328EFI_STATUS\r
4329EFIAPI\r
4330ConSplitterTextOutReset (\r
4331 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4332 IN BOOLEAN ExtendedVerification\r
4333 )\r
95276127 4334{\r
4335 EFI_STATUS Status;\r
4336 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4337 UINTN Index;\r
4338 EFI_STATUS ReturnStatus;\r
4339\r
4340 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4341\r
4342 //\r
4343 // return the worst status met\r
4344 //\r
4345 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4346\r
4347 if (Private->TextOutList[Index].TextOutEnabled) {\r
4348\r
4349 Status = Private->TextOutList[Index].TextOut->Reset (\r
4350 Private->TextOutList[Index].TextOut,\r
4351 ExtendedVerification\r
4352 );\r
4353 if (EFI_ERROR (Status)) {\r
4354 ReturnStatus = Status;\r
4355 }\r
4356 }\r
4357 }\r
4358\r
0ce1dd70 4359 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));\r
95276127 4360\r
4361 Status = DevNullTextOutSetMode (Private, 0);\r
4362 if (EFI_ERROR (Status)) {\r
4363 ReturnStatus = Status;\r
4364 }\r
4365\r
4366 return ReturnStatus;\r
4367}\r
4368\r
a4d608d1 4369\r
4370/**\r
4371 Write a Unicode string to the output device.\r
4372\r
4373 @param This Protocol instance pointer.\r
33019a71 4374 @param WString The NULL-terminated Unicode string to be\r
a4d608d1 4375 displayed on the output device(s). All output\r
4376 devices must also support the Unicode drawing\r
4377 defined in this file.\r
4378\r
4379 @retval EFI_SUCCESS The string was output to the device.\r
4380 @retval EFI_DEVICE_ERROR The device reported an error while attempting to\r
4381 output the text.\r
4382 @retval EFI_UNSUPPORTED The output device's mode is not currently in a\r
4383 defined text mode.\r
4384 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the\r
4385 characters in the Unicode string could not be\r
4386 rendered and were skipped.\r
4387\r
4388**/\r
95276127 4389EFI_STATUS\r
4390EFIAPI\r
4391ConSplitterTextOutOutputString (\r
4392 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4393 IN CHAR16 *WString\r
4394 )\r
95276127 4395{\r
4396 EFI_STATUS Status;\r
4397 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4398 UINTN Index;\r
4399 UINTN BackSpaceCount;\r
4400 EFI_STATUS ReturnStatus;\r
4401 CHAR16 *TargetString;\r
4402\r
4403 This->SetAttribute (This, This->Mode->Attribute);\r
4404\r
4405 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4406\r
4407 BackSpaceCount = 0;\r
a4d608d1 4408 for (TargetString = WString; *TargetString != L'\0'; TargetString++) {\r
95276127 4409 if (*TargetString == CHAR_BACKSPACE) {\r
4410 BackSpaceCount++;\r
4411 }\r
4412\r
4413 }\r
4414\r
4415 if (BackSpaceCount == 0) {\r
4416 TargetString = WString;\r
4417 } else {\r
4418 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
4419 StrCpy (TargetString, WString);\r
4420 }\r
4421 //\r
4422 // return the worst status met\r
4423 //\r
4424 Status = DevNullTextOutOutputString (Private, TargetString);\r
4425 if (EFI_ERROR (Status)) {\r
4426 ReturnStatus = Status;\r
4427 }\r
4428\r
4429 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4430\r
4431 if (Private->TextOutList[Index].TextOutEnabled) {\r
4432 Status = Private->TextOutList[Index].TextOut->OutputString (\r
4433 Private->TextOutList[Index].TextOut,\r
4434 TargetString\r
4435 );\r
4436 if (EFI_ERROR (Status)) {\r
4437 ReturnStatus = Status;\r
4438 }\r
4439 }\r
4440 }\r
4441\r
a4d608d1 4442 if (BackSpaceCount > 0) {\r
95276127 4443 FreePool (TargetString);\r
4444 }\r
4445\r
4446 return ReturnStatus;\r
4447}\r
4448\r
a4d608d1 4449\r
4450/**\r
4451 Verifies that all characters in a Unicode string can be output to the\r
4452 target device.\r
4453\r
4454 @param This Protocol instance pointer.\r
33019a71 4455 @param WString The NULL-terminated Unicode string to be\r
a4d608d1 4456 examined for the output device(s).\r
4457\r
4458 @retval EFI_SUCCESS The device(s) are capable of rendering the\r
4459 output string.\r
4460 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string\r
4461 cannot be rendered by one or more of the output\r
4462 devices mapped by the EFI handle.\r
4463\r
4464**/\r
95276127 4465EFI_STATUS\r
4466EFIAPI\r
4467ConSplitterTextOutTestString (\r
4468 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4469 IN CHAR16 *WString\r
4470 )\r
95276127 4471{\r
4472 EFI_STATUS Status;\r
4473 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4474 UINTN Index;\r
4475 EFI_STATUS ReturnStatus;\r
4476\r
4477 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4478\r
4479 //\r
4480 // return the worst status met\r
4481 //\r
4482 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4483 if (Private->TextOutList[Index].TextOutEnabled) {\r
4484 Status = Private->TextOutList[Index].TextOut->TestString (\r
4485 Private->TextOutList[Index].TextOut,\r
4486 WString\r
4487 );\r
4488 if (EFI_ERROR (Status)) {\r
4489 ReturnStatus = Status;\r
4490 }\r
4491 }\r
4492 }\r
4493 //\r
4494 // There is no DevNullTextOutTestString () since a Unicode buffer would\r
4495 // always return EFI_SUCCESS.\r
4496 // ReturnStatus will be EFI_SUCCESS if no consoles are present\r
4497 //\r
4498 return ReturnStatus;\r
4499}\r
4500\r
a4d608d1 4501\r
4502/**\r
4503 Returns information for an available text mode that the output device(s)\r
4504 supports.\r
4505\r
4506 @param This Protocol instance pointer.\r
4507 @param ModeNumber The mode number to return information on.\r
33019a71 4508 @param Columns Returns the columns of the text output device\r
4509 for the requested ModeNumber.\r
4510 @param Rows Returns the rows of the text output device\r
a4d608d1 4511 for the requested ModeNumber.\r
4512\r
4513 @retval EFI_SUCCESS The requested mode information was returned.\r
4514 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4515 the request.\r
4516 @retval EFI_UNSUPPORTED The mode number was not valid.\r
4517\r
4518**/\r
95276127 4519EFI_STATUS\r
4520EFIAPI\r
4521ConSplitterTextOutQueryMode (\r
4522 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4523 IN UINTN ModeNumber,\r
4524 OUT UINTN *Columns,\r
4525 OUT UINTN *Rows\r
4526 )\r
95276127 4527{\r
4528 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3012ce5c 4529 UINTN CurrentMode;\r
4530 INT32 *TextOutModeMap;\r
95276127 4531\r
4532 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4533\r
4534 //\r
4535 // Check whether param ModeNumber is valid.\r
4536 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
4537 //\r
4538 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
4539 return EFI_UNSUPPORTED;\r
4540 }\r
4541\r
4542 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
4543 return EFI_UNSUPPORTED;\r
4544 }\r
4545\r
3012ce5c 4546 //\r
4547 // We get the available mode from mode intersection map if it's available\r
4548 //\r
4549 if (Private->TextOutModeMap != NULL) {\r
4550 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4551 CurrentMode = (UINTN)(*TextOutModeMap);\r
4552 *Columns = Private->TextOutQueryData[CurrentMode].Columns;\r
4553 *Rows = Private->TextOutQueryData[CurrentMode].Rows;\r
4554 } else {\r
4555 *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
4556 *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
4557 }\r
95276127 4558\r
4559 if (*Columns <= 0 && *Rows <= 0) {\r
4560 return EFI_UNSUPPORTED;\r
4561\r
4562 }\r
4563\r
4564 return EFI_SUCCESS;\r
4565}\r
4566\r
a4d608d1 4567\r
4568/**\r
4569 Sets the output device(s) to a specified mode.\r
4570\r
4571 @param This Protocol instance pointer.\r
4572 @param ModeNumber The mode number to set.\r
4573\r
4574 @retval EFI_SUCCESS The requested text mode was set.\r
4575 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4576 the request.\r
4577 @retval EFI_UNSUPPORTED The mode number was not valid.\r
4578\r
4579**/\r
95276127 4580EFI_STATUS\r
4581EFIAPI\r
4582ConSplitterTextOutSetMode (\r
4583 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4584 IN UINTN ModeNumber\r
4585 )\r
95276127 4586{\r
4587 EFI_STATUS Status;\r
4588 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4589 UINTN Index;\r
4590 INT32 *TextOutModeMap;\r
4591 EFI_STATUS ReturnStatus;\r
4592\r
4593 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4594\r
4595 //\r
4596 // Check whether param ModeNumber is valid.\r
4597 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
4598 //\r
4599 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
4600 return EFI_UNSUPPORTED;\r
4601 }\r
4602\r
4603 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
4604 return EFI_UNSUPPORTED;\r
4605 }\r
4606 //\r
4607 // If the mode is being set to the curent mode, then just clear the screen and return.\r
4608 //\r
4609 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {\r
4610 return ConSplitterTextOutClearScreen (This);\r
4611 }\r
4612 //\r
4613 // return the worst status met\r
4614 //\r
4615 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4616 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4617\r
4618 if (Private->TextOutList[Index].TextOutEnabled) {\r
4619 Status = Private->TextOutList[Index].TextOut->SetMode (\r
4620 Private->TextOutList[Index].TextOut,\r
4621 TextOutModeMap[Index]\r
4622 );\r
4623 //\r
3012ce5c 4624 // If this console device is based on a GOP or UGA device, then sync up the bitmap from\r
4625 // the GOP/UGA splitter and reclear the text portion of the display in the new mode.\r
95276127 4626 //\r
4627 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
4628 Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
4629 }\r
4630\r
4631 if (EFI_ERROR (Status)) {\r
4632 ReturnStatus = Status;\r
4633 }\r
4634 }\r
4635 }\r
4636 //\r
4637 // The DevNull Console will support any possible mode as it allocates memory\r
4638 //\r
4639 Status = DevNullTextOutSetMode (Private, ModeNumber);\r
4640 if (EFI_ERROR (Status)) {\r
4641 ReturnStatus = Status;\r
4642 }\r
4643\r
4644 return ReturnStatus;\r
4645}\r
4646\r
a4d608d1 4647\r
4648/**\r
4649 Sets the background and foreground colors for the OutputString () and\r
4650 ClearScreen () functions.\r
4651\r
4652 @param This Protocol instance pointer.\r
4653 @param Attribute The attribute to set. Bits 0..3 are the\r
4654 foreground color, and bits 4..6 are the\r
4655 background color. All other bits are undefined\r
4656 and must be zero. The valid Attributes are\r
4657 defined in this file.\r
4658\r
4659 @retval EFI_SUCCESS The attribute was set.\r
4660 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4661 the request.\r
4662 @retval EFI_UNSUPPORTED The attribute requested is not defined.\r
4663\r
4664**/\r
95276127 4665EFI_STATUS\r
4666EFIAPI\r
4667ConSplitterTextOutSetAttribute (\r
4668 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4669 IN UINTN Attribute\r
4670 )\r
95276127 4671{\r
4672 EFI_STATUS Status;\r
4673 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4674 UINTN Index;\r
4675 EFI_STATUS ReturnStatus;\r
4676\r
4677 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4678\r
4679 //\r
4680 // Check whether param Attribute is valid.\r
4681 //\r
4682 if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {\r
4683 return EFI_UNSUPPORTED;\r
4684 }\r
4685\r
4686 //\r
4687 // return the worst status met\r
4688 //\r
4689 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4690\r
4691 if (Private->TextOutList[Index].TextOutEnabled) {\r
4692 Status = Private->TextOutList[Index].TextOut->SetAttribute (\r
4693 Private->TextOutList[Index].TextOut,\r
4694 Attribute\r
4695 );\r
4696 if (EFI_ERROR (Status)) {\r
4697 ReturnStatus = Status;\r
4698 }\r
4699 }\r
4700 }\r
4701\r
4702 Private->TextOutMode.Attribute = (INT32) Attribute;\r
4703\r
4704 return ReturnStatus;\r
4705}\r
4706\r
a4d608d1 4707\r
4708/**\r
4709 Clears the output device(s) display to the currently selected background\r
4710 color.\r
4711\r
4712 @param This Protocol instance pointer.\r
4713\r
4714 @retval EFI_SUCCESS The operation completed successfully.\r
4715 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4716 the request.\r
4717 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.\r
4718\r
4719**/\r
95276127 4720EFI_STATUS\r
4721EFIAPI\r
4722ConSplitterTextOutClearScreen (\r
4723 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
4724 )\r
95276127 4725{\r
4726 EFI_STATUS Status;\r
4727 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4728 UINTN Index;\r
4729 EFI_STATUS ReturnStatus;\r
4730\r
4731 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4732\r
4733 //\r
4734 // return the worst status met\r
4735 //\r
4736 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4737\r
4738 if (Private->TextOutList[Index].TextOutEnabled) {\r
4739 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
4740 if (EFI_ERROR (Status)) {\r
4741 ReturnStatus = Status;\r
4742 }\r
4743 }\r
4744 }\r
4745\r
4746 Status = DevNullTextOutClearScreen (Private);\r
4747 if (EFI_ERROR (Status)) {\r
4748 ReturnStatus = Status;\r
4749 }\r
4750\r
4751 return ReturnStatus;\r
4752}\r
4753\r
a4d608d1 4754\r
4755/**\r
4756 Sets the current coordinates of the cursor position\r
4757\r
4758 @param This Protocol instance pointer.\r
33019a71 4759 @param Column The column position to set the cursor to. Must be\r
4760 greater than or equal to zero and less than the\r
4761 number of columns by QueryMode ().\r
4762 @param Row The row position to set the cursor to. Must be\r
a4d608d1 4763 greater than or equal to zero and less than the\r
33019a71 4764 number of rows by QueryMode ().\r
a4d608d1 4765\r
4766 @retval EFI_SUCCESS The operation completed successfully.\r
4767 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4768 the request.\r
4769 @retval EFI_UNSUPPORTED The output device is not in a valid text mode,\r
4770 or the cursor position is invalid for the\r
4771 current mode.\r
4772\r
4773**/\r
95276127 4774EFI_STATUS\r
4775EFIAPI\r
4776ConSplitterTextOutSetCursorPosition (\r
4777 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4778 IN UINTN Column,\r
4779 IN UINTN Row\r
4780 )\r
95276127 4781{\r
4782 EFI_STATUS Status;\r
4783 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4784 UINTN Index;\r
4785 EFI_STATUS ReturnStatus;\r
4786 UINTN MaxColumn;\r
4787 UINTN MaxRow;\r
de8fe2c2 4788 INT32 *TextOutModeMap;\r
4789 INT32 ModeNumber;\r
4790 INT32 CurrentMode;\r
95276127 4791\r
4792 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
de8fe2c2 4793 TextOutModeMap = NULL;\r
4794 ModeNumber = Private->TextOutMode.Mode;\r
7a5064ce 4795\r
de8fe2c2 4796 //\r
4797 // Get current MaxColumn and MaxRow from intersection map\r
4798 //\r
4799 if (Private->TextOutModeMap != NULL) {\r
4800 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4801 CurrentMode = *TextOutModeMap;\r
4802 } else {\r
4803 CurrentMode = ModeNumber;\r
4804 }\r
7a5064ce 4805\r
de8fe2c2 4806 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;\r
4807 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;\r
95276127 4808\r
4809 if (Column >= MaxColumn || Row >= MaxRow) {\r
4810 return EFI_UNSUPPORTED;\r
4811 }\r
4812 //\r
4813 // return the worst status met\r
4814 //\r
4815 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4816\r
4817 if (Private->TextOutList[Index].TextOutEnabled) {\r
4818 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (\r
4819 Private->TextOutList[Index].TextOut,\r
4820 Column,\r
4821 Row\r
4822 );\r
4823 if (EFI_ERROR (Status)) {\r
4824 ReturnStatus = Status;\r
4825 }\r
4826 }\r
4827 }\r
4828\r
4829 DevNullTextOutSetCursorPosition (Private, Column, Row);\r
4830\r
4831 return ReturnStatus;\r
4832}\r
4833\r
a4d608d1 4834\r
4835/**\r
4836 Makes the cursor visible or invisible\r
4837\r
4838 @param This Protocol instance pointer.\r
4839 @param Visible If TRUE, the cursor is set to be visible. If\r
4840 FALSE, the cursor is set to be invisible.\r
4841\r
4842 @retval EFI_SUCCESS The operation completed successfully.\r
4843 @retval EFI_DEVICE_ERROR The device had an error and could not complete\r
4844 the request, or the device does not support\r
4845 changing the cursor mode.\r
4846 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.\r
4847\r
4848**/\r
95276127 4849EFI_STATUS\r
4850EFIAPI\r
4851ConSplitterTextOutEnableCursor (\r
4852 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4853 IN BOOLEAN Visible\r
4854 )\r
95276127 4855{\r
4856 EFI_STATUS Status;\r
4857 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4858 UINTN Index;\r
4859 EFI_STATUS ReturnStatus;\r
4860\r
4861 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4862\r
4863 //\r
4864 // return the worst status met\r
4865 //\r
4866 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4867\r
4868 if (Private->TextOutList[Index].TextOutEnabled) {\r
4869 Status = Private->TextOutList[Index].TextOut->EnableCursor (\r
4870 Private->TextOutList[Index].TextOut,\r
4871 Visible\r
4872 );\r
4873 if (EFI_ERROR (Status)) {\r
4874 ReturnStatus = Status;\r
4875 }\r
4876 }\r
4877 }\r
4878\r
4879 DevNullTextOutEnableCursor (Private, Visible);\r
4880\r
4881 return ReturnStatus;\r
4882}\r
3012ce5c 4883\r