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