Check in following modules,
[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
30//\r
31// Include common header file for this module.\r
32//\r
33#include "CommonHeader.h"\r
34\r
35#include "ConSplitter.h"\r
36\r
37//\r
38// Global Variables\r
39//\r
40STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {\r
41 TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
42 (EFI_HANDLE) NULL,\r
43 {\r
44 ConSplitterTextInReset,\r
45 ConSplitterTextInReadKeyStroke,\r
46 (EFI_EVENT) NULL\r
47 },\r
48 0,\r
49 (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
50 0,\r
51\r
52 {\r
53 ConSplitterSimplePointerReset,\r
54 ConSplitterSimplePointerGetState,\r
55 (EFI_EVENT) NULL,\r
56 (EFI_SIMPLE_POINTER_MODE *) NULL\r
57 },\r
58 {\r
59 0x10000,\r
60 0x10000,\r
61 0x10000,\r
62 TRUE,\r
63 TRUE\r
64 },\r
65 0,\r
66 (EFI_SIMPLE_POINTER_PROTOCOL **) NULL,\r
67 0,\r
68\r
69 FALSE,\r
70 {\r
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
75 },\r
76 0,\r
77 {\r
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
82 },\r
83 (EFI_EVENT) NULL,\r
84\r
85 FALSE,\r
86 FALSE\r
87};\r
88\r
89STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {\r
90 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
91 (EFI_HANDLE) NULL,\r
92 {\r
93 ConSplitterTextOutReset,\r
94 ConSplitterTextOutOutputString,\r
95 ConSplitterTextOutTestString,\r
96 ConSplitterTextOutQueryMode,\r
97 ConSplitterTextOutSetMode,\r
98 ConSplitterTextOutSetAttribute,\r
99 ConSplitterTextOutClearScreen,\r
100 ConSplitterTextOutSetCursorPosition,\r
101 ConSplitterTextOutEnableCursor,\r
102 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
103 },\r
104 {\r
105 1,\r
106 0,\r
107 0,\r
108 0,\r
109 0,\r
110 FALSE,\r
111 },\r
112 {\r
113 ConSpliterGraphicsOutputQueryMode,\r
114 ConSpliterGraphicsOutputSetMode,\r
115 ConSpliterGraphicsOutputBlt,\r
116 NULL\r
117 },\r
118 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
119 (TEXT_OUT_GOP_MODE *) NULL,\r
120 0,\r
121 TRUE,\r
122 {\r
123 ConSpliterConsoleControlGetMode,\r
124 ConSpliterConsoleControlSetMode,\r
125 ConSpliterConsoleControlLockStdIn\r
126 },\r
127\r
128 0,\r
129 (TEXT_OUT_AND_GOP_DATA *) NULL,\r
130 0,\r
131 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
132 0,\r
133 (INT32 *) NULL,\r
134\r
135 EfiConsoleControlScreenText,\r
136 0,\r
137 0,\r
138 (CHAR16 *) NULL,\r
139 (INT32 *) NULL\r
140};\r
141\r
142STATIC TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {\r
143 TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE,\r
144 (EFI_HANDLE) NULL,\r
145 {\r
146 ConSplitterTextOutReset,\r
147 ConSplitterTextOutOutputString,\r
148 ConSplitterTextOutTestString,\r
149 ConSplitterTextOutQueryMode,\r
150 ConSplitterTextOutSetMode,\r
151 ConSplitterTextOutSetAttribute,\r
152 ConSplitterTextOutClearScreen,\r
153 ConSplitterTextOutSetCursorPosition,\r
154 ConSplitterTextOutEnableCursor,\r
155 (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL\r
156 },\r
157 {\r
158 1,\r
159 0,\r
160 0,\r
161 0,\r
162 0,\r
163 FALSE,\r
164 },\r
165 {\r
166 ConSpliterGraphicsOutputQueryMode,\r
167 ConSpliterGraphicsOutputSetMode,\r
168 ConSpliterGraphicsOutputBlt,\r
169 NULL\r
170 },\r
171 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
172 (TEXT_OUT_GOP_MODE *) NULL,\r
173 0,\r
174 TRUE,\r
175 {\r
176 ConSpliterConsoleControlGetMode,\r
177 ConSpliterConsoleControlSetMode,\r
178 ConSpliterConsoleControlLockStdIn\r
179 },\r
180\r
181 0,\r
182 (TEXT_OUT_AND_GOP_DATA *) NULL,\r
183 0,\r
184 (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
185 0,\r
186 (INT32 *) NULL,\r
187\r
188 EfiConsoleControlScreenText,\r
189 0,\r
190 0,\r
191 (CHAR16 *) NULL,\r
192 (INT32 *) NULL\r
193};\r
194\r
195EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = {\r
196 ConSplitterConInDriverBindingSupported,\r
197 ConSplitterConInDriverBindingStart,\r
198 ConSplitterConInDriverBindingStop,\r
199 0xa,\r
200 NULL,\r
201 NULL\r
202};\r
203\r
204EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = {\r
205 ConSplitterSimplePointerDriverBindingSupported,\r
206 ConSplitterSimplePointerDriverBindingStart,\r
207 ConSplitterSimplePointerDriverBindingStop,\r
208 0xa,\r
209 NULL,\r
210 NULL\r
211};\r
212\r
213EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = {\r
214 ConSplitterConOutDriverBindingSupported,\r
215 ConSplitterConOutDriverBindingStart,\r
216 ConSplitterConOutDriverBindingStop,\r
217 0xa,\r
218 NULL,\r
219 NULL\r
220};\r
221\r
222EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = {\r
223 ConSplitterStdErrDriverBindingSupported,\r
224 ConSplitterStdErrDriverBindingStart,\r
225 ConSplitterStdErrDriverBindingStop,\r
226 0xa,\r
227 NULL,\r
228 NULL\r
229};\r
230\r
231/**\r
232 The user Entry Point for module ConSplitter. The user code starts with this function.\r
233\r
234 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
235 @param[in] SystemTable A pointer to the EFI System Table.\r
236 \r
237 @retval EFI_SUCCESS The entry point is executed successfully.\r
238 @retval other Some error occurs when executing this entry point.\r
239\r
240**/\r
241EFI_STATUS\r
242EFIAPI\r
243InitializeConSplitter(\r
244 IN EFI_HANDLE ImageHandle,\r
245 IN EFI_SYSTEM_TABLE *SystemTable\r
246 )\r
247{\r
248 EFI_STATUS Status;\r
249\r
250 //\r
251 // Install driver model protocol(s).\r
252 //\r
253 Status = EfiLibInstallAllDriverProtocols (\r
254 ImageHandle,\r
255 SystemTable,\r
256 &gConSplitterConInDriverBinding,\r
257 ImageHandle,\r
258 &gConSplitterConInComponentName,\r
259 NULL,\r
260 NULL\r
261 );\r
262 ASSERT_EFI_ERROR (Status);\r
263\r
264 Status = EfiLibInstallAllDriverProtocols (\r
265 ImageHandle,\r
266 SystemTable,\r
267 &gConSplitterSimplePointerDriverBinding,\r
268 NULL,\r
269 &gConSplitterSimplePointerComponentName,\r
270 NULL,\r
271 NULL\r
272 );\r
273 ASSERT_EFI_ERROR (Status);\r
274\r
275 Status = EfiLibInstallAllDriverProtocols (\r
276 ImageHandle,\r
277 SystemTable,\r
278 &gConSplitterConOutDriverBinding,\r
279 NULL,\r
280 &gConSplitterConOutComponentName,\r
281 NULL,\r
282 NULL\r
283 );\r
284 ASSERT_EFI_ERROR (Status);\r
285\r
286 Status = EfiLibInstallAllDriverProtocols (\r
287 ImageHandle,\r
288 SystemTable,\r
289 &gConSplitterStdErrDriverBinding,\r
290 NULL,\r
291 &gConSplitterStdErrComponentName,\r
292 NULL,\r
293 NULL\r
294 );\r
295 ASSERT_EFI_ERROR (Status);\r
296\r
297\r
298 //\r
299 // Call the original Entry Point\r
300 //\r
301 Status = ConSplitterDriverEntry (ImageHandle, SystemTable);\r
302\r
303 return Status;\r
304}\r
305\r
306\r
307EFI_STATUS\r
308EFIAPI\r
309ConSplitterDriverEntry (\r
310 IN EFI_HANDLE ImageHandle,\r
311 IN EFI_SYSTEM_TABLE *SystemTable\r
312 )\r
313/*++\r
314\r
315Routine Description:\r
316 Intialize a virtual console device to act as an agrigator of physical console\r
317 devices.\r
318\r
319Arguments:\r
320 ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
321 SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
322Returns:\r
323 EFI_SUCCESS\r
324\r
325--*/\r
326{\r
327 EFI_STATUS Status;\r
328\r
329 //\r
330 // The driver creates virtual handles for ConIn, ConOut, and StdErr.\r
331 // The virtual handles will always exist even if no console exist in the\r
332 // system. This is need to support hotplug devices like USB.\r
333 //\r
334 //\r
335 // Create virtual device handle for StdErr Splitter\r
336 //\r
337 Status = ConSplitterTextOutConstructor (&mStdErr);\r
338 if (!EFI_ERROR (Status)) {\r
339 Status = gBS->InstallMultipleProtocolInterfaces (\r
340 &mStdErr.VirtualHandle,\r
341 &gEfiSimpleTextOutProtocolGuid,\r
342 &mStdErr.TextOut,\r
343 &gEfiPrimaryStandardErrorDeviceGuid,\r
344 NULL,\r
345 NULL\r
346 );\r
347 }\r
348 //\r
349 // Create virtual device handle for ConIn Splitter\r
350 //\r
351 Status = ConSplitterTextInConstructor (&mConIn);\r
352 if (!EFI_ERROR (Status)) {\r
353 Status = gBS->InstallMultipleProtocolInterfaces (\r
354 &mConIn.VirtualHandle,\r
355 &gEfiSimpleTextInProtocolGuid,\r
356 &mConIn.TextIn,\r
357 &gEfiSimplePointerProtocolGuid,\r
358 &mConIn.SimplePointer,\r
359 &gEfiPrimaryConsoleInDeviceGuid,\r
360 NULL,\r
361 NULL\r
362 );\r
363 if (!EFI_ERROR (Status)) {\r
364 //\r
365 // Update the EFI System Table with new virtual console\r
366 //\r
367 gST->ConsoleInHandle = mConIn.VirtualHandle;\r
368 gST->ConIn = &mConIn.TextIn;\r
369 }\r
370 }\r
371 //\r
372 // Create virtual device handle for ConOut Splitter\r
373 //\r
374 Status = ConSplitterTextOutConstructor (&mConOut);\r
375 if (!EFI_ERROR (Status)) {\r
376 //\r
377 // In UEFI mode, Graphics Output Protocol is installed on virtual handle.\r
378 //\r
379 Status = gBS->InstallMultipleProtocolInterfaces (\r
380 &mConOut.VirtualHandle,\r
381 &gEfiSimpleTextOutProtocolGuid,\r
382 &mConOut.TextOut,\r
383 &gEfiGraphicsOutputProtocolGuid,\r
384 &mConOut.GraphicsOutput,\r
385 &gEfiConsoleControlProtocolGuid,\r
386 &mConOut.ConsoleControl,\r
387 &gEfiPrimaryConsoleOutDeviceGuid,\r
388 NULL,\r
389 NULL\r
390 );\r
391\r
392 if (!EFI_ERROR (Status)) {\r
393 //\r
394 // Update the EFI System Table with new virtual console\r
395 //\r
396 gST->ConsoleOutHandle = mConOut.VirtualHandle;\r
397 gST->ConOut = &mConOut.TextOut;\r
398 }\r
399\r
400 }\r
401 //\r
402 // Update the CRC32 in the EFI System Table header\r
403 //\r
404 gST->Hdr.CRC32 = 0;\r
405 gBS->CalculateCrc32 (\r
406 (UINT8 *) &gST->Hdr,\r
407 gST->Hdr.HeaderSize,\r
408 &gST->Hdr.CRC32\r
409 );\r
410\r
411 return EFI_SUCCESS;\r
412}\r
413\r
414EFI_STATUS\r
415ConSplitterTextInConstructor (\r
416 TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate\r
417 )\r
418/*++\r
419\r
420Routine Description:\r
421\r
422 Construct the ConSplitter.\r
423\r
424Arguments:\r
425\r
426 ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure.\r
427\r
428Returns:\r
429 EFI_OUT_OF_RESOURCES - Out of resources.\r
430\r
431--*/\r
432{\r
433 EFI_STATUS Status;\r
434\r
435 //\r
436 // Initilize console input splitter's private data.\r
437 //\r
438 Status = ConSplitterGrowBuffer (\r
439 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
440 &ConInPrivate->TextInListCount,\r
441 (VOID **) &ConInPrivate->TextInList\r
442 );\r
443 if (EFI_ERROR (Status)) {\r
444 return EFI_OUT_OF_RESOURCES;\r
445 }\r
446 //\r
447 // Create Event to support locking StdIn Device\r
448 //\r
449 Status = gBS->CreateEvent (\r
450 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
451 TPL_CALLBACK,\r
452 ConSpliterConsoleControlLockStdInEvent,\r
453 NULL,\r
454 &ConInPrivate->LockEvent\r
455 );\r
456 ASSERT_EFI_ERROR (Status);\r
457\r
458 Status = gBS->CreateEvent (\r
459 EVT_NOTIFY_WAIT,\r
460 TPL_NOTIFY,\r
461 ConSplitterTextInWaitForKey,\r
462 ConInPrivate,\r
463 &ConInPrivate->TextIn.WaitForKey\r
464 );\r
465 ASSERT_EFI_ERROR (Status);\r
466\r
467 ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
468\r
469 Status = ConSplitterGrowBuffer (\r
470 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
471 &ConInPrivate->PointerListCount,\r
472 (VOID **) &ConInPrivate->PointerList\r
473 );\r
474 if (EFI_ERROR (Status)) {\r
475 return EFI_OUT_OF_RESOURCES;\r
476 }\r
477\r
478 Status = gBS->CreateEvent (\r
479 EVT_NOTIFY_WAIT,\r
480 TPL_NOTIFY,\r
481 ConSplitterSimplePointerWaitForInput,\r
482 ConInPrivate,\r
483 &ConInPrivate->SimplePointer.WaitForInput\r
484 );\r
485\r
486 return Status;\r
487}\r
488\r
489EFI_STATUS\r
490ConSplitterTextOutConstructor (\r
491 TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate\r
492 )\r
493{\r
494 EFI_STATUS Status;\r
495\r
496 //\r
497 // Initilize console output splitter's private data.\r
498 //\r
499 ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
500\r
501 Status = ConSplitterGrowBuffer (\r
502 sizeof (TEXT_OUT_AND_GOP_DATA),\r
503 &ConOutPrivate->TextOutListCount,\r
504 (VOID **) &ConOutPrivate->TextOutList\r
505 );\r
506 if (EFI_ERROR (Status)) {\r
507 return EFI_OUT_OF_RESOURCES;\r
508 }\r
509\r
510 Status = ConSplitterGrowBuffer (\r
511 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
512 &ConOutPrivate->TextOutQueryDataCount,\r
513 (VOID **) &ConOutPrivate->TextOutQueryData\r
514 );\r
515 if (EFI_ERROR (Status)) {\r
516 return EFI_OUT_OF_RESOURCES;\r
517 }\r
518 //\r
519 // Setup the DevNullTextOut console to 80 x 25\r
520 //\r
521 ConOutPrivate->TextOutQueryData[0].Columns = 80;\r
522 ConOutPrivate->TextOutQueryData[0].Rows = 25;\r
523 DevNullTextOutSetMode (ConOutPrivate, 0);\r
524\r
525 //\r
526 // Setup resource for mode information in Graphics Output Protocol interface\r
527 //\r
528 if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) {\r
529 return EFI_OUT_OF_RESOURCES;\r
530 }\r
531 if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) {\r
532 return EFI_OUT_OF_RESOURCES;\r
533 }\r
534 //\r
535 // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel\r
536 //\r
537 if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (TEXT_OUT_GOP_MODE))) == NULL) {\r
538 return EFI_OUT_OF_RESOURCES;\r
539 }\r
540 ConOutPrivate->GraphicsOutputModeBuffer[0].HorizontalResolution = 800;\r
541 ConOutPrivate->GraphicsOutputModeBuffer[0].VerticalResolution = 600;\r
542\r
543 //\r
544 // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode()\r
545 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat\r
546 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize\r
547 //\r
548 ConOutPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
549 ConOutPrivate->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
550 ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
551 ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
552 ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0;\r
553\r
554 ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
555 //\r
556 // Initial current mode to unknow state, and then set to mode 0\r
557 //\r
558 ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff;\r
559 ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0);\r
560\r
561 return Status;\r
562}\r
563\r
564STATIC\r
565EFI_STATUS\r
566ConSplitterSupported (\r
567 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
568 IN EFI_HANDLE ControllerHandle,\r
569 IN EFI_GUID *Guid\r
570 )\r
571/*++\r
572\r
573Routine Description:\r
574 Generic Supported Check\r
575\r
576Arguments:\r
577 This - Pointer to protocol.\r
578 ControllerHandle - Controller Handle.\r
579 Guid - Guid.\r
580\r
581Returns:\r
582\r
583 EFI_UNSUPPORTED - unsupported.\r
584 EFI_SUCCESS - operation is OK.\r
585\r
586--*/\r
587{\r
588 EFI_STATUS Status;\r
589 VOID *Instance;\r
590\r
591 //\r
592 // Make sure the Console Splitter does not attempt to attach to itself\r
593 //\r
594 if (ControllerHandle == mConIn.VirtualHandle) {\r
595 return EFI_UNSUPPORTED;\r
596 }\r
597\r
598 if (ControllerHandle == mConOut.VirtualHandle) {\r
599 return EFI_UNSUPPORTED;\r
600 }\r
601\r
602 if (ControllerHandle == mStdErr.VirtualHandle) {\r
603 return EFI_UNSUPPORTED;\r
604 }\r
605 //\r
606 // Check to see whether the handle has the ConsoleInDevice GUID on it\r
607 //\r
608 Status = gBS->OpenProtocol (\r
609 ControllerHandle,\r
610 Guid,\r
611 &Instance,\r
612 This->DriverBindingHandle,\r
613 ControllerHandle,\r
614 EFI_OPEN_PROTOCOL_BY_DRIVER\r
615 );\r
616\r
617 if (EFI_ERROR (Status)) {\r
618 return Status;\r
619 }\r
620\r
621 gBS->CloseProtocol (\r
622 ControllerHandle,\r
623 Guid,\r
624 This->DriverBindingHandle,\r
625 ControllerHandle\r
626 );\r
627\r
628 return EFI_SUCCESS;\r
629}\r
630\r
631EFI_STATUS\r
632EFIAPI\r
633ConSplitterConInDriverBindingSupported (\r
634 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
635 IN EFI_HANDLE ControllerHandle,\r
636 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
637 )\r
638/*++\r
639\r
640Routine Description:\r
641 Console In Supported Check\r
642\r
643Arguments:\r
644 This - Pointer to protocol.\r
645 ControllerHandle - Controller handle.\r
646 RemainingDevicePath - Remaining device path.\r
647\r
648Returns:\r
649\r
650 EFI_STATUS\r
651\r
652--*/\r
653{\r
654 return ConSplitterSupported (\r
655 This,\r
656 ControllerHandle,\r
657 &gEfiConsoleInDeviceGuid\r
658 );\r
659}\r
660\r
661EFI_STATUS\r
662EFIAPI\r
663ConSplitterSimplePointerDriverBindingSupported (\r
664 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
665 IN EFI_HANDLE ControllerHandle,\r
666 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
667 )\r
668/*++\r
669\r
670Routine Description:\r
671 Standard Error Supported Check\r
672\r
673Arguments:\r
674 This - Pointer to protocol.\r
675 ControllerHandle - Controller handle.\r
676 RemainingDevicePath - Remaining device path.\r
677\r
678Returns:\r
679\r
680 EFI_STATUS\r
681\r
682--*/\r
683{\r
684 return ConSplitterSupported (\r
685 This,\r
686 ControllerHandle,\r
687 &gEfiSimplePointerProtocolGuid\r
688 );\r
689}\r
690\r
691EFI_STATUS\r
692EFIAPI\r
693ConSplitterConOutDriverBindingSupported (\r
694 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
695 IN EFI_HANDLE ControllerHandle,\r
696 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
697 )\r
698/*++\r
699\r
700Routine Description:\r
701 Console Out Supported Check\r
702\r
703Arguments:\r
704 This - Pointer to protocol.\r
705 ControllerHandle - Controller handle.\r
706 RemainingDevicePath - Remaining device path.\r
707\r
708Returns:\r
709\r
710 EFI_STATUS\r
711\r
712--*/\r
713{\r
714 return ConSplitterSupported (\r
715 This,\r
716 ControllerHandle,\r
717 &gEfiConsoleOutDeviceGuid\r
718 );\r
719}\r
720\r
721EFI_STATUS\r
722EFIAPI\r
723ConSplitterStdErrDriverBindingSupported (\r
724 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
725 IN EFI_HANDLE ControllerHandle,\r
726 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
727 )\r
728/*++\r
729\r
730Routine Description:\r
731 Standard Error Supported Check\r
732\r
733Arguments:\r
734 This - Pointer to protocol.\r
735 ControllerHandle - Controller handle.\r
736 RemainingDevicePath - Remaining device path.\r
737\r
738Returns:\r
739\r
740 EFI_STATUS\r
741\r
742--*/\r
743{\r
744 return ConSplitterSupported (\r
745 This,\r
746 ControllerHandle,\r
747 &gEfiStandardErrorDeviceGuid\r
748 );\r
749}\r
750\r
751STATIC\r
752EFI_STATUS\r
753EFIAPI\r
754ConSplitterStart (\r
755 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
756 IN EFI_HANDLE ControllerHandle,\r
757 IN EFI_HANDLE ConSplitterVirtualHandle,\r
758 IN EFI_GUID *DeviceGuid,\r
759 IN EFI_GUID *InterfaceGuid,\r
760 IN VOID **Interface\r
761 )\r
762/*++\r
763\r
764Routine Description:\r
765 Start ConSplitter on ControllerHandle, and create the virtual\r
766 agrogated console device on first call Start for a SimpleTextIn handle.\r
767\r
768Arguments:\r
769 (Standard DriverBinding Protocol Start() function)\r
770\r
771Returns:\r
772 EFI_ERROR if a SimpleTextIn protocol is not started.\r
773\r
774--*/\r
775{\r
776 EFI_STATUS Status;\r
777 VOID *Instance;\r
778\r
779 //\r
780 // Check to see whether the handle has the ConsoleInDevice GUID on it\r
781 //\r
782 Status = gBS->OpenProtocol (\r
783 ControllerHandle,\r
784 DeviceGuid,\r
785 &Instance,\r
786 This->DriverBindingHandle,\r
787 ControllerHandle,\r
788 EFI_OPEN_PROTOCOL_BY_DRIVER\r
789 );\r
790 if (EFI_ERROR (Status)) {\r
791 return Status;\r
792 }\r
793\r
794 Status = gBS->OpenProtocol (\r
795 ControllerHandle,\r
796 DeviceGuid,\r
797 &Instance,\r
798 This->DriverBindingHandle,\r
799 ConSplitterVirtualHandle,\r
800 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
801 );\r
802 if (EFI_ERROR (Status)) {\r
803 return Status;\r
804 }\r
805\r
806 return gBS->OpenProtocol (\r
807 ControllerHandle,\r
808 InterfaceGuid,\r
809 Interface,\r
810 This->DriverBindingHandle,\r
811 ConSplitterVirtualHandle,\r
812 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
813 );\r
814}\r
815\r
816EFI_STATUS\r
817EFIAPI\r
818ConSplitterConInDriverBindingStart (\r
819 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
820 IN EFI_HANDLE ControllerHandle,\r
821 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
822 )\r
823/*++\r
824\r
825Routine Description:\r
826 Start ConSplitter on ControllerHandle, and create the virtual\r
827 agrogated console device on first call Start for a SimpleTextIn handle.\r
828\r
829Arguments:\r
830 This - Pointer to protocol.\r
831 ControllerHandle - Controller handle.\r
832 RemainingDevicePath - Remaining device path.\r
833\r
834Returns:\r
835\r
836 EFI_STATUS\r
837 EFI_ERROR if a SimpleTextIn protocol is not started.\r
838\r
839--*/\r
840{\r
841 EFI_STATUS Status;\r
842 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
843\r
844 //\r
845 // Start ConSplitter on ControllerHandle, and create the virtual\r
846 // agrogated console device on first call Start for a SimpleTextIn handle.\r
847 //\r
848 Status = ConSplitterStart (\r
849 This,\r
850 ControllerHandle,\r
851 mConIn.VirtualHandle,\r
852 &gEfiConsoleInDeviceGuid,\r
853 &gEfiSimpleTextInProtocolGuid,\r
854 (VOID **) &TextIn\r
855 );\r
856 if (EFI_ERROR (Status)) {\r
857 return Status;\r
858 }\r
859\r
860 return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
861}\r
862\r
863EFI_STATUS\r
864EFIAPI\r
865ConSplitterSimplePointerDriverBindingStart (\r
866 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
867 IN EFI_HANDLE ControllerHandle,\r
868 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
869 )\r
870/*++\r
871\r
872Routine Description:\r
873 Start ConSplitter on ControllerHandle, and create the virtual\r
874 agrogated console device on first call Start for a SimpleTextIn handle.\r
875\r
876Arguments:\r
877 This - Pointer to protocol.\r
878 ControllerHandle - Controller handle.\r
879 RemainingDevicePath - Remaining device path.\r
880\r
881Returns:\r
882\r
883 EFI_ERROR if a SimpleTextIn protocol is not started.\r
884\r
885--*/\r
886{\r
887 EFI_STATUS Status;\r
888 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
889\r
890 Status = ConSplitterStart (\r
891 This,\r
892 ControllerHandle,\r
893 mConIn.VirtualHandle,\r
894 &gEfiSimplePointerProtocolGuid,\r
895 &gEfiSimplePointerProtocolGuid,\r
896 (VOID **) &SimplePointer\r
897 );\r
898 if (EFI_ERROR (Status)) {\r
899 return Status;\r
900 }\r
901\r
902 return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer);\r
903}\r
904\r
905EFI_STATUS\r
906EFIAPI\r
907ConSplitterConOutDriverBindingStart (\r
908 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
909 IN EFI_HANDLE ControllerHandle,\r
910 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
911 )\r
912/*++\r
913\r
914Routine Description:\r
915 Start ConSplitter on ControllerHandle, and create the virtual\r
916 agrogated console device on first call Start for a SimpleTextIn handle.\r
917\r
918Arguments:\r
919 This - Pointer to protocol.\r
920 ControllerHandle - Controller handle.\r
921 RemainingDevicePath - Remaining device path.\r
922\r
923Returns:\r
924 EFI_ERROR if a SimpleTextIn protocol is not started.\r
925\r
926--*/\r
927{\r
928 EFI_STATUS Status;\r
929 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
930 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
931 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
932\r
933 Status = ConSplitterStart (\r
934 This,\r
935 ControllerHandle,\r
936 mConOut.VirtualHandle,\r
937 &gEfiConsoleOutDeviceGuid,\r
938 &gEfiSimpleTextOutProtocolGuid,\r
939 (VOID **) &TextOut\r
940 );\r
941 if (EFI_ERROR (Status)) {\r
942 return Status;\r
943 }\r
944 //\r
945 // Try to Open Graphics Output protocol\r
946 //\r
947 Status = gBS->OpenProtocol (\r
948 ControllerHandle,\r
949 &gEfiGraphicsOutputProtocolGuid,\r
950 (VOID **) &GraphicsOutput,\r
951 This->DriverBindingHandle,\r
952 mConOut.VirtualHandle,\r
953 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
954 );\r
955 if (EFI_ERROR (Status)) {\r
956 GraphicsOutput = NULL;\r
957 }\r
958 //\r
959 // Open UGA_DRAW protocol\r
960 //\r
961 Status = gBS->OpenProtocol (\r
962 ControllerHandle,\r
963 &gEfiUgaDrawProtocolGuid,\r
964 (VOID **) &UgaDraw,\r
965 This->DriverBindingHandle,\r
966 mConOut.VirtualHandle,\r
967 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
968 );\r
969 if (EFI_ERROR (Status)) {\r
970 UgaDraw = NULL;\r
971 }\r
972 //\r
973 // If both ConOut and StdErr incorporate the same Text Out device,\r
974 // their MaxMode and QueryData should be the intersection of both.\r
975 //\r
976 Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);\r
977 ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
978\r
979 return Status;\r
980}\r
981\r
982EFI_STATUS\r
983EFIAPI\r
984ConSplitterStdErrDriverBindingStart (\r
985 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
986 IN EFI_HANDLE ControllerHandle,\r
987 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
988 )\r
989/*++\r
990\r
991Routine Description:\r
992 Start ConSplitter on ControllerHandle, and create the virtual\r
993 agrogated console device on first call Start for a SimpleTextIn handle.\r
994\r
995Arguments:\r
996 This - Pointer to protocol.\r
997 ControllerHandle - Controller handle.\r
998 RemainingDevicePath - Remaining device path.\r
999\r
1000Returns:\r
1001 EFI_ERROR if a SimpleTextIn protocol is not started.\r
1002\r
1003--*/\r
1004{\r
1005 EFI_STATUS Status;\r
1006 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1007\r
1008 Status = ConSplitterStart (\r
1009 This,\r
1010 ControllerHandle,\r
1011 mStdErr.VirtualHandle,\r
1012 &gEfiStandardErrorDeviceGuid,\r
1013 &gEfiSimpleTextOutProtocolGuid,\r
1014 (VOID **) &TextOut\r
1015 );\r
1016 if (EFI_ERROR (Status)) {\r
1017 return Status;\r
1018 }\r
1019 //\r
1020 // If both ConOut and StdErr incorporate the same Text Out device,\r
1021 // their MaxMode and QueryData should be the intersection of both.\r
1022 //\r
1023 Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);\r
1024 ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));\r
1025 if (EFI_ERROR (Status)) {\r
1026 return Status;\r
1027 }\r
1028\r
1029 if (mStdErr.CurrentNumberOfConsoles == 1) {\r
1030 gST->StandardErrorHandle = mStdErr.VirtualHandle;\r
1031 gST->StdErr = &mStdErr.TextOut;\r
1032 //\r
1033 // Update the CRC32 in the EFI System Table header\r
1034 //\r
1035 gST->Hdr.CRC32 = 0;\r
1036 gBS->CalculateCrc32 (\r
1037 (UINT8 *) &gST->Hdr,\r
1038 gST->Hdr.HeaderSize,\r
1039 &gST->Hdr.CRC32\r
1040 );\r
1041 }\r
1042\r
1043 return Status;\r
1044}\r
1045\r
1046STATIC\r
1047EFI_STATUS\r
1048EFIAPI\r
1049ConSplitterStop (\r
1050 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1051 IN EFI_HANDLE ControllerHandle,\r
1052 IN EFI_HANDLE ConSplitterVirtualHandle,\r
1053 IN EFI_GUID *DeviceGuid,\r
1054 IN EFI_GUID *InterfaceGuid,\r
1055 IN VOID **Interface\r
1056 )\r
1057/*++\r
1058\r
1059Routine Description:\r
1060\r
1061Arguments:\r
1062 (Standard DriverBinding Protocol Stop() function)\r
1063\r
1064Returns:\r
1065\r
1066 None\r
1067\r
1068--*/\r
1069{\r
1070 EFI_STATUS Status;\r
1071\r
1072 Status = gBS->OpenProtocol (\r
1073 ControllerHandle,\r
1074 InterfaceGuid,\r
1075 Interface,\r
1076 This->DriverBindingHandle,\r
1077 ControllerHandle,\r
1078 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1079 );\r
1080 if (EFI_ERROR (Status)) {\r
1081 return Status;\r
1082 }\r
1083 //\r
1084 // close the protocol refered.\r
1085 //\r
1086 gBS->CloseProtocol (\r
1087 ControllerHandle,\r
1088 DeviceGuid,\r
1089 This->DriverBindingHandle,\r
1090 ConSplitterVirtualHandle\r
1091 );\r
1092 gBS->CloseProtocol (\r
1093 ControllerHandle,\r
1094 DeviceGuid,\r
1095 This->DriverBindingHandle,\r
1096 ControllerHandle\r
1097 );\r
1098\r
1099 return EFI_SUCCESS;\r
1100}\r
1101\r
1102EFI_STATUS\r
1103EFIAPI\r
1104ConSplitterConInDriverBindingStop (\r
1105 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1106 IN EFI_HANDLE ControllerHandle,\r
1107 IN UINTN NumberOfChildren,\r
1108 IN EFI_HANDLE *ChildHandleBuffer\r
1109 )\r
1110/*++\r
1111\r
1112Routine Description:\r
1113\r
1114Arguments:\r
1115 (Standard DriverBinding Protocol Stop() function)\r
1116\r
1117Returns:\r
1118\r
1119 None\r
1120\r
1121--*/\r
1122{\r
1123 EFI_STATUS Status;\r
1124 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
1125\r
1126 if (NumberOfChildren == 0) {\r
1127 return EFI_SUCCESS;\r
1128 }\r
1129\r
1130 Status = ConSplitterStop (\r
1131 This,\r
1132 ControllerHandle,\r
1133 mConIn.VirtualHandle,\r
1134 &gEfiConsoleInDeviceGuid,\r
1135 &gEfiSimpleTextInProtocolGuid,\r
1136 (VOID **) &TextIn\r
1137 );\r
1138 if (EFI_ERROR (Status)) {\r
1139 return Status;\r
1140 }\r
1141 //\r
1142 // Delete this console input device's data structures.\r
1143 //\r
1144 return ConSplitterTextInDeleteDevice (&mConIn, TextIn);\r
1145}\r
1146\r
1147EFI_STATUS\r
1148EFIAPI\r
1149ConSplitterSimplePointerDriverBindingStop (\r
1150 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1151 IN EFI_HANDLE ControllerHandle,\r
1152 IN UINTN NumberOfChildren,\r
1153 IN EFI_HANDLE *ChildHandleBuffer\r
1154 )\r
1155/*++\r
1156\r
1157Routine Description:\r
1158\r
1159Arguments:\r
1160 (Standard DriverBinding Protocol Stop() function)\r
1161\r
1162Returns:\r
1163\r
1164 None\r
1165\r
1166--*/\r
1167{\r
1168 EFI_STATUS Status;\r
1169 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;\r
1170\r
1171 if (NumberOfChildren == 0) {\r
1172 return EFI_SUCCESS;\r
1173 }\r
1174\r
1175 Status = ConSplitterStop (\r
1176 This,\r
1177 ControllerHandle,\r
1178 mConIn.VirtualHandle,\r
1179 &gEfiSimplePointerProtocolGuid,\r
1180 &gEfiSimplePointerProtocolGuid,\r
1181 (VOID **) &SimplePointer\r
1182 );\r
1183 if (EFI_ERROR (Status)) {\r
1184 return Status;\r
1185 }\r
1186 //\r
1187 // Delete this console input device's data structures.\r
1188 //\r
1189 return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);\r
1190}\r
1191\r
1192EFI_STATUS\r
1193EFIAPI\r
1194ConSplitterConOutDriverBindingStop (\r
1195 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1196 IN EFI_HANDLE ControllerHandle,\r
1197 IN UINTN NumberOfChildren,\r
1198 IN EFI_HANDLE *ChildHandleBuffer\r
1199 )\r
1200/*++\r
1201\r
1202Routine Description:\r
1203\r
1204Arguments:\r
1205 (Standard DriverBinding Protocol Stop() function)\r
1206\r
1207Returns:\r
1208\r
1209 None\r
1210\r
1211--*/\r
1212{\r
1213 EFI_STATUS Status;\r
1214 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1215\r
1216 if (NumberOfChildren == 0) {\r
1217 return EFI_SUCCESS;\r
1218 }\r
1219\r
1220 Status = ConSplitterStop (\r
1221 This,\r
1222 ControllerHandle,\r
1223 mConOut.VirtualHandle,\r
1224 &gEfiConsoleOutDeviceGuid,\r
1225 &gEfiSimpleTextOutProtocolGuid,\r
1226 (VOID **) &TextOut\r
1227 );\r
1228 if (EFI_ERROR (Status)) {\r
1229 return Status;\r
1230 }\r
1231\r
1232 //\r
1233 // Delete this console output device's data structures.\r
1234 //\r
1235 return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);\r
1236}\r
1237\r
1238EFI_STATUS\r
1239EFIAPI\r
1240ConSplitterStdErrDriverBindingStop (\r
1241 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1242 IN EFI_HANDLE ControllerHandle,\r
1243 IN UINTN NumberOfChildren,\r
1244 IN EFI_HANDLE *ChildHandleBuffer\r
1245 )\r
1246/*++\r
1247\r
1248Routine Description:\r
1249\r
1250Arguments:\r
1251 (Standard DriverBinding Protocol Stop() function)\r
1252\r
1253Returns:\r
1254\r
1255 EFI_SUCCESS - Complete successfully.\r
1256\r
1257--*/\r
1258{\r
1259 EFI_STATUS Status;\r
1260 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
1261\r
1262 if (NumberOfChildren == 0) {\r
1263 return EFI_SUCCESS;\r
1264 }\r
1265\r
1266 Status = ConSplitterStop (\r
1267 This,\r
1268 ControllerHandle,\r
1269 mStdErr.VirtualHandle,\r
1270 &gEfiStandardErrorDeviceGuid,\r
1271 &gEfiSimpleTextOutProtocolGuid,\r
1272 (VOID **) &TextOut\r
1273 );\r
1274 if (EFI_ERROR (Status)) {\r
1275 return Status;\r
1276 }\r
1277 //\r
1278 // Delete this console error out device's data structures.\r
1279 //\r
1280 Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
1281 if (EFI_ERROR (Status)) {\r
1282 return Status;\r
1283 }\r
1284\r
1285 if (mStdErr.CurrentNumberOfConsoles == 0) {\r
1286 gST->StandardErrorHandle = NULL;\r
1287 gST->StdErr = NULL;\r
1288 //\r
1289 // Update the CRC32 in the EFI System Table header\r
1290 //\r
1291 gST->Hdr.CRC32 = 0;\r
1292 gBS->CalculateCrc32 (\r
1293 (UINT8 *) &gST->Hdr,\r
1294 gST->Hdr.HeaderSize,\r
1295 &gST->Hdr.CRC32\r
1296 );\r
1297 }\r
1298\r
1299 return Status;\r
1300}\r
1301\r
1302EFI_STATUS\r
1303ConSplitterGrowBuffer (\r
1304 IN UINTN SizeOfCount,\r
1305 IN UINTN *Count,\r
1306 IN OUT VOID **Buffer\r
1307 )\r
1308/*++\r
1309\r
1310Routine Description:\r
1311 Take the passed in Buffer of size SizeOfCount and grow the buffer\r
1312 by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount\r
1313 bytes. Copy the current data in Buffer to the new version of Buffer\r
1314 and free the old version of buffer.\r
1315\r
1316\r
1317Arguments:\r
1318 SizeOfCount - Size of element in array\r
1319 Count - Current number of elements in array\r
1320 Buffer - Bigger version of passed in Buffer with all the data\r
1321\r
1322Returns:\r
1323 EFI_SUCCESS - Buffer size has grown\r
1324 EFI_OUT_OF_RESOURCES - Could not grow the buffer size\r
1325\r
1326 None\r
1327\r
1328--*/\r
1329{\r
1330 UINTN NewSize;\r
1331 UINTN OldSize;\r
1332 VOID *Ptr;\r
1333\r
1334 //\r
1335 // grow the buffer to new buffer size,\r
1336 // copy the old buffer's content to the new-size buffer,\r
1337 // then free the old buffer.\r
1338 //\r
1339 OldSize = *Count * SizeOfCount;\r
1340 *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
1341 NewSize = *Count * SizeOfCount;\r
1342\r
1343 Ptr = AllocateZeroPool (NewSize);\r
1344 if (Ptr == NULL) {\r
1345 return EFI_OUT_OF_RESOURCES;\r
1346 }\r
1347\r
1348 CopyMem (Ptr, *Buffer, OldSize);\r
1349\r
1350 if (*Buffer != NULL) {\r
1351 FreePool (*Buffer);\r
1352 }\r
1353\r
1354 *Buffer = Ptr;\r
1355\r
1356 return EFI_SUCCESS;\r
1357}\r
1358\r
1359EFI_STATUS\r
1360ConSplitterTextInAddDevice (\r
1361 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1362 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1363 )\r
1364/*++\r
1365\r
1366Routine Description:\r
1367\r
1368Arguments:\r
1369\r
1370Returns:\r
1371\r
1372 EFI_SUCCESS\r
1373 EFI_OUT_OF_RESOURCES\r
1374\r
1375--*/\r
1376{\r
1377 EFI_STATUS Status;\r
1378\r
1379 //\r
1380 // If the Text In List is full, enlarge it by calling growbuffer().\r
1381 //\r
1382 if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) {\r
1383 Status = ConSplitterGrowBuffer (\r
1384 sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *),\r
1385 &Private->TextInListCount,\r
1386 (VOID **) &Private->TextInList\r
1387 );\r
1388 if (EFI_ERROR (Status)) {\r
1389 return EFI_OUT_OF_RESOURCES;\r
1390 }\r
1391 }\r
1392 //\r
1393 // Add the new text-in device data structure into the Text In List.\r
1394 //\r
1395 Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;\r
1396 Private->CurrentNumberOfConsoles++;\r
1397\r
1398 //\r
1399 // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
1400 //\r
1401 gBS->CheckEvent (TextIn->WaitForKey);\r
1402\r
1403 return EFI_SUCCESS;\r
1404}\r
1405\r
1406EFI_STATUS\r
1407ConSplitterTextInDeleteDevice (\r
1408 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1409 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn\r
1410 )\r
1411/*++\r
1412\r
1413Routine Description:\r
1414\r
1415Arguments:\r
1416\r
1417Returns:\r
1418\r
1419 EFI_SUCCESS\r
1420 EFI_NOT_FOUND\r
1421\r
1422--*/\r
1423{\r
1424 UINTN Index;\r
1425 //\r
1426 // Remove the specified text-in device data structure from the Text In List,\r
1427 // and rearrange the remaining data structures in the Text In List.\r
1428 //\r
1429 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
1430 if (Private->TextInList[Index] == TextIn) {\r
1431 for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
1432 Private->TextInList[Index] = Private->TextInList[Index + 1];\r
1433 }\r
1434\r
1435 Private->CurrentNumberOfConsoles--;\r
1436 return EFI_SUCCESS;\r
1437 }\r
1438 }\r
1439\r
1440 return EFI_NOT_FOUND;\r
1441}\r
1442\r
1443EFI_STATUS\r
1444ConSplitterSimplePointerAddDevice (\r
1445 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1446 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1447 )\r
1448/*++\r
1449\r
1450Routine Description:\r
1451\r
1452Arguments:\r
1453\r
1454Returns:\r
1455\r
1456 EFI_OUT_OF_RESOURCES\r
1457 EFI_SUCCESS\r
1458\r
1459--*/\r
1460{\r
1461 EFI_STATUS Status;\r
1462\r
1463 //\r
1464 // If the Text In List is full, enlarge it by calling growbuffer().\r
1465 //\r
1466 if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {\r
1467 Status = ConSplitterGrowBuffer (\r
1468 sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),\r
1469 &Private->PointerListCount,\r
1470 (VOID **) &Private->PointerList\r
1471 );\r
1472 if (EFI_ERROR (Status)) {\r
1473 return EFI_OUT_OF_RESOURCES;\r
1474 }\r
1475 }\r
1476 //\r
1477 // Add the new text-in device data structure into the Text In List.\r
1478 //\r
1479 Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;\r
1480 Private->CurrentNumberOfPointers++;\r
1481 return EFI_SUCCESS;\r
1482}\r
1483\r
1484EFI_STATUS\r
1485ConSplitterSimplePointerDeleteDevice (\r
1486 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
1487 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer\r
1488 )\r
1489/*++\r
1490\r
1491Routine Description:\r
1492\r
1493Arguments:\r
1494\r
1495Returns:\r
1496\r
1497 None\r
1498\r
1499--*/\r
1500{\r
1501 UINTN Index;\r
1502 //\r
1503 // Remove the specified text-in device data structure from the Text In List,\r
1504 // and rearrange the remaining data structures in the Text In List.\r
1505 //\r
1506 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
1507 if (Private->PointerList[Index] == SimplePointer) {\r
1508 for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
1509 Private->PointerList[Index] = Private->PointerList[Index + 1];\r
1510 }\r
1511\r
1512 Private->CurrentNumberOfPointers--;\r
1513 return EFI_SUCCESS;\r
1514 }\r
1515 }\r
1516\r
1517 return EFI_NOT_FOUND;\r
1518}\r
1519\r
1520STATIC\r
1521EFI_STATUS\r
1522ConSplitterGrowMapTable (\r
1523 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private\r
1524 )\r
1525/*++\r
1526\r
1527Routine Description:\r
1528\r
1529Arguments:\r
1530\r
1531Returns:\r
1532\r
1533 None\r
1534\r
1535--*/\r
1536{\r
1537 UINTN Size;\r
1538 UINTN NewSize;\r
1539 UINTN TotalSize;\r
1540 INT32 *TextOutModeMap;\r
1541 INT32 *OldTextOutModeMap;\r
1542 INT32 *SrcAddress;\r
1543 INT32 Index;\r
1544\r
1545 NewSize = Private->TextOutListCount * sizeof (INT32);\r
1546 OldTextOutModeMap = Private->TextOutModeMap;\r
1547 TotalSize = NewSize * Private->TextOutQueryDataCount;\r
1548\r
1549 TextOutModeMap = AllocateZeroPool (TotalSize);\r
1550 if (TextOutModeMap == NULL) {\r
1551 return EFI_OUT_OF_RESOURCES;\r
1552 }\r
1553\r
1554 SetMem (TextOutModeMap, TotalSize, 0xFF);\r
1555 Private->TextOutModeMap = TextOutModeMap;\r
1556\r
1557 //\r
1558 // If TextOutList has been enlarged, need to realloc the mode map table\r
1559 // The mode map table is regarded as a two dimension array.\r
1560 //\r
1561 // Old New\r
1562 // 0 ---------> TextOutListCount ----> TextOutListCount\r
1563 // | -------------------------------------------\r
1564 // | | | |\r
1565 // | | | |\r
1566 // | | | |\r
1567 // | | | |\r
1568 // | | | |\r
1569 // \/ | | |\r
1570 // -------------------------------------------\r
1571 // QueryDataCount\r
1572 //\r
1573 if (OldTextOutModeMap != NULL) {\r
1574\r
1575 Size = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
1576 Index = 0;\r
1577 SrcAddress = OldTextOutModeMap;\r
1578\r
1579 //\r
1580 // Copy the old data to the new one\r
1581 //\r
1582 while (Index < Private->TextOutMode.MaxMode) {\r
1583 CopyMem (TextOutModeMap, SrcAddress, Size);\r
1584 TextOutModeMap += NewSize;\r
1585 SrcAddress += Size;\r
1586 Index++;\r
1587 }\r
1588 //\r
1589 // Free the old buffer\r
1590 //\r
1591 FreePool (OldTextOutModeMap);\r
1592 }\r
1593\r
1594 return EFI_SUCCESS;\r
1595}\r
1596\r
1597STATIC\r
1598EFI_STATUS\r
1599ConSplitterAddOutputMode (\r
1600 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1601 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
1602 )\r
1603/*++\r
1604\r
1605Routine Description:\r
1606\r
1607Arguments:\r
1608\r
1609Returns:\r
1610\r
1611 None\r
1612\r
1613--*/\r
1614{\r
1615 EFI_STATUS Status;\r
1616 INT32 MaxMode;\r
1617 INT32 Mode;\r
1618 UINTN Index;\r
1619\r
1620 MaxMode = TextOut->Mode->MaxMode;\r
1621 Private->TextOutMode.MaxMode = MaxMode;\r
1622\r
1623 //\r
1624 // Grow the buffer if query data buffer is not large enough to\r
1625 // hold all the mode supported by the first console.\r
1626 //\r
1627 while (MaxMode > (INT32) Private->TextOutQueryDataCount) {\r
1628 Status = ConSplitterGrowBuffer (\r
1629 sizeof (TEXT_OUT_SPLITTER_QUERY_DATA),\r
1630 &Private->TextOutQueryDataCount,\r
1631 (VOID **) &Private->TextOutQueryData\r
1632 );\r
1633 if (EFI_ERROR (Status)) {\r
1634 return EFI_OUT_OF_RESOURCES;\r
1635 }\r
1636 }\r
1637 //\r
1638 // Allocate buffer for the output mode map\r
1639 //\r
1640 Status = ConSplitterGrowMapTable (Private);\r
1641 if (EFI_ERROR (Status)) {\r
1642 return EFI_OUT_OF_RESOURCES;\r
1643 }\r
1644 //\r
1645 // As the first textout device, directly add the mode in to QueryData\r
1646 // and at the same time record the mapping between QueryData and TextOut.\r
1647 //\r
1648 Mode = 0;\r
1649 Index = 0;\r
1650 while (Mode < MaxMode) {\r
1651 TextOut->QueryMode (\r
1652 TextOut,\r
1653 Mode,\r
1654 &Private->TextOutQueryData[Mode].Columns,\r
1655 &Private->TextOutQueryData[Mode].Rows\r
1656 );\r
1657 Private->TextOutModeMap[Index] = Mode;\r
1658 Mode++;\r
1659 Index += Private->TextOutListCount;\r
1660 }\r
1661\r
1662 return EFI_SUCCESS;\r
1663}\r
1664\r
1665STATIC\r
1666VOID\r
1667ConSplitterGetIntersection (\r
1668 IN INT32 *TextOutModeMap,\r
1669 IN INT32 *NewlyAddedMap,\r
1670 IN UINTN MapStepSize,\r
1671 IN UINTN NewMapStepSize,\r
1672 OUT INT32 *MaxMode,\r
1673 OUT INT32 *CurrentMode\r
1674 )\r
1675{\r
1676 INT32 Index;\r
1677 INT32 *CurrentMapEntry;\r
1678 INT32 *NextMapEntry;\r
1679 INT32 CurrentMaxMode;\r
1680 INT32 Mode;\r
1681\r
1682 Index = 0;\r
1683 CurrentMapEntry = TextOutModeMap;\r
1684 NextMapEntry = TextOutModeMap;\r
1685 CurrentMaxMode = *MaxMode;\r
1686 Mode = *CurrentMode;\r
1687\r
1688 while (Index < CurrentMaxMode) {\r
1689 if (*NewlyAddedMap == -1) {\r
1690 //\r
1691 // This mode is not supported any more. Remove it. Special care\r
1692 // must be taken as this remove will also affect current mode;\r
1693 //\r
1694 if (Index == *CurrentMode) {\r
1695 Mode = -1;\r
1696 } else if (Index < *CurrentMode) {\r
1697 Mode--;\r
1698 }\r
1699 (*MaxMode)--;\r
1700 } else {\r
1701 if (CurrentMapEntry != NextMapEntry) {\r
1702 CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32));\r
1703 }\r
1704\r
1705 NextMapEntry += MapStepSize;\r
1706 }\r
1707\r
1708 CurrentMapEntry += MapStepSize;\r
1709 NewlyAddedMap += NewMapStepSize;\r
1710 Index++;\r
1711 }\r
1712\r
1713 *CurrentMode = Mode;\r
1714\r
1715 return ;\r
1716}\r
1717\r
1718STATIC\r
1719VOID\r
1720ConSplitterSyncOutputMode (\r
1721 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1722 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
1723 )\r
1724/*++\r
1725\r
1726Routine Description:\r
1727\r
1728Arguments:\r
1729 Private - Private data structure.\r
1730 TextOut - Text Out Protocol.\r
1731Returns:\r
1732\r
1733 None\r
1734\r
1735--*/\r
1736{\r
1737 INT32 CurrentMaxMode;\r
1738 INT32 Mode;\r
1739 INT32 Index;\r
1740 INT32 *TextOutModeMap;\r
1741 INT32 *MapTable;\r
1742 TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData;\r
1743 UINTN Rows;\r
1744 UINTN Columns;\r
1745 UINTN StepSize;\r
1746\r
1747 //\r
1748 // Must make sure that current mode won't change even if mode number changes\r
1749 //\r
1750 CurrentMaxMode = Private->TextOutMode.MaxMode;\r
1751 TextOutModeMap = Private->TextOutModeMap;\r
1752 StepSize = Private->TextOutListCount;\r
1753 TextOutQueryData = Private->TextOutQueryData;\r
1754\r
1755 //\r
1756 // Query all the mode that the newly added TextOut supports\r
1757 //\r
1758 Mode = 0;\r
1759 MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles;\r
1760 while (Mode < TextOut->Mode->MaxMode) {\r
1761 TextOut->QueryMode (TextOut, Mode, &Columns, &Rows);\r
1762\r
1763 //\r
1764 // Search the QueryData database to see if they intersects\r
1765 //\r
1766 Index = 0;\r
1767 while (Index < CurrentMaxMode) {\r
1768 if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) {\r
1769 MapTable[Index * StepSize] = Mode;\r
1770 break;\r
1771 }\r
1772\r
1773 Index++;\r
1774 }\r
1775\r
1776 Mode++;\r
1777 }\r
1778 //\r
1779 // Now search the TextOutModeMap table to find the intersection of supported\r
1780 // mode between ConSplitter and the newly added device.\r
1781 //\r
1782 ConSplitterGetIntersection (\r
1783 TextOutModeMap,\r
1784 MapTable,\r
1785 StepSize,\r
1786 StepSize,\r
1787 &Private->TextOutMode.MaxMode,\r
1788 &Private->TextOutMode.Mode\r
1789 );\r
1790\r
1791 return ;\r
1792}\r
1793\r
1794STATIC\r
1795EFI_STATUS\r
1796ConSplitterGetIntersectionBetweenConOutAndStrErr (\r
1797 VOID\r
1798 )\r
1799/*++\r
1800\r
1801Routine Description:\r
1802\r
1803Arguments:\r
1804\r
1805Returns:\r
1806\r
1807 None\r
1808 EFI_OUT_OF_RESOURCES\r
1809\r
1810--*/\r
1811{\r
1812 UINTN ConOutNumOfConsoles;\r
1813 UINTN StdErrNumOfConsoles;\r
1814 TEXT_OUT_AND_GOP_DATA *ConOutTextOutList;\r
1815 TEXT_OUT_AND_GOP_DATA *StdErrTextOutList;\r
1816 UINTN Indexi;\r
1817 UINTN Indexj;\r
1818 UINTN Rows;\r
1819 UINTN Columns;\r
1820 INT32 ConOutMaxMode;\r
1821 INT32 StdErrMaxMode;\r
1822 INT32 Mode;\r
1823 INT32 Index;\r
1824 INT32 *ConOutModeMap;\r
1825 INT32 *StdErrModeMap;\r
1826 INT32 *ConOutMapTable;\r
1827 INT32 *StdErrMapTable;\r
1828 TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData;\r
1829 TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData;\r
1830 BOOLEAN FoundTheSameTextOut;\r
1831 UINTN ConOutMapTableSize;\r
1832 UINTN StdErrMapTableSize;\r
1833\r
1834 ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles;\r
1835 StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles;\r
1836 ConOutTextOutList = mConOut.TextOutList;\r
1837 StdErrTextOutList = mStdErr.TextOutList;\r
1838\r
1839 Indexi = 0;\r
1840 FoundTheSameTextOut = FALSE;\r
1841 while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) {\r
1842 Indexj = 0;\r
1843 while (Indexj < StdErrNumOfConsoles) {\r
1844 if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) {\r
1845 FoundTheSameTextOut = TRUE;\r
1846 break;\r
1847 }\r
1848\r
1849 Indexj++;\r
1850 StdErrTextOutList++;\r
1851 }\r
1852\r
1853 Indexi++;\r
1854 ConOutTextOutList++;\r
1855 }\r
1856\r
1857 if (!FoundTheSameTextOut) {\r
1858 return EFI_SUCCESS;\r
1859 }\r
1860 //\r
1861 // Must make sure that current mode won't change even if mode number changes\r
1862 //\r
1863 ConOutMaxMode = mConOut.TextOutMode.MaxMode;\r
1864 ConOutModeMap = mConOut.TextOutModeMap;\r
1865 ConOutQueryData = mConOut.TextOutQueryData;\r
1866\r
1867 StdErrMaxMode = mStdErr.TextOutMode.MaxMode;\r
1868 StdErrModeMap = mStdErr.TextOutModeMap;\r
1869 StdErrQueryData = mStdErr.TextOutQueryData;\r
1870\r
1871 //\r
1872 // Allocate the map table and set the map table's index to -1.\r
1873 //\r
1874 ConOutMapTableSize = ConOutMaxMode * sizeof (INT32);\r
1875 ConOutMapTable = AllocateZeroPool (ConOutMapTableSize);\r
1876 if (ConOutMapTable == NULL) {\r
1877 return EFI_OUT_OF_RESOURCES;\r
1878 }\r
1879\r
1880 SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF);\r
1881\r
1882 StdErrMapTableSize = StdErrMaxMode * sizeof (INT32);\r
1883 StdErrMapTable = AllocateZeroPool (StdErrMapTableSize);\r
1884 if (StdErrMapTable == NULL) {\r
1885 return EFI_OUT_OF_RESOURCES;\r
1886 }\r
1887\r
1888 SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF);\r
1889\r
1890 //\r
1891 // Find the intersection of the two set of modes. If they actually intersect, the\r
1892 // correponding entry in the map table is set to 1.\r
1893 //\r
1894 Mode = 0;\r
1895 while (Mode < ConOutMaxMode) {\r
1896 //\r
1897 // Search the other's QueryData database to see if they intersect\r
1898 //\r
1899 Index = 0;\r
1900 Rows = ConOutQueryData[Mode].Rows;\r
1901 Columns = ConOutQueryData[Mode].Columns;\r
1902 while (Index < StdErrMaxMode) {\r
1903 if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) {\r
1904 ConOutMapTable[Mode] = 1;\r
1905 StdErrMapTable[Index] = 1;\r
1906 break;\r
1907 }\r
1908\r
1909 Index++;\r
1910 }\r
1911\r
1912 Mode++;\r
1913 }\r
1914 //\r
1915 // Now search the TextOutModeMap table to find the intersection of supported\r
1916 // mode between ConSplitter and the newly added device.\r
1917 //\r
1918 ConSplitterGetIntersection (\r
1919 ConOutModeMap,\r
1920 ConOutMapTable,\r
1921 mConOut.TextOutListCount,\r
1922 1,\r
1923 &(mConOut.TextOutMode.MaxMode),\r
1924 &(mConOut.TextOutMode.Mode)\r
1925 );\r
1926 if (mConOut.TextOutMode.Mode < 0) {\r
1927 mConOut.TextOut.SetMode (&(mConOut.TextOut), 0);\r
1928 }\r
1929\r
1930 ConSplitterGetIntersection (\r
1931 StdErrModeMap,\r
1932 StdErrMapTable,\r
1933 mStdErr.TextOutListCount,\r
1934 1,\r
1935 &(mStdErr.TextOutMode.MaxMode),\r
1936 &(mStdErr.TextOutMode.Mode)\r
1937 );\r
1938 if (mStdErr.TextOutMode.Mode < 0) {\r
1939 mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0);\r
1940 }\r
1941\r
1942 FreePool (ConOutMapTable);\r
1943 FreePool (StdErrMapTable);\r
1944\r
1945 return EFI_SUCCESS;\r
1946}\r
1947\r
1948STATIC\r
1949EFI_STATUS\r
1950ConSplitterAddGraphicsOutputMode (\r
1951 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
1952 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
1953 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
1954 )\r
1955/*++\r
1956\r
1957Routine Description:\r
1958\r
1959Arguments:\r
1960\r
1961Returns:\r
1962\r
1963 None\r
1964\r
1965--*/\r
1966{\r
1967 EFI_STATUS Status;\r
1968 UINTN Index;\r
1969 TEXT_OUT_GOP_MODE *Mode;\r
1970 UINTN SizeOfInfo;\r
1971 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
1972 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode;\r
1973 TEXT_OUT_GOP_MODE *ModeBuffer;\r
1974 TEXT_OUT_GOP_MODE *MatchedMode;\r
1975 UINTN NumberIndex;\r
1976 BOOLEAN Match;\r
1977\r
1978 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
1979 return EFI_UNSUPPORTED;\r
1980 }\r
1981\r
1982 CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;\r
1983\r
1984 if (GraphicsOutput != NULL) {\r
1985 if (Private->CurrentNumberOfGraphicsOutput == 0) {\r
1986 //\r
1987 // This is the first Graphics Output device added\r
1988 //\r
1989 CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode;\r
1990 CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode;\r
1991 CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo);\r
1992 CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo;\r
1993 CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase;\r
1994 CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize;\r
1995\r
1996 //\r
1997 // Allocate resource for the private mode buffer\r
1998 //\r
1999 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * GraphicsOutput->Mode->MaxMode);\r
2000 if (ModeBuffer == NULL) {\r
2001 return EFI_OUT_OF_RESOURCES;\r
2002 }\r
2003 FreePool (Private->GraphicsOutputModeBuffer);\r
2004 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2005\r
2006 //\r
2007 // Store all supported display modes to the private mode buffer\r
2008 //\r
2009 Mode = ModeBuffer;\r
2010 for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) {\r
2011 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info);\r
2012 if (EFI_ERROR (Status)) {\r
2013 return Status;\r
2014 }\r
2015 Mode->HorizontalResolution = Info->HorizontalResolution;\r
2016 Mode->VerticalResolution = Info->VerticalResolution;\r
2017 Mode++;\r
2018 FreePool (Info);\r
2019 }\r
2020 } else {\r
2021 //\r
2022 // Check intersection of display mode\r
2023 //\r
2024 ModeBuffer = AllocatePool (sizeof (TEXT_OUT_GOP_MODE) * CurrentGraphicsOutputMode->MaxMode);\r
2025 if (ModeBuffer == NULL) {\r
2026 return EFI_OUT_OF_RESOURCES;\r
2027 }\r
2028\r
2029 MatchedMode = ModeBuffer;\r
2030 Mode = &Private->GraphicsOutputModeBuffer[0];\r
2031 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2032 Match = FALSE;\r
2033\r
2034 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {\r
2035 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);\r
2036 if (EFI_ERROR (Status)) {\r
2037 return Status;\r
2038 }\r
2039 if ((Info->HorizontalResolution == Mode->HorizontalResolution) &&\r
2040 (Info->VerticalResolution == Mode->VerticalResolution)){\r
2041 Match = TRUE;\r
2042 FreePool (Info);\r
2043 break;\r
2044 }\r
2045 FreePool (Info);\r
2046 }\r
2047\r
2048 if (Match) {\r
2049 CopyMem (MatchedMode, Mode, sizeof (TEXT_OUT_GOP_MODE));\r
2050 MatchedMode++;\r
2051 }\r
2052\r
2053 Mode++;\r
2054 }\r
2055\r
2056 //\r
2057 // Drop the old mode buffer, assign it to a new one\r
2058 //\r
2059 FreePool (Private->GraphicsOutputModeBuffer);\r
2060 Private->GraphicsOutputModeBuffer = ModeBuffer;\r
2061\r
2062 //\r
2063 // Physical frame buffer is no longer available when there are more than one physical GOP devices\r
2064 //\r
2065 CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (TEXT_OUT_GOP_MODE));\r
2066 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2067 ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK));\r
2068 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2069 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2070 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2071 }\r
2072\r
2073 //\r
2074 // Select a prefered Display mode 800x600\r
2075 //\r
2076 for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) {\r
2077 Mode = &Private->GraphicsOutputModeBuffer[Index];\r
2078 if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) {\r
2079 break;\r
2080 }\r
2081 }\r
2082 //\r
2083 // Prefered mode is not found, set to mode 0\r
2084 //\r
2085 if (Index >= CurrentGraphicsOutputMode->MaxMode) {\r
2086 Index = 0;\r
2087 }\r
2088\r
2089 //\r
2090 // Current mode number may need update now, so set it to an invalide mode number\r
2091 //\r
2092 CurrentGraphicsOutputMode->Mode = 0xffff;\r
2093 } else {\r
2094 //\r
2095 // For UGA device, it's inconvenient to retrieve all the supported display modes.\r
2096 // To simplify the implementation, only add one resolution(800x600, 32bit color depth) as defined in UEFI spec\r
2097 //\r
2098 CurrentGraphicsOutputMode->MaxMode = 1;\r
2099 CurrentGraphicsOutputMode->Info->Version = 0;\r
2100 CurrentGraphicsOutputMode->Info->HorizontalResolution = 800;\r
2101 CurrentGraphicsOutputMode->Info->VerticalResolution = 600;\r
2102 CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly;\r
2103 CurrentGraphicsOutputMode->Info->PixelsPerScanLine = 800;\r
2104 CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2105 CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) NULL;\r
2106 CurrentGraphicsOutputMode->FrameBufferSize = 0;\r
2107\r
2108 //\r
2109 // Update the private mode buffer\r
2110 //\r
2111 ModeBuffer = &Private->GraphicsOutputModeBuffer[0];\r
2112 ModeBuffer->HorizontalResolution = 800;\r
2113 ModeBuffer->VerticalResolution = 600;\r
2114\r
2115 //\r
2116 // Current mode is unknow now, set it to an invalid mode number 0xffff\r
2117 //\r
2118 CurrentGraphicsOutputMode->Mode = 0xffff;\r
2119 Index = 0;\r
2120 }\r
2121\r
2122 //\r
2123 // Force GraphicsOutput mode to be set,\r
2124 // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
2125 //\r
2126 Private->HardwareNeedsStarting = TRUE;\r
2127 Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) Index);\r
2128\r
2129 Private->CurrentNumberOfGraphicsOutput++;\r
2130\r
2131 return Status;\r
2132}\r
2133\r
2134EFI_STATUS\r
2135ConSplitterTextOutAddDevice (\r
2136 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2137 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,\r
2138 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
2139 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw\r
2140 )\r
2141/*++\r
2142\r
2143Routine Description:\r
2144\r
2145Arguments:\r
2146\r
2147Returns:\r
2148\r
2149 None\r
2150\r
2151--*/\r
2152{\r
2153 EFI_STATUS Status;\r
2154 UINTN CurrentNumOfConsoles;\r
2155 INT32 CurrentMode;\r
2156 INT32 MaxMode;\r
2157 TEXT_OUT_AND_GOP_DATA *TextAndGop;\r
2158\r
2159 Status = EFI_SUCCESS;\r
2160 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2161\r
2162 //\r
2163 // If the Text Out List is full, enlarge it by calling growbuffer().\r
2164 //\r
2165 while (CurrentNumOfConsoles >= Private->TextOutListCount) {\r
2166 Status = ConSplitterGrowBuffer (\r
2167 sizeof (TEXT_OUT_AND_GOP_DATA),\r
2168 &Private->TextOutListCount,\r
2169 (VOID **) &Private->TextOutList\r
2170 );\r
2171 if (EFI_ERROR (Status)) {\r
2172 return EFI_OUT_OF_RESOURCES;\r
2173 }\r
2174 //\r
2175 // Also need to reallocate the TextOutModeMap table\r
2176 //\r
2177 Status = ConSplitterGrowMapTable (Private);\r
2178 if (EFI_ERROR (Status)) {\r
2179 return EFI_OUT_OF_RESOURCES;\r
2180 }\r
2181 }\r
2182\r
2183 TextAndGop = &Private->TextOutList[CurrentNumOfConsoles];\r
2184\r
2185 TextAndGop->TextOut = TextOut;\r
2186 TextAndGop->GraphicsOutput = GraphicsOutput;\r
2187 TextAndGop->UgaDraw = UgaDraw;\r
2188\r
2189 if ((GraphicsOutput == NULL) && (UgaDraw == NULL)) {\r
2190 //\r
2191 // If No UGA device then use the ConOut device\r
2192 //\r
2193 TextAndGop->TextOutEnabled = TRUE;\r
2194 } else {\r
2195 //\r
2196 // If UGA device use ConOut device only used if UGA screen is in Text mode\r
2197 //\r
2198 TextAndGop->TextOutEnabled = (BOOLEAN) (Private->ConsoleOutputMode == EfiConsoleControlScreenText);\r
2199 }\r
2200\r
2201 if (CurrentNumOfConsoles == 0) {\r
2202 //\r
2203 // Add the first device's output mode to console splitter's mode list\r
2204 //\r
2205 Status = ConSplitterAddOutputMode (Private, TextOut);\r
2206 } else {\r
2207 ConSplitterSyncOutputMode (Private, TextOut);\r
2208 }\r
2209\r
2210 Private->CurrentNumberOfConsoles++;\r
2211\r
2212 //\r
2213 // Scan both TextOutList, for the intersection TextOut device\r
2214 // maybe both ConOut and StdErr incorporate the same Text Out\r
2215 // device in them, thus the output of both should be synced.\r
2216 //\r
2217 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2218\r
2219 CurrentMode = Private->TextOutMode.Mode;\r
2220 MaxMode = Private->TextOutMode.MaxMode;\r
2221 ASSERT (MaxMode >= 1);\r
2222\r
2223 if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
2224 ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
2225 }\r
2226\r
2227 if (Private->ConsoleOutputMode == EfiConsoleControlScreenGraphics && GraphicsOutput != NULL) {\r
2228 //\r
2229 // We just added a new UGA device in graphics mode\r
2230 //\r
2231 DevNullGopSync (Private, GraphicsOutput, UgaDraw);\r
2232 } else if ((CurrentMode >= 0) && ((GraphicsOutput != NULL) || (UgaDraw != NULL)) && (CurrentMode < Private->TextOutMode.MaxMode)) {\r
2233 //\r
2234 // The new console supports the same mode of the current console so sync up\r
2235 //\r
2236 DevNullSyncGopStdOut (Private);\r
2237 } else {\r
2238 //\r
2239 // If ConOut, then set the mode to Mode #0 which us 80 x 25\r
2240 //\r
2241 Private->TextOut.SetMode (&Private->TextOut, 0);\r
2242 }\r
2243\r
2244 return Status;\r
2245}\r
2246\r
2247EFI_STATUS\r
2248ConSplitterTextOutDeleteDevice (\r
2249 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,\r
2250 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut\r
2251 )\r
2252/*++\r
2253\r
2254Routine Description:\r
2255\r
2256Arguments:\r
2257\r
2258Returns:\r
2259\r
2260 None\r
2261\r
2262--*/\r
2263{\r
2264 INT32 Index;\r
2265 UINTN CurrentNumOfConsoles;\r
2266 TEXT_OUT_AND_GOP_DATA *TextOutList;\r
2267 EFI_STATUS Status;\r
2268\r
2269 //\r
2270 // Remove the specified text-out device data structure from the Text out List,\r
2271 // and rearrange the remaining data structures in the Text out List.\r
2272 //\r
2273 CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
2274 Index = (INT32) CurrentNumOfConsoles - 1;\r
2275 TextOutList = Private->TextOutList;\r
2276 while (Index >= 0) {\r
2277 if (TextOutList->TextOut == TextOut) {\r
2278 CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
2279 CurrentNumOfConsoles--;\r
2280 break;\r
2281 }\r
2282\r
2283 Index--;\r
2284 TextOutList++;\r
2285 }\r
2286 //\r
2287 // The specified TextOut is not managed by the ConSplitter driver\r
2288 //\r
2289 if (Index < 0) {\r
2290 return EFI_NOT_FOUND;\r
2291 }\r
2292\r
2293 if (CurrentNumOfConsoles == 0) {\r
2294 //\r
2295 // If the number of consoles is zero clear the Dev NULL device\r
2296 //\r
2297 Private->CurrentNumberOfConsoles = 0;\r
2298 Private->TextOutMode.MaxMode = 1;\r
2299 Private->TextOutQueryData[0].Columns = 80;\r
2300 Private->TextOutQueryData[0].Rows = 25;\r
2301 DevNullTextOutSetMode (Private, 0);\r
2302\r
2303 return EFI_SUCCESS;\r
2304 }\r
2305 //\r
2306 // Max Mode is realy an intersection of the QueryMode command to all\r
2307 // devices. So we must copy the QueryMode of the first device to\r
2308 // QueryData.\r
2309 //\r
2310 ZeroMem (\r
2311 Private->TextOutQueryData,\r
2312 Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA)\r
2313 );\r
2314\r
2315 FreePool (Private->TextOutModeMap);\r
2316 Private->TextOutModeMap = NULL;\r
2317 TextOutList = Private->TextOutList;\r
2318\r
2319 //\r
2320 // Add the first TextOut to the QueryData array and ModeMap table\r
2321 //\r
2322 Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut);\r
2323\r
2324 //\r
2325 // Now add one by one\r
2326 //\r
2327 Index = 1;\r
2328 Private->CurrentNumberOfConsoles = 1;\r
2329 TextOutList++;\r
2330 while ((UINTN) Index < CurrentNumOfConsoles) {\r
2331 ConSplitterSyncOutputMode (Private, TextOutList->TextOut);\r
2332 Index++;\r
2333 Private->CurrentNumberOfConsoles++;\r
2334 TextOutList++;\r
2335 }\r
2336\r
2337 ConSplitterGetIntersectionBetweenConOutAndStrErr ();\r
2338\r
2339 return Status;\r
2340}\r
2341//\r
2342// ConSplitter TextIn member functions\r
2343//\r
2344EFI_STATUS\r
2345EFIAPI\r
2346ConSplitterTextInReset (\r
2347 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
2348 IN BOOLEAN ExtendedVerification\r
2349 )\r
2350/*++\r
2351\r
2352 Routine Description:\r
2353 Reset the input device and optionaly run diagnostics\r
2354\r
2355 Arguments:\r
2356 This - Protocol instance pointer.\r
2357 ExtendedVerification - Driver may perform diagnostics on reset.\r
2358\r
2359 Returns:\r
2360 EFI_SUCCESS - The device was reset.\r
2361 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
2362 not be reset.\r
2363\r
2364--*/\r
2365{\r
2366 EFI_STATUS Status;\r
2367 EFI_STATUS ReturnStatus;\r
2368 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2369 UINTN Index;\r
2370\r
2371 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2372\r
2373 Private->KeyEventSignalState = FALSE;\r
2374\r
2375 //\r
2376 // return the worst status met\r
2377 //\r
2378 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2379 Status = Private->TextInList[Index]->Reset (\r
2380 Private->TextInList[Index],\r
2381 ExtendedVerification\r
2382 );\r
2383 if (EFI_ERROR (Status)) {\r
2384 ReturnStatus = Status;\r
2385 }\r
2386 }\r
2387\r
2388 return ReturnStatus;\r
2389}\r
2390\r
2391EFI_STATUS\r
2392EFIAPI\r
2393ConSplitterTextInPrivateReadKeyStroke (\r
2394 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2395 OUT EFI_INPUT_KEY *Key\r
2396 )\r
2397/*++\r
2398\r
2399 Routine Description:\r
2400 Reads the next keystroke from the input device. The WaitForKey Event can\r
2401 be used to test for existance of a keystroke via WaitForEvent () call.\r
2402\r
2403 Arguments:\r
2404 This - Protocol instance pointer.\r
2405 Key - Driver may perform diagnostics on reset.\r
2406\r
2407 Returns:\r
2408 EFI_SUCCESS - The keystroke information was returned.\r
2409 EFI_NOT_READY - There was no keystroke data availiable.\r
2410 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2411 hardware errors.\r
2412\r
2413--*/\r
2414{\r
2415 EFI_STATUS Status;\r
2416 UINTN Index;\r
2417 EFI_INPUT_KEY CurrentKey;\r
2418\r
2419 Key->UnicodeChar = 0;\r
2420 Key->ScanCode = SCAN_NULL;\r
2421\r
2422 //\r
2423 // if no physical console input device exists, return EFI_NOT_READY;\r
2424 // if any physical console input device has key input,\r
2425 // return the key and EFI_SUCCESS.\r
2426 //\r
2427 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2428 Status = Private->TextInList[Index]->ReadKeyStroke (\r
2429 Private->TextInList[Index],\r
2430 &CurrentKey\r
2431 );\r
2432 if (!EFI_ERROR (Status)) {\r
2433 *Key = CurrentKey;\r
2434 return Status;\r
2435 }\r
2436 }\r
2437\r
2438 return EFI_NOT_READY;\r
2439}\r
2440\r
2441BOOLEAN\r
2442ConSpliterConssoleControlStdInLocked (\r
2443 VOID\r
2444 )\r
2445/*++\r
2446\r
2447Routine Description:\r
2448 Return TRUE if StdIn is locked. The ConIn device on the virtual handle is\r
2449 the only device locked.\r
2450\r
2451Arguments:\r
2452 NONE\r
2453\r
2454Returns:\r
2455 TRUE - StdIn locked\r
2456 FALSE - StdIn working normally\r
2457\r
2458--*/\r
2459{\r
2460 return mConIn.PasswordEnabled;\r
2461}\r
2462\r
2463VOID\r
2464EFIAPI\r
2465ConSpliterConsoleControlLockStdInEvent (\r
2466 IN EFI_EVENT Event,\r
2467 IN VOID *Context\r
2468 )\r
2469/*++\r
2470\r
2471Routine Description:\r
2472 This timer event will fire when StdIn is locked. It will check the key\r
2473 sequence on StdIn to see if it matches the password. Any error in the\r
2474 password will cause the check to reset. As long a mConIn.PasswordEnabled is\r
2475 TRUE the StdIn splitter will not report any input.\r
2476\r
2477Arguments:\r
2478 (Standard EFI_EVENT_NOTIFY)\r
2479\r
2480Returns:\r
2481 None\r
2482\r
2483--*/\r
2484{\r
2485 EFI_STATUS Status;\r
2486 EFI_INPUT_KEY Key;\r
2487 CHAR16 BackSpaceString[2];\r
2488 CHAR16 SpaceString[2];\r
2489\r
2490 do {\r
2491 Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key);\r
2492 if (!EFI_ERROR (Status)) {\r
2493 //\r
2494 // if it's an ENTER, match password\r
2495 //\r
2496 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) {\r
2497 mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL;\r
2498 if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) {\r
2499 //\r
2500 // Password not match\r
2501 //\r
2502 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r");\r
2503 mConIn.PwdIndex = 0;\r
2504 } else {\r
2505 //\r
2506 // Key matches password sequence\r
2507 //\r
2508 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0);\r
2509 mConIn.PasswordEnabled = FALSE;\r
2510 Status = EFI_NOT_READY;\r
2511 }\r
2512 } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) {\r
2513 //\r
2514 // BackSpace met\r
2515 //\r
2516 if (mConIn.PwdIndex > 0) {\r
2517 BackSpaceString[0] = CHAR_BACKSPACE;\r
2518 BackSpaceString[1] = 0;\r
2519\r
2520 SpaceString[0] = ' ';\r
2521 SpaceString[1] = 0;\r
2522\r
2523 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
2524 ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString);\r
2525 ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString);\r
2526\r
2527 mConIn.PwdIndex--;\r
2528 }\r
2529 } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) {\r
2530 //\r
2531 // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input\r
2532 //\r
2533 if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) {\r
2534 if (mConIn.PwdIndex == 0) {\r
2535 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r");\r
2536 }\r
2537\r
2538 ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*");\r
2539 mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar;\r
2540 mConIn.PwdIndex++;\r
2541 }\r
2542 }\r
2543 }\r
2544 } while (!EFI_ERROR (Status));\r
2545}\r
2546\r
2547EFI_STATUS\r
2548EFIAPI\r
2549ConSpliterConsoleControlLockStdIn (\r
2550 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,\r
2551 IN CHAR16 *Password\r
2552 )\r
2553/*++\r
2554\r
2555Routine Description:\r
2556 If Password is NULL unlock the password state variable and set the event\r
2557 timer. If the Password is too big return an error. If the Password is valid\r
2558 Copy the Password and enable state variable and then arm the periodic timer\r
2559\r
2560Arguments:\r
2561\r
2562Returns:\r
2563 EFI_SUCCESS - Lock the StdIn device\r
2564 EFI_INVALID_PARAMETER - Password is NULL\r
2565 EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails\r
2566\r
2567--*/\r
2568{\r
2569 if (Password == NULL) {\r
2570 return EFI_INVALID_PARAMETER;\r
2571 }\r
2572\r
2573 if (StrLen (Password) >= MAX_STD_IN_PASSWORD) {\r
2574 //\r
2575 // Currently have a max password size\r
2576 //\r
2577 return EFI_OUT_OF_RESOURCES;\r
2578 }\r
2579 //\r
2580 // Save the password, initialize state variables and arm event timer\r
2581 //\r
2582 StrCpy (mConIn.Password, Password);\r
2583 mConIn.PasswordEnabled = TRUE;\r
2584 mConIn.PwdIndex = 0;\r
2585 gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25));\r
2586\r
2587 return EFI_SUCCESS;\r
2588}\r
2589\r
2590EFI_STATUS\r
2591EFIAPI\r
2592ConSplitterTextInReadKeyStroke (\r
2593 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
2594 OUT EFI_INPUT_KEY *Key\r
2595 )\r
2596/*++\r
2597\r
2598 Routine Description:\r
2599 Reads the next keystroke from the input device. The WaitForKey Event can\r
2600 be used to test for existance of a keystroke via WaitForEvent () call.\r
2601 If the ConIn is password locked make it look like no keystroke is availible\r
2602\r
2603 Arguments:\r
2604 This - Protocol instance pointer.\r
2605 Key - Driver may perform diagnostics on reset.\r
2606\r
2607 Returns:\r
2608 EFI_SUCCESS - The keystroke information was returned.\r
2609 EFI_NOT_READY - There was no keystroke data availiable.\r
2610 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2611 hardware errors.\r
2612\r
2613--*/\r
2614{\r
2615 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2616\r
2617 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2618 if (Private->PasswordEnabled) {\r
2619 //\r
2620 // If StdIn Locked return not ready\r
2621 //\r
2622 return EFI_NOT_READY;\r
2623 }\r
2624\r
2625 Private->KeyEventSignalState = FALSE;\r
2626\r
2627 return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
2628}\r
2629\r
2630VOID\r
2631EFIAPI\r
2632ConSplitterTextInWaitForKey (\r
2633 IN EFI_EVENT Event,\r
2634 IN VOID *Context\r
2635 )\r
2636/*++\r
2637\r
2638Routine Description:\r
2639 This event agregates all the events of the ConIn devices in the spliter.\r
2640 If the ConIn is password locked then return.\r
2641 If any events of physical ConIn devices are signaled, signal the ConIn\r
2642 spliter event. This will cause the calling code to call\r
2643 ConSplitterTextInReadKeyStroke ().\r
2644\r
2645Arguments:\r
2646 Event - The Event assoicated with callback.\r
2647 Context - Context registered when Event was created.\r
2648\r
2649Returns:\r
2650 None\r
2651\r
2652--*/\r
2653{\r
2654 EFI_STATUS Status;\r
2655 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2656 UINTN Index;\r
2657\r
2658 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
2659 if (Private->PasswordEnabled) {\r
2660 //\r
2661 // If StdIn Locked return not ready\r
2662 //\r
2663 return ;\r
2664 }\r
2665\r
2666 //\r
2667 // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
2668 //\r
2669 if (Private->KeyEventSignalState) {\r
2670 gBS->SignalEvent (Event);\r
2671 return ;\r
2672 }\r
2673 //\r
2674 // if any physical console input device has key input, signal the event.\r
2675 //\r
2676 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2677 Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey);\r
2678 if (!EFI_ERROR (Status)) {\r
2679 gBS->SignalEvent (Event);\r
2680 Private->KeyEventSignalState = TRUE;\r
2681 }\r
2682 }\r
2683}\r
2684\r
2685EFI_STATUS\r
2686EFIAPI\r
2687ConSplitterSimplePointerReset (\r
2688 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
2689 IN BOOLEAN ExtendedVerification\r
2690 )\r
2691/*++\r
2692\r
2693 Routine Description:\r
2694 Reset the input device and optionaly run diagnostics\r
2695\r
2696 Arguments:\r
2697 This - Protocol instance pointer.\r
2698 ExtendedVerification - Driver may perform diagnostics on reset.\r
2699\r
2700 Returns:\r
2701 EFI_SUCCESS - The device was reset.\r
2702 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
2703 not be reset.\r
2704\r
2705--*/\r
2706{\r
2707 EFI_STATUS Status;\r
2708 EFI_STATUS ReturnStatus;\r
2709 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2710 UINTN Index;\r
2711\r
2712 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
2713\r
2714 Private->InputEventSignalState = FALSE;\r
2715\r
2716 if (Private->CurrentNumberOfPointers == 0) {\r
2717 return EFI_SUCCESS;\r
2718 }\r
2719 //\r
2720 // return the worst status met\r
2721 //\r
2722 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) {\r
2723 Status = Private->PointerList[Index]->Reset (\r
2724 Private->PointerList[Index],\r
2725 ExtendedVerification\r
2726 );\r
2727 if (EFI_ERROR (Status)) {\r
2728 ReturnStatus = Status;\r
2729 }\r
2730 }\r
2731\r
2732 return ReturnStatus;\r
2733}\r
2734\r
2735STATIC\r
2736EFI_STATUS\r
2737EFIAPI\r
2738ConSplitterSimplePointerPrivateGetState (\r
2739 IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
2740 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
2741 )\r
2742/*++\r
2743\r
2744 Routine Description:\r
2745 Reads the next keystroke from the input device. The WaitForKey Event can\r
2746 be used to test for existance of a keystroke via WaitForEvent () call.\r
2747\r
2748 Arguments:\r
2749 This - Protocol instance pointer.\r
2750 State -\r
2751\r
2752 Returns:\r
2753 EFI_SUCCESS - The keystroke information was returned.\r
2754 EFI_NOT_READY - There was no keystroke data availiable.\r
2755 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2756 hardware errors.\r
2757\r
2758--*/\r
2759{\r
2760 EFI_STATUS Status;\r
2761 EFI_STATUS ReturnStatus;\r
2762 UINTN Index;\r
2763 EFI_SIMPLE_POINTER_STATE CurrentState;\r
2764\r
2765 State->RelativeMovementX = 0;\r
2766 State->RelativeMovementY = 0;\r
2767 State->RelativeMovementZ = 0;\r
2768 State->LeftButton = FALSE;\r
2769 State->RightButton = FALSE;\r
2770\r
2771 //\r
2772 // if no physical console input device exists, return EFI_NOT_READY;\r
2773 // if any physical console input device has key input,\r
2774 // return the key and EFI_SUCCESS.\r
2775 //\r
2776 ReturnStatus = EFI_NOT_READY;\r
2777 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
2778\r
2779 Status = Private->PointerList[Index]->GetState (\r
2780 Private->PointerList[Index],\r
2781 &CurrentState\r
2782 );\r
2783 if (!EFI_ERROR (Status)) {\r
2784 if (ReturnStatus == EFI_NOT_READY) {\r
2785 ReturnStatus = EFI_SUCCESS;\r
2786 }\r
2787\r
2788 if (CurrentState.LeftButton) {\r
2789 State->LeftButton = TRUE;\r
2790 }\r
2791\r
2792 if (CurrentState.RightButton) {\r
2793 State->RightButton = TRUE;\r
2794 }\r
2795\r
2796 if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) {\r
2797 State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX;\r
2798 }\r
2799\r
2800 if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) {\r
2801 State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY;\r
2802 }\r
2803\r
2804 if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) {\r
2805 State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ;\r
2806 }\r
2807 } else if (Status == EFI_DEVICE_ERROR) {\r
2808 ReturnStatus = EFI_DEVICE_ERROR;\r
2809 }\r
2810 }\r
2811\r
2812 return ReturnStatus;\r
2813}\r
2814\r
2815EFI_STATUS\r
2816EFIAPI\r
2817ConSplitterSimplePointerGetState (\r
2818 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
2819 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
2820 )\r
2821/*++\r
2822\r
2823 Routine Description:\r
2824 Reads the next keystroke from the input device. The WaitForKey Event can\r
2825 be used to test for existance of a keystroke via WaitForEvent () call.\r
2826 If the ConIn is password locked make it look like no keystroke is availible\r
2827\r
2828 Arguments:\r
2829 This - Protocol instance pointer.\r
2830 State -\r
2831\r
2832 Returns:\r
2833 EFI_SUCCESS - The keystroke information was returned.\r
2834 EFI_NOT_READY - There was no keystroke data availiable.\r
2835 EFI_DEVICE_ERROR - The keydtroke information was not returned due to\r
2836 hardware errors.\r
2837\r
2838--*/\r
2839{\r
2840 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2841\r
2842 Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This);\r
2843 if (Private->PasswordEnabled) {\r
2844 //\r
2845 // If StdIn Locked return not ready\r
2846 //\r
2847 return EFI_NOT_READY;\r
2848 }\r
2849\r
2850 Private->InputEventSignalState = FALSE;\r
2851\r
2852 return ConSplitterSimplePointerPrivateGetState (Private, State);\r
2853}\r
2854\r
2855VOID\r
2856EFIAPI\r
2857ConSplitterSimplePointerWaitForInput (\r
2858 IN EFI_EVENT Event,\r
2859 IN VOID *Context\r
2860 )\r
2861/*++\r
2862\r
2863Routine Description:\r
2864 This event agregates all the events of the ConIn devices in the spliter.\r
2865 If the ConIn is password locked then return.\r
2866 If any events of physical ConIn devices are signaled, signal the ConIn\r
2867 spliter event. This will cause the calling code to call\r
2868 ConSplitterTextInReadKeyStroke ().\r
2869\r
2870Arguments:\r
2871 Event - The Event assoicated with callback.\r
2872 Context - Context registered when Event was created.\r
2873\r
2874Returns:\r
2875 None\r
2876\r
2877--*/\r
2878{\r
2879 EFI_STATUS Status;\r
2880 TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
2881 UINTN Index;\r
2882\r
2883 Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context;\r
2884 if (Private->PasswordEnabled) {\r
2885 //\r
2886 // If StdIn Locked return not ready\r
2887 //\r
2888 return ;\r
2889 }\r
2890\r
2891 //\r
2892 // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke()\r
2893 //\r
2894 if (Private->InputEventSignalState) {\r
2895 gBS->SignalEvent (Event);\r
2896 return ;\r
2897 }\r
2898 //\r
2899 // if any physical console input device has key input, signal the event.\r
2900 //\r
2901 for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
2902 Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput);\r
2903 if (!EFI_ERROR (Status)) {\r
2904 gBS->SignalEvent (Event);\r
2905 Private->InputEventSignalState = TRUE;\r
2906 }\r
2907 }\r
2908}\r
2909\r
2910EFI_STATUS\r
2911EFIAPI\r
2912ConSplitterTextOutReset (\r
2913 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
2914 IN BOOLEAN ExtendedVerification\r
2915 )\r
2916/*++\r
2917\r
2918 Routine Description:\r
2919 Reset the text output device hardware and optionaly run diagnostics\r
2920\r
2921 Arguments:\r
2922 This - Protocol instance pointer.\r
2923 ExtendedVerification - Driver may perform more exhaustive verfication\r
2924 operation of the device during reset.\r
2925\r
2926 Returns:\r
2927 EFI_SUCCESS - The text output device was reset.\r
2928 EFI_DEVICE_ERROR - The text output device is not functioning correctly and\r
2929 could not be reset.\r
2930\r
2931--*/\r
2932{\r
2933 EFI_STATUS Status;\r
2934 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
2935 UINTN Index;\r
2936 EFI_STATUS ReturnStatus;\r
2937\r
2938 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
2939\r
2940 //\r
2941 // return the worst status met\r
2942 //\r
2943 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
2944\r
2945 if (Private->TextOutList[Index].TextOutEnabled) {\r
2946\r
2947 Status = Private->TextOutList[Index].TextOut->Reset (\r
2948 Private->TextOutList[Index].TextOut,\r
2949 ExtendedVerification\r
2950 );\r
2951 if (EFI_ERROR (Status)) {\r
2952 ReturnStatus = Status;\r
2953 }\r
2954 }\r
2955 }\r
2956\r
2957 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
2958\r
2959 Status = DevNullTextOutSetMode (Private, 0);\r
2960 if (EFI_ERROR (Status)) {\r
2961 ReturnStatus = Status;\r
2962 }\r
2963\r
2964 return ReturnStatus;\r
2965}\r
2966\r
2967EFI_STATUS\r
2968EFIAPI\r
2969ConSplitterTextOutOutputString (\r
2970 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
2971 IN CHAR16 *WString\r
2972 )\r
2973/*++\r
2974\r
2975 Routine Description:\r
2976 Write a Unicode string to the output device.\r
2977\r
2978 Arguments:\r
2979 This - Protocol instance pointer.\r
2980 String - The NULL-terminated Unicode string to be displayed on the output\r
2981 device(s). All output devices must also support the Unicode\r
2982 drawing defined in this file.\r
2983\r
2984 Returns:\r
2985 EFI_SUCCESS - The string was output to the device.\r
2986 EFI_DEVICE_ERROR - The device reported an error while attempting to output\r
2987 the text.\r
2988 EFI_UNSUPPORTED - The output device's mode is not currently in a\r
2989 defined text mode.\r
2990 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the\r
2991 characters in the Unicode string could not be\r
2992 rendered and were skipped.\r
2993\r
2994--*/\r
2995{\r
2996 EFI_STATUS Status;\r
2997 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
2998 UINTN Index;\r
2999 UINTN BackSpaceCount;\r
3000 EFI_STATUS ReturnStatus;\r
3001 CHAR16 *TargetString;\r
3002\r
3003 This->SetAttribute (This, This->Mode->Attribute);\r
3004\r
3005 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3006\r
3007 BackSpaceCount = 0;\r
3008 for (TargetString = WString; *TargetString; TargetString++) {\r
3009 if (*TargetString == CHAR_BACKSPACE) {\r
3010 BackSpaceCount++;\r
3011 }\r
3012\r
3013 }\r
3014\r
3015 if (BackSpaceCount == 0) {\r
3016 TargetString = WString;\r
3017 } else {\r
3018 TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
3019 StrCpy (TargetString, WString);\r
3020 }\r
3021 //\r
3022 // return the worst status met\r
3023 //\r
3024 Status = DevNullTextOutOutputString (Private, TargetString);\r
3025 if (EFI_ERROR (Status)) {\r
3026 ReturnStatus = Status;\r
3027 }\r
3028\r
3029 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3030\r
3031 if (Private->TextOutList[Index].TextOutEnabled) {\r
3032 Status = Private->TextOutList[Index].TextOut->OutputString (\r
3033 Private->TextOutList[Index].TextOut,\r
3034 TargetString\r
3035 );\r
3036 if (EFI_ERROR (Status)) {\r
3037 ReturnStatus = Status;\r
3038 }\r
3039 }\r
3040 }\r
3041\r
3042 if (BackSpaceCount) {\r
3043 FreePool (TargetString);\r
3044 }\r
3045\r
3046 return ReturnStatus;\r
3047}\r
3048\r
3049EFI_STATUS\r
3050EFIAPI\r
3051ConSplitterTextOutTestString (\r
3052 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3053 IN CHAR16 *WString\r
3054 )\r
3055/*++\r
3056\r
3057 Routine Description:\r
3058 Verifies that all characters in a Unicode string can be output to the\r
3059 target device.\r
3060\r
3061 Arguments:\r
3062 This - Protocol instance pointer.\r
3063 String - The NULL-terminated Unicode string to be examined for the output\r
3064 device(s).\r
3065\r
3066 Returns:\r
3067 EFI_SUCCESS - The device(s) are capable of rendering the output string.\r
3068 EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be\r
3069 rendered by one or more of the output devices mapped\r
3070 by the EFI handle.\r
3071\r
3072--*/\r
3073{\r
3074 EFI_STATUS Status;\r
3075 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3076 UINTN Index;\r
3077 EFI_STATUS ReturnStatus;\r
3078\r
3079 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3080\r
3081 //\r
3082 // return the worst status met\r
3083 //\r
3084 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3085 if (Private->TextOutList[Index].TextOutEnabled) {\r
3086 Status = Private->TextOutList[Index].TextOut->TestString (\r
3087 Private->TextOutList[Index].TextOut,\r
3088 WString\r
3089 );\r
3090 if (EFI_ERROR (Status)) {\r
3091 ReturnStatus = Status;\r
3092 }\r
3093 }\r
3094 }\r
3095 //\r
3096 // There is no DevNullTextOutTestString () since a Unicode buffer would\r
3097 // always return EFI_SUCCESS.\r
3098 // ReturnStatus will be EFI_SUCCESS if no consoles are present\r
3099 //\r
3100 return ReturnStatus;\r
3101}\r
3102\r
3103EFI_STATUS\r
3104EFIAPI\r
3105ConSplitterTextOutQueryMode (\r
3106 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3107 IN UINTN ModeNumber,\r
3108 OUT UINTN *Columns,\r
3109 OUT UINTN *Rows\r
3110 )\r
3111/*++\r
3112\r
3113 Routine Description:\r
3114 Returns information for an available text mode that the output device(s)\r
3115 supports.\r
3116\r
3117 Arguments:\r
3118 This - Protocol instance pointer.\r
3119 ModeNumber - The mode number to return information on.\r
3120 Columns, Rows - Returns the geometry of the text output device for the\r
3121 requested ModeNumber.\r
3122\r
3123 Returns:\r
3124 EFI_SUCCESS - The requested mode information was returned.\r
3125 EFI_DEVICE_ERROR - The device had an error and could not\r
3126 complete the request.\r
3127 EFI_UNSUPPORTED - The mode number was not valid.\r
3128\r
3129--*/\r
3130{\r
3131 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3132\r
3133 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3134\r
3135 //\r
3136 // Check whether param ModeNumber is valid.\r
3137 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
3138 //\r
3139 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
3140 return EFI_UNSUPPORTED;\r
3141 }\r
3142\r
3143 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
3144 return EFI_UNSUPPORTED;\r
3145 }\r
3146\r
3147 *Columns = Private->TextOutQueryData[ModeNumber].Columns;\r
3148 *Rows = Private->TextOutQueryData[ModeNumber].Rows;\r
3149\r
3150 if (*Columns <= 0 && *Rows <= 0) {\r
3151 return EFI_UNSUPPORTED;\r
3152\r
3153 }\r
3154\r
3155 return EFI_SUCCESS;\r
3156}\r
3157\r
3158EFI_STATUS\r
3159EFIAPI\r
3160ConSplitterTextOutSetMode (\r
3161 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3162 IN UINTN ModeNumber\r
3163 )\r
3164/*++\r
3165\r
3166 Routine Description:\r
3167 Sets the output device(s) to a specified mode.\r
3168\r
3169 Arguments:\r
3170 This - Protocol instance pointer.\r
3171 ModeNumber - The mode number to set.\r
3172\r
3173 Returns:\r
3174 EFI_SUCCESS - The requested text mode was set.\r
3175 EFI_DEVICE_ERROR - The device had an error and\r
3176 could not complete the request.\r
3177 EFI_UNSUPPORTED - The mode number was not valid.\r
3178\r
3179--*/\r
3180{\r
3181 EFI_STATUS Status;\r
3182 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
3183 UINTN Index;\r
3184 INT32 *TextOutModeMap;\r
3185 EFI_STATUS ReturnStatus;\r
3186\r
3187 Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
3188\r
3189 //\r
3190 // Check whether param ModeNumber is valid.\r
3191 // ModeNumber should be within range 0 ~ MaxMode - 1.\r
3192 //\r
3193 if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) {\r
3194 return EFI_UNSUPPORTED;\r
3195 }\r
3196\r
3197 if ((INT32) ModeNumber >= This->Mode->MaxMode) {\r
3198 return EFI_UNSUPPORTED;\r
3199 }\r
3200 //\r
3201 // If the mode is being set to the curent mode, then just clear the screen and return.\r
3202 //\r
3203 if (Private->TextOutMode.Mode == (INT32) ModeNumber) {\r
3204 return ConSplitterTextOutClearScreen (This);\r
3205 }\r
3206 //\r
3207 // return the worst status met\r
3208 //\r
3209 TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
3210 for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
3211\r
3212 if (Private->TextOutList[Index].TextOutEnabled) {\r
3213 Status = Private->TextOutList[Index].TextOut->SetMode (\r
3214 Private->TextOutList[Index].TextOut,\r
3215 TextOutModeMap[Index]\r
3216 );\r
3217 //\r
3218 // If this console device is based on a UGA device, then sync up the bitmap from\r
3219 // the UGA splitter and reclear the text portion of the display in the new mode.\r
3220 //\r
3221 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {\r
3222 Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut);\r
3223 }\r
3224\r
3225 if (EFI_ERROR (Status)) {\r
3226 ReturnStatus = Status;\r
3227 }\r
3228 }\r
3229 }\r
3230 //\r
3231 // The DevNull Console will support any possible mode as it allocates memory\r
3232 //\r
3233 Status = DevNullTextOutSetMode (Private, ModeNumber);\r
3234 if (EFI_ERROR (Status)) {\r
3235 ReturnStatus = Status;\r
3236 }\r
3237\r
3238 return ReturnStatus;\r
3239}\r
3240\r
3241EFI_STATUS\r
3242EFIAPI\r
3243ConSplitterTextOutSetAttribute (\r
3244 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
3245 IN UINTN Attribute\r
3246 )\r
3247/*++\r
3248\r
3249 Routine Description:\r
3250 Sets the background and foreground colors for the OutputString () and\r
3251 ClearScreen () functions.\r
3252\r
3253 Arguments:\r
3254 This - Protocol instance pointer.\r
3255 Attribute - The attribute to set. Bits 0..3 are the foreground color, an