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