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