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