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