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