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