]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
Updated with the latest changes of build tools.
[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
66aa04e4 960 Status = gBS->OpenProtocol (\r
961 ControllerHandle,\r
962 &gEfiSimpleTextInputExProtocolGuid,\r
963 (VOID **) &TextInEx,\r
964 This->DriverBindingHandle,\r
965 mConIn.VirtualHandle,\r
966 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
967 );\r
968 if (EFI_ERROR (Status)) {\r
969 return Status;\r
970 }\r
971\r
972 Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
973 if (EFI_ERROR (Status)) {\r
974 return Status;\r
975 } \r
976\r
95276127 977 return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
978}\r
979\r
980EFI_STATUS\r
981EFIAPI\r
982ConSplitterSimplePointerDriverBindingStart (\r
983 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
984 IN EFI_HANDLE ControllerHandle,\r
985 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
986 )\r
987/*++\r
988\r
989Routine Description:\r
990 Start ConSplitter on ControllerHandle, and create the virtual\r
991 agrogated console device on first call Start for a SimpleTextIn handle.\r
992\r
993Arguments:\r
994 This - Pointer to protocol.\r
995 ControllerHandle - Controller handle.\r
996 RemainingDevicePath - Remaining device path.\r
997\r
998Returns:\r
999\r
1000 EFI_ERROR if a SimpleTextIn protocol is not started.\r
1001\r
1002--*/\r
1003{\r
1004 EFI_STATUS Status;\r
1005 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
1006\r
1007 Status = ConSplitterStart (\r
1008 This,\r
1009 ControllerHandle,\r
1010 mConIn.VirtualHandle,\r
1011 &gEfiSimplePointerProtocolGuid,\r
1012 &gEfiSimplePointerProtocolGuid,\r
1013 (VOID **) &SimplePointer\r
1014 );\r
1015 if (EFI_ERROR (Status)) {\r
1016 return Status;\r
1017 }\r
1018\r
1019 return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);\r
1020}\r
1021\r
1022EFI_STATUS\r
1023EFIAPI\r
1024ConSplitterConOutDriverBindingStart (\r
1025 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1026 IN EFI_HANDLE ControllerHandle,\r
1027 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1028 )\r
1029/*++\r
1030\r
1031Routine Description:\r
1032 Start ConSplitter on ControllerHandle, and create the virtual\r
1033 agrogated console device on first call Start for a SimpleTextIn handle.\r
1034\r
1035Arguments:\r
1036 This - Pointer to protocol.\r
1037 ControllerHandle - Controller handle.\r
1038 RemainingDevicePath - Remaining device path.\r
1039\r
1040Returns:\r
1041 EFI_ERROR if a SimpleTextIn protocol is not started.\r
1042\r
1043--*/\r
1044{\r
1045 EFI_STATUS Status;\r
1046 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1047 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
1048 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
1049\r
1050 Status = ConSplitterStart (\r
1051 This,\r
1052 ControllerHandle,\r
1053 mConOut.VirtualHandle,\r
1054 &gEfiConsoleOutDeviceGuid,\r
1055 &gEfiSimpleTextOutProtocolGuid,\r
1056 (VOID **) &TextOut\r
1057 );\r
1058 if (EFI_ERROR (Status)) {\r
1059 return Status;\r
1060 }\r
1061 //\r
1062 // Try to Open Graphics Output protocol\r
1063 //\r
1064 Status = gBS->OpenProtocol (\r
1065 ControllerHandle,\r
1066 &gEfiGraphicsOutputProtocolGuid,\r
1067 (VOID **) &GraphicsOutput,\r
1068 This->DriverBindingHandle,\r
1069 mConOut.VirtualHandle,\r
1070 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1071 );\r
1072 if (EFI_ERROR (Status)) {\r
1073 GraphicsOutput = NULL;\r
1074 }\r
1075 //\r
1076 // Open UGA_DRAW protocol\r
1077 //\r
1078 Status = gBS->OpenProtocol (\r
1079 ControllerHandle,\r
1080 &gEfiUgaDrawProtocolGuid,\r
1081 (VOID **) &UgaDraw,\r
1082 This->DriverBindingHandle,\r
1083 mConOut.VirtualHandle,\r
1084 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1085 );\r
1086 if (EFI_ERROR (Status)) {\r
1087 UgaDraw = NULL;\r
1088 }\r
1089 //\r
1090 // If both ConOut and StdErr incorporate the same Text Out device,\r
1091 // their MaxMode and QueryData should be the intersection of both.\r
1092 //\r
1093 Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
1094 ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
1095\r
d0c64728 1096 if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
1097 //\r
1098 // Match the UGA mode data of ConOut with the current mode\r
1099 //\r
1100 if (UgaDraw != NULL) {\r
1101 UgaDraw->GetMode (\r
1102 UgaDraw,\r
1103 &mConOut.UgaHorizontalResolution,\r
1104 &mConOut.UgaVerticalResolution,\r
1105 &mConOut.UgaColorDepth,\r
1106 &mConOut.UgaRefreshRate\r
1107 );\r
1108 }\r
1109 }\r
95276127 1110 return Status;\r
1111}\r
1112\r
1113EFI_STATUS\r
1114EFIAPI\r
1115ConSplitterStdErrDriverBindingStart (\r
1116 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1117 IN EFI_HANDLE ControllerHandle,\r
1118 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1119 )\r
1120/*++\r
1121\r
1122Routine Description:\r
1123 Start ConSplitter on ControllerHandle, and create the virtual\r
1124 agrogated console device on first call Start for a SimpleTextIn handle.\r
1125\r
1126Arguments:\r
1127 This - Pointer to protocol.\r
1128 ControllerHandle - Controller handle.\r
1129 RemainingDevicePath - Remaining device path.\r
1130\r
1131Returns:\r
1132 EFI_ERROR if a SimpleTextIn protocol is not started.\r
1133\r
1134--*/\r
1135{\r
1136 EFI_STATUS Status;\r
1137 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1138\r
1139 Status = ConSplitterStart (\r
1140 This,\r
1141 ControllerHandle,\r
1142 mStdErr.VirtualHandle,\r
1143 &gEfiStandardErrorDeviceGuid,\r
1144 &gEfiSimpleTextOutProtocolGuid,\r
1145 (VOID **) &TextOut\r
1146 );\r
1147 if (EFI_ERROR (Status)) {\r
1148 return Status;\r
1149 }\r
1150 //\r
1151 // If both ConOut and StdErr incorporate the same Text Out device,\r
1152 // their MaxMode and QueryData should be the intersection of both.\r
1153 //\r
1154 Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);\r
1155 ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));\r
1156 if (EFI_ERROR (Status)) {\r
1157 return Status;\r
1158 }\r
1159\r
1160 if (mStdErr.CurrentNumberOfConsoles == 1) {\r
1161 gST->StandardErrorHandle = mStdErr.VirtualHandle;\r
1162 gST->StdErr = &mStdErr.TextOut;\r
1163 //\r
1164 // Update the CRC32 in the EFI System Table header\r
1165 //\r
1166 gST->Hdr.CRC32 = 0;\r
1167 gBS->CalculateCrc32 (\r
1168 (UINT8 *) &gST->Hdr,\r
1169 gST->Hdr.HeaderSize,\r
1170 &gST->Hdr.CRC32\r
1171 );\r
1172 }\r
1173\r
1174 return Status;\r
1175}\r
1176\r
1177STATIC\r
1178EFI_STATUS\r
1179EFIAPI\r
1180ConSplitterStop (\r
1181 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1182 IN EFI_HANDLE ControllerHandle,\r
1183 IN EFI_HANDLE ConSplitterVirtualHandle,\r
1184 IN EFI_GUID *DeviceGuid,\r
1185 IN EFI_GUID *InterfaceGuid,\r
1186 IN VOID **Interface\r
1187 )\r
1188/*++\r
1189\r
1190Routine Description:\r
1191\r
1192Arguments:\r
1193 (Standard DriverBinding Protocol Stop() function)\r
1194\r
1195Returns:\r
1196\r
1197 None\r
1198\r
1199--*/\r
1200{\r
1201 EFI_STATUS Status;\r
1202\r
1203 Status = gBS->OpenProtocol (\r
1204 ControllerHandle,\r
1205 InterfaceGuid,\r
1206 Interface,\r
1207 This->DriverBindingHandle,\r
1208 ControllerHandle,\r
1209 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1210 );\r
1211 if (EFI_ERROR (Status)) {\r
1212 return Status;\r
1213 }\r
1214 //\r
1215 // close the protocol refered.\r
1216 //\r
1217 gBS->CloseProtocol (\r
1218 ControllerHandle,\r
1219 DeviceGuid,\r
1220 This->DriverBindingHandle,\r
1221 ConSplitterVirtualHandle\r
1222 );\r
1223 gBS->CloseProtocol (\r
1224 ControllerHandle,\r
1225 DeviceGuid,\r
1226 This->DriverBindingHandle,\r
1227 ControllerHandle\r
1228 );\r
1229\r
1230 return EFI_SUCCESS;\r
1231}\r
1232\r
1233EFI_STATUS\r
1234EFIAPI\r
1235ConSplitterConInDriverBindingStop (\r
1236 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1237 IN EFI_HANDLE ControllerHandle,\r
1238 IN UINTN NumberOfChildren,\r
1239 IN EFI_HANDLE *ChildHandleBuffer\r
1240 )\r
1241/*++\r
1242\r
1243Routine Description:\r
1244\r
1245Arguments:\r
1246 (Standard DriverBinding Protocol Stop() function)\r
1247\r
1248Returns:\r
1249\r
1250 None\r
1251\r
1252--*/\r
1253{\r
1254 EFI_STATUS Status;\r
1255 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
1256\r
66aa04e4 1257 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
95276127 1258 if (NumberOfChildren == 0) {\r
1259 return EFI_SUCCESS;\r
1260 }\r
1261\r
66aa04e4 1262 Status = gBS->OpenProtocol (\r
1263 ControllerHandle,\r
1264 &gEfiSimpleTextInputExProtocolGuid,\r
1265 (VOID **) &TextInEx,\r
1266 This->DriverBindingHandle,\r
1267 ControllerHandle,\r
1268 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1269 );\r
1270 if (EFI_ERROR (Status)) {\r
1271 return Status;\r
1272 }\r
1273\r
1274 Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
1275 if (EFI_ERROR (Status)) {\r
1276 return Status;\r
1277 }\r
1278 \r
1279 \r
95276127 1280 Status = ConSplitterStop (\r
1281 This,\r
1282 ControllerHandle,\r
1283 mConIn.VirtualHandle,\r
1284 &gEfiConsoleInDeviceGuid,\r
1285 &gEfiSimpleTextInProtocolGuid,\r
1286 (VOID **) &TextIn\r
1287 );\r
1288 if (EFI_ERROR (Status)) {\r
1289 return Status;\r
1290 }\r
1291 //\r
1292 // Delete this console input device's data structures.\r
1293 //\r
1294 return ConSplitterTextInDeleteDevice (&mConIn, TextIn);\r
1295}\r
1296\r
1297EFI_STATUS\r
1298EFIAPI\r
1299ConSplitterSimplePointerDriverBindingStop (\r
1300 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1301 IN EFI_HANDLE ControllerHandle,\r
1302 IN UINTN NumberOfChildren,\r
1303 IN EFI_HANDLE *ChildHandleBuffer\r
1304 )\r
1305/*++\r
1306\r
1307Routine Description:\r
1308\r
1309Arguments:\r
1310 (Standard DriverBinding Protocol Stop() function)\r
1311\r
1312Returns:\r
1313\r
1314 None\r
1315\r
1316--*/\r
1317{\r
1318 EFI_STATUS Status;\r
1319 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
1320\r
1321 if (NumberOfChildren == 0) {\r
1322 return EFI_SUCCESS;\r
1323 }\r
1324\r
1325 Status = ConSplitterStop (\r
1326 This,\r
1327 ControllerHandle,\r
1328 mConIn.VirtualHandle,\r
1329 &gEfiSimplePointerProtocolGuid,\r
1330 &gEfiSimplePointerProtocolGuid,\r
1331 (VOID **) &SimplePointer\r
1332 );\r
1333 if (EFI_ERROR (Status)) {\r
1334 return Status;\r
1335 }\r
1336 //\r
1337 // Delete this console input device's data structures.\r
1338 //\r
1339 return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);\r
1340}\r
1341\r
1342EFI_STATUS\r
1343EFIAPI\r
1344ConSplitterConOutDriverBindingStop (\r
1345 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1346 IN EFI_HANDLE ControllerHandle,\r
1347 IN UINTN NumberOfChildren,\r
1348 IN EFI_HANDLE *ChildHandleBuffer\r
1349 )\r
1350/*++\r
1351\r
1352Routine Description:\r
1353\r
1354Arguments:\r
1355 (Standard DriverBinding Protocol Stop() function)\r
1356\r
1357Returns:\r
1358\r
1359 None\r
1360\r
1361--*/\r
1362{\r
1363 EFI_STATUS Status;\r
1364 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1365\r
1366 if (NumberOfChildren == 0) {\r
1367 return EFI_SUCCESS;\r
1368 }\r
1369\r
1370 Status = ConSplitterStop (\r
1371 This,\r
1372 ControllerHandle,\r
1373 mConOut.VirtualHandle,\r
1374 &gEfiConsoleOutDeviceGuid,\r
1375 &gEfiSimpleTextOutProtocolGuid,\r
1376 (VOID **) &TextOut\r
1377 );\r
1378 if (EFI_ERROR (Status)) {\r
1379 return Status;\r
1380 }\r
1381\r
1382 //\r
1383 // Delete this console output device's data structures.\r
1384 //\r
1385 return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);\r
1386}\r
1387\r
1388EFI_STATUS\r
1389EFIAPI\r
1390ConSplitterStdErrDriverBindingStop (\r
1391 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1392 IN EFI_HANDLE ControllerHandle,\r
1393 IN UINTN NumberOfChildren,\r
1394 IN EFI_HANDLE *ChildHandleBuffer\r
1395 )\r
1396/*++\r
1397\r
1398Routine Description:\r
1399\r
1400Arguments:\r
1401 (Standard DriverBinding Protocol Stop() function)\r
1402\r
1403Returns:\r
1404\r
1405 EFI_SUCCESS - Complete successfully.\r
1406\r
1407--*/\r
1408{\r
1409 EFI_STATUS Status;\r
1410 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1411\r
1412 if (NumberOfChildren == 0) {\r
1413 return EFI_SUCCESS;\r
1414 }\r
1415\r
1416 Status = ConSplitterStop (\r
1417 This,\r
1418 ControllerHandle,\r
1419 mStdErr.VirtualHandle,\r
1420 &gEfiStandardErrorDeviceGuid,\r
1421 &gEfiSimpleTextOutProtocolGuid,\r
1422 (VOID **) &TextOut\r
1423 );\r
1424 if (EFI_ERROR (Status)) {\r
1425 return Status;\r
1426 }\r
1427 //\r
1428 // Delete this console error out device's data structures.\r
1429 //\r
1430 Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
1431 if (EFI_ERROR (Status)) {\r
1432 return Status;\r
1433 }\r
1434\r
1435 if (mStdErr.CurrentNumberOfConsoles == 0) {\r
1436 gST->StandardErrorHandle = NULL;\r
1437 gST->StdErr = NULL;\r
1438 //\r
1439 // Update the CRC32 in the EFI System Table header\r
1440 //\r
1441 gST->Hdr.CRC32 = 0;\r
1442 gBS->CalculateCrc32 (\r
1443 (UINT8 *) &gST->Hdr,\r
1444 gST->Hdr.HeaderSize,\r
1445 &gST->Hdr.CRC32\r
1446 );\r
1447 }\r
1448\r
1449 return Status;\r
1450}\r
1451\r
1452EFI_STATUS\r
1453ConSplitterGrowBuffer (\r
1454 IN UINTN SizeOfCount,\r
1455 IN UINTN *Count,\r
1456 IN OUT VOID **Buffer\r
1457 )\r
1458/*++\r
1459\r
1460Routine Description:\r
1461 Take the passed in Buffer of size SizeOfCount and grow the buffer\r
1462 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount\r
1463 bytes. Copy the current data in Buffer to the new version of Buffer\r
1464 and free the old version of buffer.\r
1465\r
1466\r
1467Arguments:\r
1468 SizeOfCount - Size of element in array\r
1469 Count - Current number of elements in array\r
1470 Buffer - Bigger version of passed in Buffer with all the data\r
1471\r
1472Returns:\r
1473 EFI_SUCCESS - Buffer size has grown\r
1474 EFI_OUT_OF_RESOURCES - Could not grow the buffer size\r
1475\r
1476 None\r
1477\r
1478--*/\r
1479{\r
1480 UINTN NewSize;\r
1481 UINTN OldSize;\r
1482 VOID *Ptr;\r
1483\r
1484 //\r
1485 // grow the buffer to new buffer size,\r
1486 // copy the old buffer's content to the new-size buffer,\r
1487 // then free the old buffer.\r
1488 //\r
1489 OldSize = *Count * SizeOfCount;\r
1490 *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
1491 NewSize = *Count * SizeOfCount;\r
1492\r
1493 Ptr = AllocateZeroPool (NewSize);\r
1494 if (Ptr == NULL) {\r
1495 return EFI_OUT_OF_RESOURCES;\r
1496 }\r
1497\r
1498 CopyMem (Ptr, *Buffer, OldSize);\r
1499\r
1500 if (*Buffer != NULL) {\r
1501 FreePool (*Buffer);\r
1502 }\r
1503\r
1504 *Buffer = Ptr;\r
1505\r
1506 return EFI_SUCCESS;\r
1507}\r
1508\r
1509EFI_STATUS\r
1510ConSplitterTextInAddDevice (\r
1511 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1512 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1513 )\r
1514/*++\r
1515\r
1516Routine Description:\r
1517\r
1518Arguments:\r
1519\r
1520Returns:\r
1521\r
1522 EFI_SUCCESS\r
1523 EFI_OUT_OF_RESOURCES\r
1524\r
1525--*/\r
1526{\r
1527 EFI_STATUS Status;\r
1528\r
1529 //\r
1530 // If the Text In List is full, enlarge it by calling growbuffer().\r
1531 //\r
1532 if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {\r
1533 Status = ConSplitterGrowBuffer (\r
1534 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
1535 &Private->TextInListCount,\r
1536 (VOID **) &Private->TextInList\r
1537 );\r
1538 if (EFI_ERROR (Status)) {\r
1539 return EFI_OUT_OF_RESOURCES;\r
1540 }\r
1541 }\r
1542 //\r
1543 // Add the new text-in device data structure into the Text In List.\r
1544 //\r
1545 Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;\r
1546 Private->CurrentNumberOfConsoles++;\r
1547\r
1548 //\r
1549 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1550 //\r
1551 gBS->CheckEvent (TextIn->WaitForKey);\r
1552\r
1553 return EFI_SUCCESS;\r
1554}\r
1555\r
1556EFI_STATUS\r
1557ConSplitterTextInDeleteDevice (\r
1558 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1559 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1560 )\r
1561/*++\r
1562\r
1563Routine Description:\r
1564\r
1565Arguments:\r
1566\r
1567Returns:\r
1568\r
1569 EFI_SUCCESS\r
1570 EFI_NOT_FOUND\r
1571\r
1572--*/\r
1573{\r
1574 UINTN Index;\r
1575 //\r
1576 // Remove the specified text-in device data structure from the Text In List,\r
1577 // and rearrange the remaining data structures in the Text In List.\r
1578 //\r
1579 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
1580 if (Private->TextInList[Index] == TextIn) {\r
1581 for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
1582 Private->TextInList[Index] = Private->TextInList[Index + 1];\r
1583 }\r
1584\r
1585 Private->CurrentNumberOfConsoles--;\r
1586 return EFI_SUCCESS;\r
1587 }\r
1588 }\r
1589\r
1590 return EFI_NOT_FOUND;\r
1591}\r
1592\r
66aa04e4 1593EFI_STATUS\r
1594ConSplitterTextInExAddDevice (\r
1595 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1596 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
1597 )\r
1598{\r
1599 EFI_STATUS Status;\r
1600\r
1601 //\r
1602 // If the TextInEx List is full, enlarge it by calling growbuffer().\r
1603 //\r
1604 if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
1605 Status = ConSplitterGrowBuffer (\r
1606 sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
1607 &Private->TextInExListCount,\r
1608 (VOID **) &Private->TextInExList\r
1609 );\r
1610 if (EFI_ERROR (Status)) {\r
1611 return EFI_OUT_OF_RESOURCES;\r
1612 }\r
1613 }\r
1614 //\r
1615 // Add the new text-in device data structure into the Text In List.\r
1616 //\r
1617 Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
1618 Private->CurrentNumberOfExConsoles++;\r
1619\r
1620 //\r
1621 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1622 //\r
1623 gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
1624\r
1625 return EFI_SUCCESS;\r
1626}\r
1627\r
1628EFI_STATUS\r
1629ConSplitterTextInExDeleteDevice (\r
1630 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1631 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
1632 )\r
1633{\r
1634 UINTN Index;\r
1635 //\r
1636 // Remove the specified text-in device data structure from the Text In List,\r
1637 // and rearrange the remaining data structures in the Text In List.\r
1638 //\r
1639 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
1640 if (Private->TextInExList[Index] == TextInEx) {\r
1641 for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
1642 Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
1643 }\r
1644\r
1645 Private->CurrentNumberOfExConsoles--;\r
1646 return EFI_SUCCESS;\r
1647 }\r
1648 }\r
1649\r
1650 return EFI_NOT_FOUND;\r
1651}\r
1652\r
95276127 1653EFI_STATUS\r
1654ConSplitterSimplePointerAddDevice (\r
1655 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1656 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1657 )\r
1658/*++\r
1659\r
1660Routine Description:\r
1661\r
1662Arguments:\r
1663\r
1664Returns:\r
1665\r
1666 EFI_OUT_OF_RESOURCES\r
1667 EFI_SUCCESS\r
1668\r
1669--*/\r
1670{\r
1671 EFI_STATUS Status;\r
1672\r
1673 //\r
1674 // If the Text In List is full, enlarge it by calling growbuffer().\r
1675 //\r
1676 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {\r
1677 Status = ConSplitterGrowBuffer (\r
1678 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
1679 &Private->PointerListCount,\r
1680 (VOID **) &Private->PointerList\r
1681 );\r
1682 if (EFI_ERROR (Status)) {\r
1683 return EFI_OUT_OF_RESOURCES;\r
1684 }\r
1685 }\r
1686 //\r
1687 // Add the new text-in device data structure into the Text In List.\r
1688 //\r
1689 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;\r
1690 Private->CurrentNumberOfPointers++;\r
1691 return EFI_SUCCESS;\r
1692}\r
1693\r
1694EFI_STATUS\r
1695ConSplitterSimplePointerDeleteDevice (\r
1696 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1697 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1698 )\r
1699/*++\r
1700\r
1701Routine Description:\r
1702\r
1703Arguments:\r
1704\r
1705Returns:\r
1706\r
1707 None\r
1708\r
1709--*/\r
1710{\r
1711 UINTN Index;\r
1712 //\r
1713 // Remove the specified text-in device data structure from the Text In List,\r
1714 // and rearrange the remaining data structures in the Text In List.\r
1715 //\r
1716 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
1717 if (Private->PointerList[Index] == SimplePointer) {\r
1718 for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
1719 Private->PointerList[Index] = Private->PointerList[Index + 1];\r
1720 }\r
1721\r
1722 Private->CurrentNumberOfPointers--;\r
1723 return EFI_SUCCESS;\r
1724 }\r
1725 }\r
1726\r
1727 return EFI_NOT_FOUND;\r
1728}\r
1729\r
1730STATIC\r
1731EFI_STATUS\r
1732ConSplitterGrowMapTable (\r
1733 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
1734 )\r
1735/*++\r
1736\r
1737Routine Description:\r
1738\r
1739Arguments:\r
1740\r
1741Returns:\r
1742\r
1743 None\r
1744\r
1745--*/\r
1746{\r
1747 UINTN Size;\r
1748 UINTN NewSize;\r
1749 UINTN TotalSize;\r
1750 INT32 *TextOutModeMap;\r
1751 INT32 *OldTextOutModeMap;\r
1752 INT32 *SrcAddress;\r
1753 INT32 Index;\r
1754\r
1755 NewSize = Private->TextOutListCount * sizeof (INT32);\r
1756 OldTextOutModeMap = Private->TextOutModeMap;\r
1757 TotalSize = NewSize * Private->TextOutQueryDataCount;\r
1758\r
1759 TextOutModeMap = AllocateZeroPool (TotalSize);\r
1760 if (TextOutModeMap == NULL) {\r
1761 return EFI_OUT_OF_RESOURCES;\r
1762 }\r
1763\r
1764 SetMem (TextOutModeMap, TotalSize, 0xFF);\r
1765 Private->TextOutModeMap = TextOutModeMap;\r
1766\r
1767 //\r
1768 // If TextOutList has been enlarged, need to realloc the mode map table\r
1769 // The mode map table is regarded as a two dimension array.\r
1770 //\r
1771 // Old New\r
1772 // 0 ---------> TextOutListCount ----> TextOutListCount\r
1773 // | -------------------------------------------\r
1774 // | | | |\r
1775 // | | | |\r
1776 // | | | |\r
1777 // | | | |\r
1778 // | | | |\r
1779 // \/ | | |\r
1780 // -------------------------------------------\r
1781 // QueryDataCount\r
1782 //\r
1783 if (OldTextOutModeMap != NULL) {\r
1784\r
1785 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
1786 Index = 0;\r
1787 SrcAddress = OldTextOutModeMap;\r
1788\r
1789 //\r
1790 // Copy the old data to the new one\r
1791 //\r
1792 while (Index < Private->TextOutMode.MaxMode) {\r
1793 CopyMem (TextOutModeMap, SrcAddress, Size);\r
1794 TextOutModeMap += NewSize;\r
1795 SrcAddress += Size;\r
1796 Index++;\r
1797 }\r
1798 //\r
1799 // Free the old buffer\r
1800 //\r
1801 FreePool (OldTextOutModeMap);\r
1802 }\r
1803\r
1804 return EFI_SUCCESS;\r
1805}\r
1806\r
1807STATIC\r
1808EFI_STATUS\r
1809ConSplitterAddOutputMode (\r
1810 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1811 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
1812 )\r
1813/*++\r
1814\r
1815Routine Description:\r
1816\r
1817Arguments:\r
1818\r
1819Returns:\r
1820\r
1821 None\r
1822\r
1823--*/\r
1824{\r
1825 EFI_STATUS Status;\r
1826 INT32 MaxMode;\r
1827 INT32 Mode;\r
1828 UINTN Index;\r
1829\r
1830 MaxMode = TextOut->Mode->MaxMode;\r
1831 Private->TextOutMode.MaxMode = MaxMode;\r
1832\r
1833 //\r
1834 // Grow the buffer if query data buffer is not large enough to\r
1835 // hold all the mode supported by the first console.\r
1836 //\r
1837 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {\r
1838 Status = ConSplitterGrowBuffer (\r
1839 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
1840 &Private->TextOutQueryDataCount,\r
1841 (VOID **) &Private->TextOutQueryData\r
1842 );\r
1843 if (EFI_ERROR (Status)) {\r
1844 return EFI_OUT_OF_RESOURCES;\r
1845 }\r
1846 }\r
1847 //\r
1848 // Allocate buffer for the output mode map\r
1849 //\r
1850 Status = ConSplitterGrowMapTable (Private);\r
1851 if (EFI_ERROR (Status)) {\r
1852 return EFI_OUT_OF_RESOURCES;\r
1853 }\r
1854 //\r
1855 // As the first textout device, directly add the mode in to QueryData\r
1856 // and at the same time record the mapping between QueryData and TextOut.\r
1857 //\r
1858 Mode = 0;\r
1859 Index = 0;\r
1860 while (Mode < MaxMode) {\r
1861 TextOut->QueryMode (\r
1862 TextOut,\r
1863 Mode,\r
1864 &Private->TextOutQueryData[Mode].Columns,\r
1865 &Private->TextOutQueryData[Mode].Rows\r
1866 );\r
1867 Private->TextOutModeMap[Index] = Mode;\r
1868 Mode++;\r
1869 Index += Private->TextOutListCount;\r
1870 }\r
1871\r
1872 return EFI_SUCCESS;\r
1873}\r
1874\r
1875STATIC\r
1876VOID\r
1877ConSplitterGetIntersection (\r
1878 IN INT32 *TextOutModeMap,\r
1879 IN INT32 *NewlyAddedMap,\r
1880 IN UINTN MapStepSize,\r
1881 IN UINTN NewMapStepSize,\r
1882 OUT INT32 *MaxMode,\r
1883 OUT INT32 *CurrentMode\r
1884 )\r
1885{\r
1886 INT32 Index;\r
1887 INT32 *CurrentMapEntry;\r
1888 INT32 *NextMapEntry;\r
1889 INT32 CurrentMaxMode;\r
1890 INT32 Mode;\r
1891\r
1892 Index = 0;\r
1893 CurrentMapEntry = TextOutModeMap;\r
1894 NextMapEntry = TextOutModeMap;\r
1895 CurrentMaxMode = *MaxMode;\r
1896 Mode = *CurrentMode;\r
1897\r
1898 while (Index < CurrentMaxMode) {\r
1899 if (*NewlyAddedMap == -1) {\r
1900 //\r
1901 // This mode is not supported any more. Remove it. Special care\r
1902 // must be taken as this remove will also affect current mode;\r
1903 //\r
1904 if (Index == *CurrentMode) {\r
1905 Mode = -1;\r
1906 } else if (Index < *CurrentMode) {\r
1907 Mode--;\r
1908 }\r
1909 (*MaxMode)--;\r
1910 } else {\r
1911 if (CurrentMapEntry != NextMapEntry) {\r
1912 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));\r
1913 }\r
1914\r
1915 NextMapEntry += MapStepSize;\r
1916 }\r
1917\r
1918 CurrentMapEntry += MapStepSize;\r
1919 NewlyAddedMap += NewMapStepSize;\r
1920 Index++;\r
1921 }\r
1922\r
1923 *CurrentMode = Mode;\r
1924\r
1925 return ;\r
1926}\r
1927\r
1928STATIC\r
1929VOID\r
1930ConSplitterSyncOutputMode (\r
1931 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1932 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
1933 )\r
1934/*++\r
1935\r
1936Routine Description:\r
1937\r
1938Arguments:\r
1939 Private - Private data structure.\r
1940 TextOut - Text Out Protocol.\r
1941Returns:\r
1942\r
1943 None\r
1944\r
1945--*/\r
1946{\r
1947 INT32 CurrentMaxMode;\r
1948 INT32 Mode;\r
1949 INT32 Index;\r
1950 INT32 *TextOutModeMap;\r
1951 INT32 *MapTable;\r
1952 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;\r
1953 UINTN Rows;\r
1954 UINTN Columns;\r
1955 UINTN StepSize;\r
1956\r
1957 //\r
1958 // Must make sure that current mode won't change even if mode number changes\r
1959 //\r
1960 CurrentMaxMode = Private->TextOutMode.MaxMode;\r
1961 TextOutModeMap = Private->TextOutModeMap;\r
1962 StepSize = Private->TextOutListCount;\r
1963 TextOutQueryData = Private->TextOutQueryData;\r
1964\r
1965 //\r
1966 // Query all the mode that the newly added TextOut supports\r
1967 //\r
1968 Mode = 0;\r
1969 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
1970 while (Mode < TextOut->Mode->MaxMode) {\r
1971 TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
1972\r
1973 //\r
1974 // Search the QueryData database to see if they intersects\r
1975 //\r
1976 Index = 0;\r
1977 while (Index < CurrentMaxMode) {\r
1978 if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
1979 MapTable[Index * StepSize] = Mode;\r
1980 break;\r
1981 }\r
1982\r
1983 Index++;\r
1984 }\r
1985\r
1986 Mode++;\r
1987 }\r
1988 //\r
1989 // Now search the TextOutModeMap table to find the intersection of supported\r
1990 // mode between ConSplitter and the newly added device.\r
1991 //\r
1992 ConSplitterGetIntersection (\r
1993 TextOutModeMap,\r
1994 MapTable,\r
1995 StepSize,\r
1996 StepSize,\r
1997 &Private->TextOutMode.MaxMode,\r
1998 &Private->TextOutMode.Mode\r
1999 );\r
2000\r
2001 return ;\r
2002}\r
2003\r
2004STATIC\r
2005EFI_STATUS\r
2006ConSplitterGetIntersectionBetweenConOutAndStrErr (\r
2007 VOID\r
2008 )\r
2009/*++\r
2010\r
2011Routine Description:\r
2012\r
2013Arguments:\r
2014\r
2015Returns:\r
2016\r
2017 None\r
2018 EFI_OUT_OF_RESOURCES\r
2019\r
2020--*/\r
2021{\r
2022 UINTN ConOutNumOfConsoles;\r
2023 UINTN StdErrNumOfConsoles;\r
2024 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;\r
2025 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;\r
2026 UINTN Indexi;\r
2027 UINTN Indexj;\r
2028 UINTN Rows;\r
2029 UINTN Columns;\r
2030 INT32 ConOutMaxMode;\r
2031 INT32 StdErrMaxMode;\r
2032 INT32 Mode;\r
2033 INT32 Index;\r
2034 INT32 *ConOutModeMap;\r
2035 INT32 *StdErrModeMap;\r
2036 INT32 *ConOutMapTable;\r
2037 INT32 *StdErrMapTable;\r
2038 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;\r
2039 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;\r
2040 BOOLEAN FoundTheSameTextOut;\r
2041 UINTN ConOutMapTableSize;\r
2042 UINTN StdErrMapTableSize;\r
2043\r
2044 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;\r
2045 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;\r
2046 ConOutTextOutList = mConOut.TextOutList;\r
2047 StdErrTextOutList = mStdErr.TextOutList;\r
2048\r
2049 Indexi = 0;\r
2050 FoundTheSameTextOut = FALSE;\r
2051 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {\r
2052 Indexj = 0;\r
2053 while (Indexj < StdErrNumOfConsoles) {\r
2054 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {\r
2055 FoundTheSameTextOut = TRUE;\r
2056 break;\r
2057 }\r
2058\r
2059 Indexj++;\r
2060 StdErrTextOutList++;\r
2061 }\r
2062\r
2063 Indexi++;\r
2064 ConOutTextOutList++;\r
2065 }\r
2066\r
2067 if (!FoundTheSameTextOut) {\r
2068 return EFI_SUCCESS;\r
2069 }\r
2070 //\r
2071 // Must make sure that current mode won't change even if mode number changes\r
2072 //\r
2073 ConOutMaxMode = mConOut.TextOutMode.MaxMode;\r
2074 ConOutModeMap = mConOut.TextOutModeMap;\r
2075 ConOutQueryData = mConOut.TextOutQueryData;\r
2076\r
2077 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;\r
2078 StdErrModeMap = mStdErr.TextOutModeMap;\r
2079 StdErrQueryData = mStdErr.TextOutQueryData;\r
2080\r
2081 //\r
2082 // Allocate the map table and set the map table's index to -1.\r
2083 //\r
2084 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);\r
2085 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);\r
2086 if (ConOutMapTable == NULL) {\r
2087 return EFI_OUT_OF_RESOURCES;\r
2088 }\r
2089\r
2090 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);\r
2091\r
2092 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);\r
2093 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);\r
2094 if (StdErrMapTable == NULL) {\r
2095 return EFI_OUT_OF_RESOURCES;\r
2096 }\r
2097\r
2098 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);\r
2099\r
2100 //\r
2101 // Find the intersection of the two set of modes. If they actually intersect, the\r
2102 // correponding entry in the map table is set to 1.\r
2103 //\r
2104 Mode = 0;\r
2105 while (Mode < ConOutMaxMode) {\r
2106 //\r
2107 // Search the other's QueryData database to see if they intersect\r
2108 //\r
2109 Index = 0;\r
2110 Rows = ConOutQueryData[Mode].Rows;\r
2111 Columns = ConOutQueryData[Mode].Columns;\r
2112 while (Index < StdErrMaxMode) {\r
2113 if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
2114 ConOutMapTable[Mode] = 1;\r
2115 StdErrMapTable[Index] = 1;\r
2116 break;\r
2117 }\r
2118\r
2119 Index++;\r
2120 }\r
2121\r
2122 Mode++;\r
2123 }\r
2124 //\r
2125 // Now search the TextOutModeMap table to find the intersection of supported\r
2126 // mode between ConSplitter and the newly added device.\r
2127 //\r
2128 ConSplitterGetIntersection (\r
2129 ConOutModeMap,\r
2130 ConOutMapTable,\r
2131 mConOut.TextOutListCount,\r
2132 1,\r
2133 &(mConOut.TextOutMode.MaxMode),\r
2134 &(mConOut.TextOutMode.Mode)\r
2135 );\r
2136 if (mConOut.TextOutMode.Mode < 0) {\r
2137 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);\r
2138 }\r
2139\r
2140 ConSplitterGetIntersection (\r
2141 StdErrModeMap,\r
2142 StdErrMapTable,\r
2143 mStdErr.TextOutListCount,\r
2144 1,\r
2145 &(mStdErr.TextOutMode.MaxMode),\r
2146 &(mStdErr.TextOutMode.Mode)\r
2147 );\r
2148 if (mStdErr.TextOutMode.Mode < 0) {\r
2149 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);\r
2150 }\r
2151\r
2152 FreePool (ConOutMapTable);\r
2153 FreePool (StdErrMapTable);\r
2154\r
2155 return EFI_SUCCESS;\r
2156}\r
2157\r
2158STATIC\r
2159EFI_STATUS\r
2160ConSplitterAddGraphicsOutputMode (\r
2161 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2162 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2163 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2164 )\r
2165/*++\r
2166\r
2167Routine Description:\r
2168\r
2169Arguments:\r
2170\r
2171Returns:\r
2172\r
2173 None\r
2174\r
2175--*/\r
2176{\r
2177 EFI_STATUS Status;\r
2178 UINTN Index;\r
2179 TEXT_OUT_GOP_MODE *Mode;\r
2180 UINTN SizeOfInfo;\r
2181 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
2182 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;\r
2183 TEXT_OUT_GOP_MODE *ModeBuffer;\r
2184 TEXT_OUT_GOP_MODE *MatchedMode;\r
2185 UINTN NumberIndex;\r
2186 BOOLEAN Match;\r
2187\r
2188 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2189 return EFI_UNSUPPORTED;\r
2190 }\r
2191\r
2192 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
2193\r
2194 if (GraphicsOutput != NULL) {\r
2195 if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
2196 //\r
2197 // This is the first Graphics Output device added\r
2198 //\r
2199 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;\r
2200 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;\r
2201 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);\r
2202 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;\r
2203 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;\r
2204 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;\r
2205\r
2206 //\r
2207 // Allocate resource for the private mode buffer\r
2208 //\r
2209 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);\r
2210 if (ModeBuffer == NULL) {\r
2211 return EFI_OUT_OF_RESOURCES;\r
2212 }\r
2213 FreePool (Private->GraphicsOutputModeBuffer);\r
2214 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2215\r
2216 //\r
2217 // Store all supported display modes to the private mode buffer\r
2218 //\r
2219 Mode = ModeBuffer;\r
2220 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {\r
2221 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);\r
2222 if (EFI_ERROR (Status)) {\r
2223 return Status;\r
2224 }\r
2225 Mode->HorizontalResolution = Info->HorizontalResolution;\r
2226 Mode->VerticalResolution = Info->VerticalResolution;\r
2227 Mode++;\r
2228 FreePool (Info);\r
2229 }\r
2230 } else {\r
2231 //\r
2232 // Check intersection of display mode\r
2233 //\r
2234 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);\r
2235 if (ModeBuffer == NULL) {\r
2236 return EFI_OUT_OF_RESOURCES;\r
2237 }\r
2238\r
2239 MatchedMode = ModeBuffer;\r
2240 Mode = &Private->GraphicsOutputModeBuffer[0];\r
2241 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2242 Match = FALSE;\r
2243\r
2244 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {\r
2245 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
2246 if (EFI_ERROR (Status)) {\r
2247 return Status;\r
2248 }\r
2249 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
2250 (Info->VerticalResolution == Mode->VerticalResolution)){\r
2251 Match = TRUE;\r
2252 FreePool (Info);\r
2253 break;\r
2254 }\r
2255 FreePool (Info);\r
2256 }\r
2257\r
2258 if (Match) {\r
2259 CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));\r
2260 MatchedMode++;\r
2261 }\r
2262\r
2263 Mode++;\r
2264 }\r
2265\r
2266 //\r
2267 // Drop the old mode buffer, assign it to a new one\r
2268 //\r
2269 FreePool (Private->GraphicsOutputModeBuffer);\r
2270 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2271\r
2272 //\r
2273 // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
2274 //\r
2275 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));\r
2276 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2277 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2278 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2279 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2280 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2281 }\r
2282\r
2283 //\r
2284 // Select a prefered Display mode 800x600\r
2285 //\r
2286 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2287 Mode = &Private->GraphicsOutputModeBuffer[Index];\r
2288 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
2289 break;\r
2290 }\r
2291 }\r
2292 //\r
2293 // Prefered mode is not found, set to mode 0\r
2294 //\r
2295 if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
2296 Index = 0;\r
2297 }\r
2298\r
2299 //\r
2300 // Current mode number may need update now, so set it to an invalide mode number\r
2301 //\r
2302 CurrentGraphicsOutputMode->Mode = 0xffff;\r
2303 } else {\r
2304 //\r
2305 // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
2306 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\r
2307 //\r
2308 CurrentGraphicsOutputMode->MaxMode = 1;\r
2309 CurrentGraphicsOutputMode->Info->Version = 0;\r
2310 CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;\r
2311 CurrentGraphicsOutputMode->Info->VerticalResolution = 600;\r
2312 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2313 CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;\r
2314 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2315 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2316 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2317\r
2318 //\r
2319 // Update the private mode buffer\r
2320 //\r
2321 ModeBuffer = &Private->GraphicsOutputModeBuffer[0];\r
2322 ModeBuffer->HorizontalResolution = 800;\r
2323 ModeBuffer->VerticalResolution = 600;\r
2324\r
2325 //\r
2326 // Current mode is unknow now, set it to an invalid mode number 0xffff\r
2327 //\r
2328 CurrentGraphicsOutputMode->Mode = 0xffff;\r
2329 Index = 0;\r
2330 }\r
2331\r
2332 //\r
2333 // Force GraphicsOutput mode to be set,\r
2334 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
2335 //\r
2336 Private->HardwareNeedsStarting = TRUE;\r
2337 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
2338\r
2339 Private->CurrentNumberOfGraphicsOutput++;\r
2340\r
2341 return Status;\r
2342}\r
2343\r
2344EFI_STATUS\r
2345ConSplitterTextOutAddDevice (\r
2346 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2347 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,\r
2348 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2349 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2350 )\r
2351/*++\r
2352\r
2353Routine Description:\r
2354\r
2355Arguments:\r
2356\r
2357Returns:\r
2358\r
2359 None\r
2360\r
2361--*/\r
2362{\r
2363 EFI_STATUS Status;\r
2364 UINTN CurrentNumOfConsoles;\r
2365 INT32 CurrentMode;\r
2366 INT32 MaxMode;\r
2367 TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
2368\r
2369 Status = EFI_SUCCESS;\r
2370 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2371\r
2372 //\r
2373 // If the Text Out List is full, enlarge it by calling growbuffer().\r
2374 //\r
2375 while (CurrentNumOfConsoles >= Private->TextOutListCount) {\r
2376 Status = ConSplitterGrowBuffer (\r
2377 sizeof (TEXT_OUT_AND_GOP_DATA),\r
2378 &Private->TextOutListCount,\r
2379 (VOID **) &Private->TextOutList\r
2380 );\r
2381 if (EFI_ERROR (Status)) {\r
2382 return EFI_OUT_OF_RESOURCES;\r
2383 }\r
2384 //\r
2385 // Also need to reallocate the TextOutModeMap table\r
2386 //\r
2387 Status = ConSplitterGrowMapTable (Private);\r
2388 if (EFI_ERROR (Status)) {\r
2389 return EFI_OUT_OF_RESOURCES;\r
2390 }\r
2391 }\r
2392\r
2393 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];\r
2394\r
2395 TextAndGop->TextOut = TextOut;\r
2396 TextAndGop->GraphicsOutput = GraphicsOutput;\r
2397 TextAndGop->UgaDraw = UgaDraw;\r
2398\r
2399 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2400 //\r
2401 // If No UGA device then use the ConOut device\r
2402 //\r
2403 TextAndGop->TextOutEnabled = TRUE;\r
2404 } else {\r
2405 //\r
2406 // If UGA device use ConOut device only used if UGA screen is in Text mode\r
2407 //\r
2408 TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
2409 }\r
2410\r
2411 if (CurrentNumOfConsoles == 0) {\r
2412 //\r
2413 // Add the first device's output mode to console splitter's mode list\r
2414 //\r
2415 Status = ConSplitterAddOutputMode (Private, TextOut);\r
2416 } else {\r
2417 ConSplitterSyncOutputMode (Private, TextOut);\r
2418 }\r
2419\r
2420 Private->CurrentNumberOfConsoles++;\r
2421\r
2422 //\r
2423 // Scan both TextOutList, for the intersection TextOut device\r
2424 // maybe both ConOut and StdErr incorporate the same Text Out\r
2425 // device in them, thus the output of both should be synced.\r
2426 //\r
2427 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2428\r
2429 CurrentMode = Private->TextOutMode.Mode;\r
2430 MaxMode = Private->TextOutMode.MaxMode;\r
2431 ASSERT (MaxMode >= 1);\r
2432\r
d0c64728 2433 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2434 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
2435 ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
2436 }\r
95276127 2437 }\r
2438\r
2439 if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
2440 //\r
2441 // We just added a new UGA device in graphics mode\r
2442 //\r
d0c64728 2443 if (FeaturePcdGet (PcdConOutGopSupport)) {\r
2444 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2445 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
2446 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);\r
2447 }\r
95276127 2448 } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
2449 //\r
2450 // The new console supports the same mode of the current console so sync up\r
2451 //\r
2452 DevNullSyncGopStdOut (Private);\r
2453 } else {\r
2454 //\r
2455 // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
2456 //\r
2457 Private->TextOut.SetMode (&Private->TextOut, 0);\r
2458 }\r
2459\r
2460 return Status;\r
2461}\r
2462\r
2463EFI_STATUS\r
2464ConSplitterTextOutDeleteDevice (\r
2465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2466 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
2467 )\r
2468/*++\r
2469\r
2470Routine Description:\r
2471\r
2472Arguments:\r
2473\r
2474Returns:\r
2475\r
2476 None\r
2477\r
2478--*/\r
2479{\r
2480 INT32 Index;\r
2481 UINTN CurrentNumOfConsoles;\r
2482 TEXT_OUT_AND_GOP_DATA *TextOutList;\r
2483 EFI_STATUS Status;\r
2484\r
2485 //\r
2486 // Remove the specified text-out device data structure from the Text out List,\r
2487 // and rearrange the remaining data structures in the Text out List.\r
2488 //\r
2489 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2490 Index = (INT32) CurrentNumOfConsoles - 1;\r
2491 TextOutList = Private->TextOutList;\r
2492 while (Index >= 0) {\r
2493 if (TextOutList->TextOut == TextOut) {\r
2494 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
2495 CurrentNumOfConsoles--;\r
2496 break;\r
2497 }\r
2498\r
2499 Index--;\r
2500 TextOutList++;\r
2501 }\r
2502 //\r
2503 // The specified TextOut is not managed by the ConSplitter driver\r
2504 //\r
2505 if (Index < 0) {\r
2506 return EFI_NOT_FOUND;\r
2507 }\r
2508\r
2509 if (CurrentNumOfConsoles == 0) {\r
2510 //\r
2511 // If the number of consoles is zero clear the Dev NULL device\r
2512 //\r
2513 Private->CurrentNumberOfConsoles = 0;\r
2514 Private->TextOutMode.MaxMode = 1;\r
2515 Private->TextOutQueryData[0].Columns = 80;\r
2516 Private->TextOutQueryData[0].Rows = 25;\r
2517 DevNullTextOutSetMode (Private, 0);\r
2518\r
2519 return EFI_SUCCESS;\r
2520 }\r
2521 //\r
2522 // Max Mode is realy an intersection of the QueryMode command to all\r
2523 // devices. So we must copy the QueryMode of the first device to\r
2524 // QueryData.\r
2525 //\r
2526 ZeroMem (\r
2527 Private->TextOutQueryData,\r
2528 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)\r
2529 );\r
2530\r
2531 FreePool (Private->TextOutModeMap);\r
2532 Private->TextOutModeMap = NULL;\r
2533 TextOutList = Private->TextOutList;\r
2534\r
2535 //\r
2536 // Add the first TextOut to the QueryData array and ModeMap table\r
2537 //\r
2538 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);\r
2539\r
2540 //\r
2541 // Now add one by one\r
2542 //\r
2543 Index = 1;\r
2544 Private->CurrentNumberOfConsoles = 1;\r
2545 TextOutList++;\r
2546 while ((UINTN) Index < CurrentNumOfConsoles) {\r
2547 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);\r
2548 Index++;\r
2549 Private->CurrentNumberOfConsoles++;\r
2550 TextOutList++;\r
2551 }\r
2552\r
2553 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2554\r
2555 return Status;\r
2556}\r
2557//\r
2558// ConSplitter TextIn member functions\r
2559//\r
2560EFI_STATUS\r
2561EFIAPI\r
2562ConSplitterTextInReset (\r
2563 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
2564 IN BOOLEAN ExtendedVerification\r
2565 )\r
2566/*++\r
2567\r
2568 Routine Description:\r
2569 Reset the input device and optionaly run diagnostics\r
2570\r
2571 Arguments:\r
2572 This - Protocol instance pointer.\r
2573 ExtendedVerification - Driver may perform diagnostics on reset.\r
2574\r
2575 Returns:\r
2576 EFI_SUCCESS - The device was reset.\r
2577 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
2578 not be reset.\r
2579\r
2580--*/\r
2581{\r
2582 EFI_STATUS Status;\r
2583 EFI_STATUS ReturnStatus;\r
2584 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2585 UINTN Index;\r
2586\r
2587 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2588\r
2589 Private->KeyEventSignalState = FALSE;\r
2590\r
2591 //\r
2592 // return the worst status met\r
2593 //\r
2594 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2595 Status = Private->TextInList[Index]->Reset (\r
2596 Private->TextInList[Index],\r
2597 ExtendedVerification\r
2598 );\r
2599 if (EFI_ERROR (Status)) {\r
2600 ReturnStatus = Status;\r
2601 }\r
2602 }\r
2603\r
2604 return ReturnStatus;\r
2605}\r
2606\r
2607EFI_STATUS\r
2608EFIAPI\r
2609ConSplitterTextInPrivateReadKeyStroke (\r
2610 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2611 OUT EFI_INPUT_KEY *Key\r
2612 )\r
2613/*++\r
2614\r
2615 Routine Description:\r
2616 Reads the next keystroke from the input device. The WaitForKey Event can\r
2617 be used to test for existance of a keystroke via WaitForEvent () call.\r
2618\r
2619 Arguments:\r
2620 This - Protocol instance pointer.\r
2621 Key - Driver may perform diagnostics on reset.\r
2622\r
2623 Returns:\r
2624 EFI_SUCCESS - The keystroke information was returned.\r
2625 EFI_NOT_READY - There was no keystroke data availiable.\r
2626 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2627 hardware errors.\r
2628\r
2629--*/\r
2630{\r
2631 EFI_STATUS Status;\r
2632 UINTN Index;\r
2633 EFI_INPUT_KEY CurrentKey;\r
2634\r
2635 Key->UnicodeChar = 0;\r
2636 Key->ScanCode = SCAN_NULL;\r
2637\r
2638 //\r
2639 // if no physical console input device exists, return EFI_NOT_READY;\r
2640 // if any physical console input device has key input,\r
2641 // return the key and EFI_SUCCESS.\r
2642 //\r
2643 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2644 Status = Private->TextInList[Index]->ReadKeyStroke (\r
2645 Private->TextInList[Index],\r
2646 &CurrentKey\r
2647 );\r
2648 if (!EFI_ERROR (Status)) {\r
2649 *Key = CurrentKey;\r
2650 return Status;\r
2651 }\r
2652 }\r
2653\r
2654 return EFI_NOT_READY;\r
2655}\r
2656\r
2657BOOLEAN\r
2658ConSpliterConssoleControlStdInLocked (\r
2659 VOID\r
2660 )\r
2661/*++\r
2662\r
2663Routine Description:\r
2664 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is\r
2665 the only device locked.\r
2666\r
2667Arguments:\r
2668 NONE\r
2669\r
2670Returns:\r
2671 TRUE - StdIn locked\r
2672 FALSE - StdIn working normally\r
2673\r
2674--*/\r
2675{\r
2676 return mConIn.PasswordEnabled;\r
2677}\r
2678\r
2679VOID\r
2680EFIAPI\r
2681ConSpliterConsoleControlLockStdInEvent (\r
2682 IN EFI_EVENT Event,\r
2683 IN VOID *Context\r
2684 )\r
2685/*++\r
2686\r
2687Routine Description:\r
2688 This timer event will fire when StdIn is locked. It will check the key\r
2689 sequence on StdIn to see if it matches the password. Any error in the\r
2690 password will cause the check to reset. As long a mConIn.PasswordEnabled is\r
2691 TRUE the StdIn splitter will not report any input.\r
2692\r
2693Arguments:\r
2694 (Standard EFI_EVENT_NOTIFY)\r
2695\r
2696Returns:\r
2697 None\r
2698\r
2699--*/\r
2700{\r
2701 EFI_STATUS Status;\r
2702 EFI_INPUT_KEY Key;\r
2703 CHAR16 BackSpaceString[2];\r
2704 CHAR16 SpaceString[2];\r
2705\r
2706 do {\r
2707 Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);\r
2708 if (!EFI_ERROR (Status)) {\r
2709 //\r
2710 // if it's an ENTER, match password\r
2711 //\r
2712 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {\r
2713 mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;\r
2714 if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {\r
2715 //\r
2716 // Password not match\r
2717 //\r
2718 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");\r
2719 mConIn.PwdIndex = 0;\r
2720 } else {\r
2721 //\r
2722 // Key matches password sequence\r
2723 //\r
2724 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);\r
2725 mConIn.PasswordEnabled = FALSE;\r
2726 Status = EFI_NOT_READY;\r
2727 }\r
2728 } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {\r
2729 //\r
2730 // BackSpace met\r
2731 //\r
2732 if (mConIn.PwdIndex > 0) {\r
2733 BackSpaceString[0] = CHAR_BACKSPACE;\r
2734 BackSpaceString[1] = 0;\r
2735\r
2736 SpaceString[0] = ' ';\r
2737 SpaceString[1] = 0;\r
2738\r
2739 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
2740 ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);\r
2741 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
2742\r
2743 mConIn.PwdIndex--;\r
2744 }\r
2745 } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {\r
2746 //\r
2747 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input\r
2748 //\r
2749 if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {\r
2750 if (mConIn.PwdIndex == 0) {\r
2751 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");\r
2752 }\r
2753\r
2754 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");\r
2755 mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;\r
2756 mConIn.PwdIndex++;\r
2757 }\r
2758 }\r
2759 }\r
2760 } while (!EFI_ERROR (Status));\r
2761}\r
2762\r
2763EFI_STATUS\r
2764EFIAPI\r
2765ConSpliterConsoleControlLockStdIn (\r
2766 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
2767 IN CHAR16 *Password\r
2768 )\r
2769/*++\r
2770\r
2771Routine Description:\r
2772 If Password is NULL unlock the password state variable and set the event\r
2773 timer. If the Password is too big return an error. If the Password is valid\r
2774 Copy the Password and enable state variable and then arm the periodic timer\r
2775\r
2776Arguments:\r
2777\r
2778Returns:\r
2779 EFI_SUCCESS - Lock the StdIn device\r
2780 EFI_INVALID_PARAMETER - Password is NULL\r
2781 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails\r
2782\r
2783--*/\r
2784{\r
2785 if (Password == NULL) {\r
2786 return EFI_INVALID_PARAMETER;\r
2787 }\r
2788\r
2789 if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {\r
2790 //\r
2791 // Currently have a max password size\r
2792 //\r
2793 return EFI_OUT_OF_RESOURCES;\r
2794 }\r
2795 //\r
2796 // Save the password, initialize state variables and arm event timer\r
2797 //\r
2798 StrCpy (mConIn.Password, Password);\r
2799 mConIn.PasswordEnabled = TRUE;\r
2800 mConIn.PwdIndex = 0;\r
2801 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));\r
2802\r
2803 return EFI_SUCCESS;\r
2804}\r
2805\r
2806EFI_STATUS\r
2807EFIAPI\r
2808ConSplitterTextInReadKeyStroke (\r
2809 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
2810 OUT EFI_INPUT_KEY *Key\r
2811 )\r
2812/*++\r
2813\r
2814 Routine Description:\r
2815 Reads the next keystroke from the input device. The WaitForKey Event can\r
2816 be used to test for existance of a keystroke via WaitForEvent () call.\r
2817 If the ConIn is password locked make it look like no keystroke is availible\r
2818\r
2819 Arguments:\r
2820 This - Protocol instance pointer.\r
2821 Key - Driver may perform diagnostics on reset.\r
2822\r
2823 Returns:\r
2824 EFI_SUCCESS - The keystroke information was returned.\r
2825 EFI_NOT_READY - There was no keystroke data availiable.\r
2826 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2827 hardware errors.\r
2828\r
2829--*/\r
2830{\r
2831 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2832\r
2833 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2834 if (Private->PasswordEnabled) {\r
2835 //\r
2836 // If StdIn Locked return not ready\r
2837 //\r
2838 return EFI_NOT_READY;\r
2839 }\r
2840\r
2841 Private->KeyEventSignalState = FALSE;\r
2842\r
2843 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
2844}\r
2845\r
2846VOID\r
2847EFIAPI\r
2848ConSplitterTextInWaitForKey (\r
2849 IN EFI_EVENT Event,\r
2850 IN VOID *Context\r
2851 )\r
2852/*++\r
2853\r
2854Routine Description:\r
2855 This event agregates all the events of the ConIn devices in the spliter.\r
2856 If the ConIn is password locked then return.\r
2857 If any events of physical ConIn devices are signaled, signal the ConIn\r
2858 spliter event. This will cause the calling code to call\r
2859 ConSplitterTextInReadKeyStroke ().\r
2860\r
2861Arguments:\r
2862 Event - The Event assoicated with callback.\r
2863 Context - Context registered when Event was created.\r
2864\r
2865Returns:\r
2866 None\r
2867\r
2868--*/\r
2869{\r
2870 EFI_STATUS Status;\r
2871 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2872 UINTN Index;\r
2873\r
2874 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
2875 if (Private->PasswordEnabled) {\r
2876 //\r
2877 // If StdIn Locked return not ready\r
2878 //\r
2879 return ;\r
2880 }\r
2881\r
2882 //\r
2883 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
2884 //\r
2885 if (Private->KeyEventSignalState) {\r
2886 gBS->SignalEvent (Event);\r
2887 return ;\r
2888 }\r
2889 //\r
2890 // if any physical console input device has key input, signal the event.\r
2891 //\r
2892 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2893 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);\r
2894 if (!EFI_ERROR (Status)) {\r
2895 gBS->SignalEvent (Event);\r
2896 Private->KeyEventSignalState = TRUE;\r
2897 }\r
2898 }\r
2899}\r
2900\r
66aa04e4 2901\r
2902STATIC\r
2903BOOLEAN\r
2904IsKeyRegistered (\r
2905 IN EFI_KEY_DATA *RegsiteredData,\r
2906 IN EFI_KEY_DATA *InputData\r
2907 )\r
2908/*++\r
2909\r
2910Routine Description:\r
2911\r
2912Arguments:\r
2913\r
2914 RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
2915 state data for the key that was registered.\r
2916 InputData - A pointer to a buffer that is filled in with the keystroke \r
2917 state data for the key that was pressed.\r
2918\r
2919Returns:\r
2920 TRUE - Key be pressed matches a registered key.\r
2921 FLASE - Match failed. \r
2922 \r
2923--*/\r
2924{\r
2925 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
2926 \r
2927 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
2928 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
2929 return FALSE; \r
2930 } \r
2931 \r
2932 //\r
2933 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
2934 //\r
2935 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
2936 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
2937 return FALSE; \r
2938 } \r
2939 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
2940 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
2941 return FALSE; \r
2942 } \r
2943 \r
2944 return TRUE;\r
2945\r
2946}\r
2947\r
2948//\r
2949// Simple Text Input Ex protocol functions\r
2950//\r
2951\r
2952EFI_STATUS\r
2953EFIAPI\r
2954ConSplitterTextInResetEx (\r
2955 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2956 IN BOOLEAN ExtendedVerification\r
2957 )\r
2958/*++\r
2959\r
2960 Routine Description:\r
2961 Reset the input device and optionaly run diagnostics\r
2962\r
2963 Arguments:\r
2964 This - Protocol instance pointer.\r
2965 ExtendedVerification - Driver may perform diagnostics on reset.\r
2966\r
2967 Returns:\r
2968 EFI_SUCCESS - The device was reset.\r
2969 EFI_DEVICE_ERROR - The device is not functioning properly and could \r
2970 not be reset.\r
2971\r
2972--*/\r
2973{\r
2974 EFI_STATUS Status;\r
2975 EFI_STATUS ReturnStatus;\r
2976 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2977 UINTN Index;\r
2978\r
2979 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2980\r
2981 Private->KeyEventSignalState = FALSE;\r
2982\r
2983 //\r
2984 // return the worst status met\r
2985 //\r
2986 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
2987 Status = Private->TextInExList[Index]->Reset (\r
2988 Private->TextInExList[Index],\r
2989 ExtendedVerification\r
2990 );\r
2991 if (EFI_ERROR (Status)) {\r
2992 ReturnStatus = Status;\r
2993 }\r
2994 }\r
2995\r
2996 return ReturnStatus;\r
2997\r
2998}\r
2999\r
3000EFI_STATUS\r
3001EFIAPI\r
3002ConSplitterTextInReadKeyStrokeEx (\r
3003 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3004 OUT EFI_KEY_DATA *KeyData\r
3005 )\r
3006/*++\r
3007\r
3008 Routine Description:\r
3009 Reads the next keystroke from the input device. The WaitForKey Event can \r
3010 be used to test for existance of a keystroke via WaitForEvent () call.\r
3011\r
3012 Arguments:\r
3013 This - Protocol instance pointer.\r
3014 KeyData - A pointer to a buffer that is filled in with the keystroke \r
3015 state data for the key that was pressed.\r
3016\r
3017 Returns:\r
3018 EFI_SUCCESS - The keystroke information was returned.\r
3019 EFI_NOT_READY - There was no keystroke data availiable.\r
3020 EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
3021 hardware errors.\r
3022 EFI_INVALID_PARAMETER - KeyData is NULL. \r
3023\r
3024--*/\r
3025{\r
3026 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3027 EFI_STATUS Status;\r
3028 UINTN Index;\r
3029 EFI_KEY_DATA CurrentKeyData;\r
3030\r
3031 \r
3032 if (KeyData == NULL) {\r
3033 return EFI_INVALID_PARAMETER;\r
3034 }\r
3035\r
3036 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3037 if (Private->PasswordEnabled) {\r
3038 //\r
3039 // If StdIn Locked return not ready\r
3040 //\r
3041 return EFI_NOT_READY;\r
3042 }\r
3043\r
3044 Private->KeyEventSignalState = FALSE;\r
3045\r
3046 KeyData->Key.UnicodeChar = 0;\r
3047 KeyData->Key.ScanCode = SCAN_NULL;\r
3048\r
3049 //\r
3050 // if no physical console input device exists, return EFI_NOT_READY;\r
3051 // if any physical console input device has key input,\r
3052 // return the key and EFI_SUCCESS.\r
3053 //\r
3054 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3055 Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
3056 Private->TextInExList[Index],\r
3057 &CurrentKeyData\r
3058 );\r
3059 if (!EFI_ERROR (Status)) {\r
3060 CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
3061 return Status;\r
3062 }\r
3063 }\r
3064\r
3065 return EFI_NOT_READY; \r
3066}\r
3067\r
3068EFI_STATUS\r
3069EFIAPI\r
3070ConSplitterTextInSetState (\r
3071 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3072 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
3073 )\r
3074/*++\r
3075\r
3076 Routine Description:\r
3077 Set certain state for the input device.\r
3078\r
3079 Arguments:\r
3080 This - Protocol instance pointer.\r
3081 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
3082 state for the input device.\r
3083 \r
3084 Returns: \r
3085 EFI_SUCCESS - The device state was set successfully.\r
3086 EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
3087 not have the setting adjusted.\r
3088 EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
3089 EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
3090\r
3091--*/ \r
3092{\r
3093 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3094 EFI_STATUS Status;\r
3095 UINTN Index;\r
3096\r
3097 if (KeyToggleState == NULL) {\r
3098 return EFI_INVALID_PARAMETER;\r
3099 }\r
3100\r
3101 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3102\r
3103 //\r
3104 // if no physical console input device exists, return EFI_SUCCESS;\r
3105 // otherwise return the status of setting state of physical console input device\r
3106 //\r
3107 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3108 Status = Private->TextInExList[Index]->SetState (\r
3109 Private->TextInExList[Index],\r
3110 KeyToggleState\r
3111 );\r
3112 if (EFI_ERROR (Status)) {\r
3113 return Status;\r
3114 }\r
3115 }\r
3116\r
3117 return EFI_SUCCESS; \r
3118\r
3119}\r
3120\r
3121EFI_STATUS\r
3122EFIAPI\r
3123ConSplitterTextInRegisterKeyNotify (\r
3124 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3125 IN EFI_KEY_DATA *KeyData,\r
3126 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
3127 OUT EFI_HANDLE *NotifyHandle\r
3128 )\r
3129/*++\r
3130\r
3131 Routine Description:\r
3132 Register a notification function for a particular keystroke for the input device.\r
3133\r
3134 Arguments:\r
3135 This - Protocol instance pointer.\r
3136 KeyData - A pointer to a buffer that is filled in with the keystroke \r
3137 information data for the key that was pressed.\r
3138 KeyNotificationFunction - Points to the function to be called when the key \r
3139 sequence is typed specified by KeyData. \r
3140 NotifyHandle - Points to the unique handle assigned to the registered notification. \r
3141\r
3142 Returns:\r
3143 EFI_SUCCESS - The notification function was registered successfully.\r
3144 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
3145 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
3146 \r
3147--*/ \r
3148{\r
3149 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3150 EFI_STATUS Status;\r
3151 UINTN Index;\r
3152 TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
3153 LIST_ENTRY *Link;\r
3154 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; \r
3155 \r
3156\r
3157 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
3158 return EFI_INVALID_PARAMETER;\r
3159 }\r
3160\r
3161 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3162\r
3163 //\r
3164 // if no physical console input device exists, \r
3165 // return EFI_SUCCESS directly.\r
3166 //\r
3167 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3168 return EFI_SUCCESS;\r
3169 }\r
3170\r
3171 //\r
3172 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
3173 //\r
3174 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3175 CurrentNotify = CR (\r
3176 Link, \r
3177 TEXT_IN_EX_SPLITTER_NOTIFY, \r
3178 NotifyEntry, \r
3179 TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
3180 );\r
3181 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
3182 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
3183 *NotifyHandle = CurrentNotify->NotifyHandle; \r
3184 return EFI_SUCCESS;\r
3185 }\r
3186 }\r
3187 }\r
3188 \r
3189 //\r
3190 // Allocate resource to save the notification function\r
3191 // \r
3192 NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
3193 if (NewNotify == NULL) {\r
3194 return EFI_OUT_OF_RESOURCES;\r
3195 }\r
3196 NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
3197 if (NewNotify->NotifyHandleList == NULL) {\r
3198 gBS->FreePool (NewNotify);\r
3199 return EFI_OUT_OF_RESOURCES;\r
3200 }\r
3201 NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE; \r
3202 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
3203 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
3204 \r
3205 //\r
3206 // Return the wrong status of registering key notify of \r
3207 // physical console input device if meet problems\r
3208 //\r
3209 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3210 Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
3211 Private->TextInExList[Index],\r
3212 KeyData,\r
3213 KeyNotificationFunction,\r
3214 &NewNotify->NotifyHandleList[Index]\r
3215 );\r
3216 if (EFI_ERROR (Status)) {\r
3217 gBS->FreePool (NewNotify->NotifyHandleList);\r
3218 gBS->FreePool (NewNotify);\r
3219 return Status;\r
3220 }\r
3221 }\r
3222\r
3223 //\r
3224 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
3225 // \r
3226 Status = gBS->InstallMultipleProtocolInterfaces (\r
3227 &NewNotify->NotifyHandle,\r
3228 &gSimpleTextInExNotifyGuid,\r
3229 NULL,\r
3230 NULL\r
3231 );\r
3232 ASSERT_EFI_ERROR (Status);\r
3233\r
3234 InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
3235 \r
3236 *NotifyHandle = NewNotify->NotifyHandle; \r
3237 \r
3238 return EFI_SUCCESS; \r
3239 \r
3240}\r
3241\r
3242EFI_STATUS\r
3243EFIAPI\r
3244ConSplitterTextInUnregisterKeyNotify (\r
3245 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
3246 IN EFI_HANDLE NotificationHandle\r
3247 )\r
3248/*++\r
3249\r
3250 Routine Description:\r
3251 Remove a registered notification function from a particular keystroke.\r
3252\r
3253 Arguments:\r
3254 This - Protocol instance pointer. \r
3255 NotificationHandle - The handle of the notification function being unregistered.\r
3256\r
3257 Returns:\r
3258 EFI_SUCCESS - The notification function was unregistered successfully.\r
3259 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
3260 EFI_NOT_FOUND - Can not find the matching entry in database. \r
3261 \r
3262--*/ \r
3263{\r
3264 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3265 EFI_STATUS Status;\r
3266 UINTN Index;\r
3267 TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
3268 LIST_ENTRY *Link; \r
3269\r
3270 if (NotificationHandle == NULL) {\r
3271 return EFI_INVALID_PARAMETER;\r
3272 }\r
3273\r
3274 Status = gBS->OpenProtocol (\r
3275 NotificationHandle,\r
3276 &gSimpleTextInExNotifyGuid,\r
3277 NULL,\r
3278 NULL,\r
3279 NULL,\r
3280 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
3281 );\r
3282 if (EFI_ERROR (Status)) {\r
3283 return EFI_INVALID_PARAMETER;\r
3284 }\r
3285\r
3286 Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3287\r
3288 //\r
3289 // if no physical console input device exists, \r
3290 // return EFI_SUCCESS directly.\r
3291 //\r
3292 if (Private->CurrentNumberOfExConsoles <= 0) {\r
3293 return EFI_SUCCESS;\r
3294 }\r
3295\r
3296 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
3297 CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
3298 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
3299 for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
3300 Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
3301 Private->TextInExList[Index], \r
3302 CurrentNotify->NotifyHandleList[Index]\r
3303 );\r
3304 if (EFI_ERROR (Status)) {\r
3305 return Status;\r
3306 } \r
3307 }\r
3308 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
3309 Status = gBS->UninstallMultipleProtocolInterfaces (\r
3310 CurrentNotify->NotifyHandle,\r
3311 &gSimpleTextInExNotifyGuid,\r
3312 NULL,\r
3313 NULL\r
3314 );\r
3315 ASSERT_EFI_ERROR (Status);\r
3316 gBS->FreePool (CurrentNotify->NotifyHandleList);\r
3317 gBS->FreePool (CurrentNotify);\r
3318 return EFI_SUCCESS; \r
3319 } \r
3320 }\r
3321\r
3322 return EFI_NOT_FOUND; \r
3323 \r
3324}\r
3325\r
3326\r
3327\r
95276127 3328EFI_STATUS\r
3329EFIAPI\r
3330ConSplitterSimplePointerReset (\r
3331 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
3332 IN BOOLEAN ExtendedVerification\r
3333 )\r
3334/*++\r
3335\r
3336 Routine Description:\r
3337 Reset the input device and optionaly run diagnostics\r
3338\r
3339 Arguments:\r
3340 This - Protocol instance pointer.\r
3341 ExtendedVerification - Driver may perform diagnostics on reset.\r
3342\r
3343 Returns:\r
3344 EFI_SUCCESS - The device was reset.\r
3345 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
3346 not be reset.\r
3347\r
3348--*/\r
3349{\r
3350 EFI_STATUS Status;\r
3351 EFI_STATUS ReturnStatus;\r
3352 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3353 UINTN Index;\r
3354\r
3355 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
3356\r
3357 Private->InputEventSignalState = FALSE;\r
3358\r
3359 if (Private->CurrentNumberOfPointers == 0) {\r
3360 return EFI_SUCCESS;\r
3361 }\r
3362 //\r
3363 // return the worst status met\r
3364 //\r
3365 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
3366 Status = Private->PointerList[Index]->Reset (\r
3367 Private->PointerList[Index],\r
3368 ExtendedVerification\r
3369 );\r
3370 if (EFI_ERROR (Status)) {\r
3371 ReturnStatus = Status;\r
3372 }\r
3373 }\r
3374\r
3375 return ReturnStatus;\r
3376}\r
3377\r
3378STATIC\r
3379EFI_STATUS\r
3380EFIAPI\r
3381ConSplitterSimplePointerPrivateGetState (\r
3382 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
3383 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
3384 )\r
3385/*++\r
3386\r
3387 Routine Description:\r
3388 Reads the next keystroke from the input device. The WaitForKey Event can\r
3389 be used to test for existance of a keystroke via WaitForEvent () call.\r
3390\r
3391 Arguments:\r
3392 This - Protocol instance pointer.\r
3393 State -\r
3394\r
3395 Returns:\r
3396 EFI_SUCCESS - The keystroke information was returned.\r
3397 EFI_NOT_READY - There was no keystroke data availiable.\r
3398 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
3399 hardware errors.\r
3400\r
3401--*/\r
3402{\r
3403 EFI_STATUS Status;\r
3404 EFI_STATUS ReturnStatus;\r
3405 UINTN Index;\r
3406 EFI_SIMPLE_POINTER_STATE CurrentState;\r
3407\r
3408 State->RelativeMovementX = 0;\r
3409 State->RelativeMovementY = 0;\r
3410 State->RelativeMovementZ = 0;\r
3411 State->LeftButton = FALSE;\r
3412 State->RightButton = FALSE;\r
3413\r
3414 //\r
3415 // if no physical console input device exists, return EFI_NOT_READY;\r
3416 // if any physical console input device has key input,\r
3417 // return the key and EFI_SUCCESS.\r
3418 //\r
3419 ReturnStatus = EFI_NOT_READY;\r
3420 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
3421\r
3422 Status = Private->PointerList[Index]->GetState (\r
3423 Private->PointerList[Index],\r
3424 &CurrentState\r
3425 );\r
3426 if (!EFI_ERROR (Status)) {\r
3427 if (ReturnStatus == EFI_NOT_READY) {\r
3428 ReturnStatus = EFI_SUCCESS;\r
3429 }\r
3430\r
3431 if (CurrentState.LeftButton) {\r
3432 State->LeftButton = TRUE;\r
3433 }\r
3434\r
3435 if (CurrentState.RightButton) {\r
3436 State->RightButton = TRUE;\r
3437 }\r
3438\r
3439 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
3440 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
3441 }\r
3442\r
3443 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
3444 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
3445 }\r
3446\r
3447 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
3448 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
3449 }\r
3450 } else if (Status == EFI_DEVICE_ERROR) {\r
3451 ReturnStatus = EFI_DEVICE_ERROR;\r
3452 }\r
3453 }\r
3454\r
3455 return ReturnStatus;\r
3456}\r
3457\r
3458EFI_STATUS\r
3459EFIAPI\r
3460ConSplitterSimplePointerGetState (\r
3461 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
3462 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
3463 )\r
3464/*++\r
3465\r
3466 Routine Description:\r
3467 Reads the next keystroke from the input device. The WaitForKey Event can\r
3468 be used to test for existance of a keystroke via WaitForEvent () call.\r
3469 If the ConIn is password locked make it look like no keystroke is availible\r
3470\r
3471 Arguments:\r
3472 This - Protocol instance pointer.\r
3473 State -\r
3474\r
3475 Returns:\r
3476 EFI_SUCCESS - The keystroke information was returned.\r
3477 EFI_NOT_READY - There was no keystroke data availiable.\r
3478 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
3479 hardware errors.\r
3480\r
3481--*/\r
3482{\r
3483 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3484\r
3485 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
3486 if (Private->PasswordEnabled) {\r
3487 //\r
3488 // If StdIn Locked return not ready\r
3489 //\r
3490 return EFI_NOT_READY;\r
3491 }\r
3492\r
3493 Private->InputEventSignalState = FALSE;\r
3494\r
3495 return ConSplitterSimplePointerPrivateGetState (Private, State);\r
3496}\r
3497\r
3498VOID\r
3499EFIAPI\r
3500ConSplitterSimplePointerWaitForInput (\r
3501 IN EFI_EVENT Event,\r
3502 IN VOID *Context\r
3503 )\r
3504/*++\r
3505\r
3506Routine Description:\r
3507 This event agregates all the events of the ConIn devices in the spliter.\r
3508 If the ConIn is password locked then return.\r
3509 If any events of physical ConIn devices are signaled, signal the ConIn\r
3510 spliter event. This will cause the calling code to call\r
3511 ConSplitterTextInReadKeyStroke ().\r
3512\r
3513Arguments:\r
3514 Event - The Event assoicated with callback.\r
3515 Context - Context registered when Event was created.\r
3516\r
3517Returns:\r
3518 None\r
3519\r
3520--*/\r
3521{\r
3522 EFI_STATUS Status;\r
3523 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
3524 UINTN Index;\r
3525\r
3526 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
3527 if (Private->PasswordEnabled) {\r
3528 //\r
3529 // If StdIn Locked return not ready\r
3530 //\r
3531 return ;\r
3532 }\r
3533\r
3534 //\r
3535 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
3536 //\r
3537 if (Private->InputEventSignalState) {\r
3538 gBS->SignalEvent (Event);\r
3539 return ;\r
3540 }\r
3541 //\r
3542 // if any physical console input device has key input, signal the event.\r
3543 //\r
3544 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
3545 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);\r
3546 if (!EFI_ERROR (Status)) {\r
3547 gBS->SignalEvent (Event);\r
3548 Private->InputEventSignalState = TRUE;\r
3549 }\r
3550 }\r
3551}\r
3552\r
3553EFI_STATUS\r
3554EFIAPI\r
3555ConSplitterTextOutReset (\r
3556 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3557 IN BOOLEAN ExtendedVerification\r
3558 )\r
3559/*++\r
3560\r
3561 Routine Description:\r
3562 Reset the text output device hardware and optionaly run diagnostics\r
3563\r
3564 Arguments:\r
3565 This - Protocol instance pointer.\r
3566 ExtendedVerification - Driver may perform more exhaustive verfication\r
3567 operation of the device during reset.\r
3568\r
3569 Returns:\r
3570 EFI_SUCCESS - The text output device was reset.\r
3571 EFI_DEVICE_ERROR - The text output device is not functioning correctly and\r
3572 could not be reset.\r
3573\r
3574--*/\r
3575{\r
3576 EFI_STATUS Status;\r
3577 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3578 UINTN Index;\r
3579 EFI_STATUS ReturnStatus;\r
3580\r
3581 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3582\r
3583 //\r
3584 // return the worst status met\r
3585 //\r
3586 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3587\r
3588 if (Private->TextOutList[Index].TextOutEnabled) {\r
3589\r
3590 Status = Private->TextOutList[Index].TextOut->Reset (\r
3591 Private->TextOutList[Index].TextOut,\r
3592 ExtendedVerification\r
3593 );\r
3594 if (EFI_ERROR (Status)) {\r
3595 ReturnStatus = Status;\r
3596 }\r
3597 }\r
3598 }\r
3599\r
3600 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
3601\r
3602 Status = DevNullTextOutSetMode (Private, 0);\r
3603 if (EFI_ERROR (Status)) {\r
3604 ReturnStatus = Status;\r
3605 }\r
3606\r
3607 return ReturnStatus;\r
3608}\r
3609\r
3610EFI_STATUS\r
3611EFIAPI\r
3612ConSplitterTextOutOutputString (\r
3613 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3614 IN CHAR16 *WString\r
3615 )\r
3616/*++\r
3617\r
3618 Routine Description:\r
3619 Write a Unicode string to the output device.\r
3620\r
3621 Arguments:\r
3622 This - Protocol instance pointer.\r
3623 String - The NULL-terminated Unicode string to be displayed on the output\r
3624 device(s). All output devices must also support the Unicode\r
3625 drawing defined in this file.\r
3626\r
3627 Returns:\r
3628 EFI_SUCCESS - The string was output to the device.\r
3629 EFI_DEVICE_ERROR - The device reported an error while attempting to output\r
3630 the text.\r
3631 EFI_UNSUPPORTED - The output device's mode is not currently in a\r
3632 defined text mode.\r
3633 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the\r
3634 characters in the Unicode string could not be\r
3635 rendered and were skipped.\r
3636\r
3637--*/\r
3638{\r
3639 EFI_STATUS Status;\r
3640 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3641 UINTN Index;\r
3642 UINTN BackSpaceCount;\r
3643 EFI_STATUS ReturnStatus;\r
3644 CHAR16 *TargetString;\r
3645\r
3646 This->SetAttribute (This, This->Mode->Attribute);\r
3647\r
3648 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3649\r
3650 BackSpaceCount = 0;\r
3651 for (TargetString = WString; *TargetString; TargetString++) {\r
3652 if (*TargetString == CHAR_BACKSPACE) {\r
3653 BackSpaceCount++;\r
3654 }\r
3655\r
3656 }\r
3657\r
3658 if (BackSpaceCount == 0) {\r
3659 TargetString = WString;\r
3660 } else {\r
3661 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
3662 StrCpy (TargetString, WString);\r
3663 }\r
3664 //\r
3665 // return the worst status met\r
3666 //\r
3667 Status = DevNullTextOutOutputString (Private, TargetString);\r
3668 if (EFI_ERROR (Status)) {\r
3669 ReturnStatus = Status;\r
3670 }\r
3671\r
3672 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3673\r
3674 if (Private->TextOutList[Index].TextOutEnabled) {\r
3675 Status = Private->TextOutList[Index].TextOut->OutputString (\r
3676 Private->TextOutList[Index].TextOut,\r
3677 TargetString\r
3678 );\r
3679 if (EFI_ERROR (Status)) {\r
3680 ReturnStatus = Status;\r
3681 }\r
3682 }\r
3683 }\r
3684\r
3685 if (BackSpaceCount) {\r
3686 FreePool (TargetString);\r
3687 }\r
3688\r
3689 return ReturnStatus;\r
3690}\r
3691\r
3692EFI_STATUS\r
3693EFIAPI\r
3694ConSplitterTextOutTestString (\r
3695 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3696 IN CHAR16 *WString\r
3697 )\r
3698/*++\r
3699\r
3700 Routine Description:\r
3701 Verifies that all characters in a Unicode string can be output to the\r
3702 target device.\r
3703\r
3704 Arguments:\r
3705 This - Protocol instance pointer.\r
3706 String - The NULL-terminated Unicode string to be examined for the output\r
3707 device(s).\r
3708\r
3709 Returns:\r
3710 EFI_SUCCESS - The device(s) are capable of rendering the output string.\r
3711 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be\r
3712 rendered by one or more of the output devices mapped\r
3713 by the EFI handle.\r
3714\r
3715--*/\r
3716{\r
3717 EFI_STATUS Status;\r
3718 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3719 UINTN Index;\r
3720 EFI_STATUS ReturnStatus;\r
3721\r
3722 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3723\r
3724 //\r
3725 // return the worst status met\r
3726 //\r
3727 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3728 if (Private->TextOutList[Index].TextOutEnabled) {\r
3729 Status = Private->TextOutList[Index].TextOut->TestString (\r
3730 Private->TextOutList[Index].TextOut,\r
3731 WString\r
3732 );\r
3733 if (EFI_ERROR (Status)) {\r
3734 ReturnStatus = Status;\r
3735 }\r
3736 }\r
3737 }\r
3738 //\r
3739 // There is no DevNullTextOutTestString () since a Unicode buffer would\r
3740 // always return EFI_SUCCESS.\r
3741 // ReturnStatus will be EFI_SUCCESS if no consoles are present\r
3742 //\r
3743 return ReturnStatus;\r
3744}\r
3745\r
3746EFI_STATUS\r
3747EFIAPI\r
3748ConSplitterTextOutQueryMode (\r
3749 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3750 IN UINTN ModeNumber,\r
3751 OUT UINTN *Columns,\r
3752 OUT UINTN *Rows\r
3753 )\r
3754/*++\r
3755\r
3756 Routine Description:\r
3757 Returns information for an available text mode that the output device(s)\r
3758 supports.\r
3759\r
3760 Arguments:\r
3761 This - Protocol instance pointer.\r
3762 ModeNumber - The mode number to return information on.\r
3763 Columns, Rows - Returns the geometry of the text output device for the\r
3764 requested ModeNumber.\r
3765\r
3766 Returns:\r
3767 EFI_SUCCESS - The requested mode information was returned.\r
3768 EFI_DEVICE_ERROR - The device had an error and could not\r
3769 complete the request.\r
3770 EFI_UNSUPPORTED - The mode number was not valid.\r
3771\r
3772--*/\r
3773{\r
3774 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3775\r
3776 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3777\r
3778 //\r
3779 // Check whether param ModeNumber is valid.\r
3780 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
3781 //\r
3782 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
3783 return EFI_UNSUPPORTED;\r
3784 }\r
3785\r
3786 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
3787 return EFI_UNSUPPORTED;\r
3788 }\r
3789\r
3790 *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
3791 *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
3792\r
3793 if (*Columns <= 0 && *Rows <= 0) {\r
3794 return EFI_UNSUPPORTED;\r
3795\r
3796 }\r
3797\r
3798 return EFI_SUCCESS;\r
3799}\r
3800\r
3801EFI_STATUS\r
3802EFIAPI\r
3803ConSplitterTextOutSetMode (\r
3804 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3805 IN UINTN ModeNumber\r
3806 )\r
3807/*++\r
3808\r
3809 Routine Description:\r
3810 Sets the output device(s) to a specified mode.\r
3811\r
3812 Arguments:\r
3813 This - Protocol instance pointer.\r
3814 ModeNumber - The mode number to set.\r
3815\r
3816 Returns:\r
3817 EFI_SUCCESS - The requested text mode was set.\r
3818 EFI_DEVICE_ERROR - The device had an error and\r
3819 could not complete the request.\r
3820 EFI_UNSUPPORTED - The mode number was not valid.\r
3821\r
3822--*/\r
3823{\r
3824 EFI_STATUS Status;\r
3825 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3826 UINTN Index;\r
3827 INT32 *TextOutModeMap;\r
3828 EFI_STATUS ReturnStatus;\r
3829\r
3830 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3831\r
3832 //\r
3833 // Check whether param ModeNumber is valid.\r
3834 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
3835 //\r
3836 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
3837 return EFI_UNSUPPORTED;\r
3838 }\r
3839\r
3840 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
3841 return EFI_UNSUPPORTED;\r
3842 }\r
3843 //\r
3844 // If the mode is being set to the curent mode, then just clear the screen and return.\r
3845 //\r
3846 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {\r
3847 return ConSplitterTextOutClearScreen (This);\r
3848 }\r
3849 //\r
3850 // return the worst status met\r
3851 //\r
3852 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
3853 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3854\r
3855 if (Private->TextOutList[Index].TextOutEnabled) {\r
3856 Status = Private->TextOutList[Index].TextOut->SetMode (\r
3857 Private->TextOutList[Index].TextOut,\r
3858 TextOutModeMap[Index]\r
3859 );\r
3860 //\r
3861 // If this console device is based on a UGA device, then sync up the bitmap from\r
3862 // the UGA splitter and reclear the text portion of the display in the new mode.\r
3863 //\r
3864 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
3865 Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
3866 }\r
3867\r
3868 if (EFI_ERROR (Status)) {\r
3869 ReturnStatus = Status;\r
3870 }\r
3871 }\r
3872 }\r
3873 //\r
3874 // The DevNull Console will support any possible mode as it allocates memory\r
3875 //\r
3876 Status = DevNullTextOutSetMode (Private, ModeNumber);\r
3877 if (EFI_ERROR (Status)) {\r
3878 ReturnStatus = Status;\r
3879 }\r
3880\r
3881 return ReturnStatus;\r
3882}\r
3883\r
3884EFI_STATUS\r
3885EFIAPI\r
3886ConSplitterTextOutSetAttribute (\r
3887 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3888 IN UINTN Attribute\r
3889 )\r
3890/*++\r
3891\r
3892 Routine Description:\r
3893 Sets the background and foreground colors for the OutputString () and\r
3894 ClearScreen () functions.\r
3895\r
3896 Arguments:\r
3897 This - Protocol instance pointer.\r
3898 Attribute - The attribute to set. Bits 0..3 are the foreground color, and\r
3899 bits 4..6 are the background color. All other bits are undefined\r
3900 and must be zero. The valid Attributes are defined in this file.\r
3901\r
3902 Returns:\r
3903 EFI_SUCCESS - The attribute was set.\r
3904 EFI_DEVICE_ERROR - The device had an error and\r
3905 could not complete the request.\r
3906 EFI_UNSUPPORTED - The attribute requested is not defined.\r
3907\r
3908--*/\r
3909{\r
3910 EFI_STATUS Status;\r
3911 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3912 UINTN Index;\r
3913 EFI_STATUS ReturnStatus;\r
3914\r
3915 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3916\r
3917 //\r
3918 // Check whether param Attribute is valid.\r
3919 //\r
3920 if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {\r
3921 return EFI_UNSUPPORTED;\r
3922 }\r
3923\r
3924 //\r
3925 // return the worst status met\r
3926 //\r
3927 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3928\r
3929 if (Private->TextOutList[Index].TextOutEnabled) {\r
3930 Status = Private->TextOutList[Index].TextOut->SetAttribute (\r
3931 Private->TextOutList[Index].TextOut,\r
3932 Attribute\r
3933 );\r
3934 if (EFI_ERROR (Status)) {\r
3935 ReturnStatus = Status;\r
3936 }\r
3937 }\r
3938 }\r
3939\r
3940 Private->TextOutMode.Attribute = (INT32) Attribute;\r
3941\r
3942 return ReturnStatus;\r
3943}\r
3944\r
3945EFI_STATUS\r
3946EFIAPI\r
3947ConSplitterTextOutClearScreen (\r
3948 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
3949 )\r
3950/*++\r
3951\r
3952 Routine Description:\r
3953 Clears the output device(s) display to the currently selected background\r
3954 color.\r
3955\r
3956 Arguments:\r
3957 This - Protocol instance pointer.\r
3958\r
3959 Returns:\r
3960 EFI_SUCCESS - The operation completed successfully.\r
3961 EFI_DEVICE_ERROR - The device had an error and\r
3962 could not complete the request.\r
3963 EFI_UNSUPPORTED - The output device is not in a valid text mode.\r
3964\r
3965--*/\r
3966{\r
3967 EFI_STATUS Status;\r
3968 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3969 UINTN Index;\r
3970 EFI_STATUS ReturnStatus;\r
3971\r
3972 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3973\r
3974 //\r
3975 // return the worst status met\r
3976 //\r
3977 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3978\r
3979 if (Private->TextOutList[Index].TextOutEnabled) {\r
3980 Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
3981 if (EFI_ERROR (Status)) {\r
3982 ReturnStatus = Status;\r
3983 }\r
3984 }\r
3985 }\r
3986\r
3987 Status = DevNullTextOutClearScreen (Private);\r
3988 if (EFI_ERROR (Status)) {\r
3989 ReturnStatus = Status;\r
3990 }\r
3991\r
3992 return ReturnStatus;\r
3993}\r
3994\r
3995EFI_STATUS\r
3996EFIAPI\r
3997ConSplitterTextOutSetCursorPosition (\r
3998 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3999 IN UINTN Column,\r
4000 IN UINTN Row\r
4001 )\r
4002/*++\r
4003\r
4004 Routine Description:\r
4005 Sets the current coordinates of the cursor position\r
4006\r
4007 Arguments:\r
4008 This - Protocol instance pointer.\r
4009 Column, Row - the position to set the cursor to. Must be greater than or\r
4010 equal to zero and less than the number of columns and rows\r
4011 by QueryMode ().\r
4012\r
4013 Returns:\r
4014 EFI_SUCCESS - The operation completed successfully.\r
4015 EFI_DEVICE_ERROR - The device had an error and\r
4016 could not complete the request.\r
4017 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the\r
4018 cursor position is invalid for the current mode.\r
4019\r
4020--*/\r
4021{\r
4022 EFI_STATUS Status;\r
4023 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4024 UINTN Index;\r
4025 EFI_STATUS ReturnStatus;\r
4026 UINTN MaxColumn;\r
4027 UINTN MaxRow;\r
de8fe2c2 4028 INT32 *TextOutModeMap;\r
4029 INT32 ModeNumber;\r
4030 INT32 CurrentMode;\r
95276127 4031\r
4032 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
de8fe2c2 4033 TextOutModeMap = NULL;\r
4034 ModeNumber = Private->TextOutMode.Mode;\r
4035 \r
4036 //\r
4037 // Get current MaxColumn and MaxRow from intersection map\r
4038 //\r
4039 if (Private->TextOutModeMap != NULL) {\r
4040 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
4041 CurrentMode = *TextOutModeMap;\r
4042 } else {\r
4043 CurrentMode = ModeNumber;\r
4044 }\r
4045 \r
4046 MaxColumn = Private->TextOutQueryData[CurrentMode].Columns;\r
4047 MaxRow = Private->TextOutQueryData[CurrentMode].Rows;\r
95276127 4048\r
4049 if (Column >= MaxColumn || Row >= MaxRow) {\r
4050 return EFI_UNSUPPORTED;\r
4051 }\r
4052 //\r
4053 // return the worst status met\r
4054 //\r
4055 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4056\r
4057 if (Private->TextOutList[Index].TextOutEnabled) {\r
4058 Status = Private->TextOutList[Index].TextOut->SetCursorPosition (\r
4059 Private->TextOutList[Index].TextOut,\r
4060 Column,\r
4061 Row\r
4062 );\r
4063 if (EFI_ERROR (Status)) {\r
4064 ReturnStatus = Status;\r
4065 }\r
4066 }\r
4067 }\r
4068\r
4069 DevNullTextOutSetCursorPosition (Private, Column, Row);\r
4070\r
4071 return ReturnStatus;\r
4072}\r
4073\r
4074EFI_STATUS\r
4075EFIAPI\r
4076ConSplitterTextOutEnableCursor (\r
4077 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
4078 IN BOOLEAN Visible\r
4079 )\r
4080/*++\r
4081\r
4082 Routine Description:\r
4083 Makes the cursor visible or invisible\r
4084\r
4085 Arguments:\r
4086 This - Protocol instance pointer.\r
4087 Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is\r
4088 set to be invisible.\r
4089\r
4090 Returns:\r
4091 EFI_SUCCESS - The operation completed successfully.\r
4092 EFI_DEVICE_ERROR - The device had an error and could not complete the\r
4093 request, or the device does not support changing\r
4094 the cursor mode.\r
4095 EFI_UNSUPPORTED - The output device is not in a valid text mode.\r
4096\r
4097--*/\r
4098{\r
4099 EFI_STATUS Status;\r
4100 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
4101 UINTN Index;\r
4102 EFI_STATUS ReturnStatus;\r
4103\r
4104 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
4105\r
4106 //\r
4107 // return the worst status met\r
4108 //\r
4109 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
4110\r
4111 if (Private->TextOutList[Index].TextOutEnabled) {\r
4112 Status = Private->TextOutList[Index].TextOut->EnableCursor (\r
4113 Private->TextOutList[Index].TextOut,\r
4114 Visible\r
4115 );\r
4116 if (EFI_ERROR (Status)) {\r
4117 ReturnStatus = Status;\r
4118 }\r
4119 }\r
4120 }\r
4121\r
4122 DevNullTextOutEnableCursor (Private, Visible);\r
4123\r
4124 return ReturnStatus;\r
4125}\r