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