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