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