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