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