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