3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Support for ConsoleControl protocol. Support for UGA Draw spliter.
19 Support for DevNull Console Out. This console uses memory buffers
20 to represnt the console. It allows a console to start very early and
21 when a new console is added it is synced up with the current console
27 // Include common header file for this module.
29 #include "CommonHeader.h"
31 #include "ConSplitter.h"
33 #include <Protocol/FrameworkHii.h>
35 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
39 ConSpliterConsoleControlGetMode (
40 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
41 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE
*Mode
,
42 OUT BOOLEAN
*GopExists
,
43 OUT BOOLEAN
*StdInLocked
48 Return the current video mode information. Also returns info about existence
49 of UGA Draw devices in system, and if the Std In device is locked. All the
50 arguments are optional and only returned if a non NULL pointer is passed in.
53 This - Protocol instance pointer.
54 Mode - Are we in text of grahics mode.
55 UgaExists - TRUE if UGA Spliter has found a UGA device
56 StdInLocked - TRUE if StdIn device is keyboard locked
59 EFI_SUCCESS - Mode information returned.
60 EFI_INVALID_PARAMETER - Invalid parameters.
64 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
67 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
70 return EFI_INVALID_PARAMETER
;
73 *Mode
= Private
->ConsoleOutputMode
;
75 if (GopExists
!= NULL
) {
77 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
78 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
85 if (StdInLocked
!= NULL
) {
86 *StdInLocked
= ConSpliterConssoleControlStdInLocked ();
94 ConSpliterConsoleControlSetMode (
95 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
96 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
101 Set the current mode to either text or graphics. Graphics is
105 This - Protocol instance pointer.
106 Mode - Mode to set the
109 EFI_SUCCESS - Mode information returned.
110 EFI_INVALID_PARAMETER - Invalid parameter.
111 EFI_UNSUPPORTED - Operation unsupported.
115 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
117 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
120 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
122 if (Mode
>= EfiConsoleControlScreenMaxValue
) {
123 return EFI_INVALID_PARAMETER
;
127 // Judge current mode with wanted mode at first.
129 if (Private
->ConsoleOutputMode
== Mode
) {
134 TextAndGop
= &Private
->TextOutList
[0];
135 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
136 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
142 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
143 return EFI_UNSUPPORTED
;
146 Private
->ConsoleOutputMode
= Mode
;
148 TextAndGop
= &Private
->TextOutList
[0];
149 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
151 TextAndGop
->TextOutEnabled
= TRUE
;
153 // If we are going into Graphics mode disable ConOut to any UGA device
155 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
156 TextAndGop
->TextOutEnabled
= FALSE
;
157 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
161 if (Mode
== EfiConsoleControlScreenText
) {
162 DevNullSyncGopStdOut (Private
);
170 ConSpliterGraphicsOutputQueryMode (
171 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
172 IN UINT32 ModeNumber
,
173 OUT UINTN
*SizeOfInfo
,
174 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
179 Return the current video mode information.
182 This - Protocol instance pointer.
183 ModeNumber - The mode number to return information on.
184 Info - Caller allocated buffer that returns information about ModeNumber.
185 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
188 EFI_SUCCESS - Mode information returned.
189 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
190 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
191 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
192 EFI_INVALID_PARAMETER - One of the input args was NULL.
196 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
197 TEXT_OUT_GOP_MODE
*Mode
;
199 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
200 return EFI_INVALID_PARAMETER
;
204 // retrieve private data
206 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
208 if (Private
->HardwareNeedsStarting
) {
209 return EFI_NOT_STARTED
;
212 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
215 return EFI_OUT_OF_RESOURCES
;
218 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
220 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
221 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
222 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
223 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
224 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
231 ConSpliterGraphicsOutputSetMode (
232 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
239 Graphics output protocol interface to set video mode
242 This - Protocol instance pointer.
243 ModeNumber - The mode number to be set.
246 EFI_SUCCESS - Graphics mode was changed.
247 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
248 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
253 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
255 EFI_STATUS ReturnStatus
;
256 TEXT_OUT_GOP_MODE
*Mode
;
258 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
261 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
262 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
264 if (ModeNumber
>= This
->Mode
->MaxMode
) {
265 return EFI_UNSUPPORTED
;
268 if (ModeNumber
== This
->Mode
->Mode
) {
272 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
275 // GopDevNullSetMode ()
277 ReturnStatus
= EFI_SUCCESS
;
280 // Free the old version
282 if (Private
->GraphicsOutputBlt
!= NULL
) {
283 FreePool (Private
->GraphicsOutputBlt
);
287 // Allocate the virtual Blt buffer
289 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
290 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
291 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
293 if (Private
->GraphicsOutputBlt
== NULL
) {
294 return EFI_OUT_OF_RESOURCES
;
297 if (!Private
->HardwareNeedsStarting
) {
298 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
299 return EFI_UNSUPPORTED
;
303 // return the worst status met
305 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
306 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
307 if (GraphicsOutput
!= NULL
) {
309 // Find corresponding ModeNumber of this GraphicsOutput instance
311 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
312 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
313 if (EFI_ERROR (Status
)) {
316 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
323 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
324 if (EFI_ERROR (Status
)) {
325 ReturnStatus
= Status
;
329 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
330 if (UgaDraw
!= NULL
) {
331 Status
= UgaDraw
->SetMode (
333 Mode
->HorizontalResolution
,
334 Mode
->VerticalResolution
,
338 if (EFI_ERROR (Status
)) {
339 ReturnStatus
= Status
;
344 This
->Mode
->Mode
= ModeNumber
;
346 Info
= This
->Mode
->Info
;
347 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
348 Info
->VerticalResolution
= Mode
->VerticalResolution
;
349 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
352 // Information is not enough here, so the following items remain unchanged:
353 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
354 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
355 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
358 Private
->HardwareNeedsStarting
= FALSE
;
365 DevNullGraphicsOutputBlt (
366 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
367 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
368 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
371 IN UINTN DestinationX
,
372 IN UINTN DestinationY
,
375 IN UINTN Delta OPTIONAL
381 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
382 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
383 UINTN HorizontalResolution
;
384 UINTN VerticalResolution
;
386 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
387 return EFI_INVALID_PARAMETER
;
390 if (Width
== 0 || Height
== 0) {
391 return EFI_INVALID_PARAMETER
;
395 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
398 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
399 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
402 // We need to fill the Virtual Screen buffer with the blt data.
404 if (BltOperation
== EfiBltVideoToBltBuffer
) {
406 // Video to BltBuffer: Source is Video, destination is BltBuffer
408 if ((SourceY
+ Height
) > VerticalResolution
) {
409 return EFI_INVALID_PARAMETER
;
412 if ((SourceX
+ Width
) > HorizontalResolution
) {
413 return EFI_INVALID_PARAMETER
;
416 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
417 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
419 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
420 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
421 ScreenPtr
+= HorizontalResolution
;
426 // BltBuffer to Video: Source is BltBuffer, destination is Video
428 if (DestinationY
+ Height
> VerticalResolution
) {
429 return EFI_INVALID_PARAMETER
;
432 if (DestinationX
+ Width
> HorizontalResolution
) {
433 return EFI_INVALID_PARAMETER
;
436 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
438 // Copy backwards, only care the Video to Video Blt
440 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
441 SrcY
= SourceY
+ Height
- 1;
445 // Copy forwards, for other cases
447 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
452 while (Height
!= 0) {
453 if (BltOperation
== EfiBltVideoFill
) {
454 for (Index
= 0; Index
< Width
; Index
++) {
455 ScreenPtr
[Index
] = *BltBuffer
;
458 if (BltOperation
== EfiBltBufferToVideo
) {
459 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
461 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
464 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
468 ScreenPtr
+= HorizontalResolution
;
471 ScreenPtr
-= HorizontalResolution
;
483 ConSpliterGraphicsOutputBlt (
484 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
485 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
486 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
489 IN UINTN DestinationX
,
490 IN UINTN DestinationY
,
493 IN UINTN Delta OPTIONAL
498 The following table defines actions for BltOperations:
499 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
500 directly to every pixel of the video display rectangle
501 (DestinationX, DestinationY)
502 (DestinationX + Width, DestinationY + Height).
503 Only one pixel will be used from the BltBuffer. Delta is NOT used.
504 EfiBltVideoToBltBuffer - Read data from the video display rectangle
505 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
506 the BltBuffer rectangle (DestinationX, DestinationY )
507 (DestinationX + Width, DestinationY + Height). If DestinationX or
508 DestinationY is not zero then Delta must be set to the length in bytes
509 of a row in the BltBuffer.
510 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
511 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
512 video display rectangle (DestinationX, DestinationY)
513 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
514 not zero then Delta must be set to the length in bytes of a row in the
516 EfiBltVideoToVideo - Copy from the video display rectangle
517 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
518 to the video display rectangle (DestinationX, DestinationY)
519 (DestinationX + Width, DestinationY + Height).
520 The BltBuffer and Delta are not used in this mode.
523 This - Protocol instance pointer.
524 BltBuffer - Buffer containing data to blit into video buffer. This
525 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
526 BltOperation - Operation to perform on BlitBuffer and video memory
527 SourceX - X coordinate of source for the BltBuffer.
528 SourceY - Y coordinate of source for the BltBuffer.
529 DestinationX - X coordinate of destination for the BltBuffer.
530 DestinationY - Y coordinate of destination for the BltBuffer.
531 Width - Width of rectangle in BltBuffer in pixels.
532 Height - Hight of rectangle in BltBuffer in pixels.
536 EFI_SUCCESS - The Blt operation completed.
537 EFI_INVALID_PARAMETER - BltOperation is not valid.
538 EFI_DEVICE_ERROR - A hardware error occured writting to the video
544 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
546 EFI_STATUS ReturnStatus
;
547 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
548 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
550 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
553 // Sync up DevNull GOP device
555 ReturnStatus
= DevNullGraphicsOutputBlt (
568 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
572 // return the worst status met
574 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
575 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
576 if (GraphicsOutput
!= NULL
) {
577 Status
= GraphicsOutput
->Blt (
589 if (EFI_ERROR (Status
)) {
590 ReturnStatus
= Status
;
591 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
593 // Only need to read the data into buffer one time
599 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
600 if (UgaDraw
!= NULL
) {
601 Status
= UgaDraw
->Blt (
603 (EFI_UGA_PIXEL
*) BltBuffer
,
604 (EFI_UGA_BLT_OPERATION
) BltOperation
,
613 if (EFI_ERROR (Status
)) {
614 ReturnStatus
= Status
;
615 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
617 // Only need to read the data into buffer one time
629 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
630 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
631 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
634 if (GraphicsOutput
!= NULL
) {
635 return GraphicsOutput
->Blt (
637 Private
->GraphicsOutputBlt
,
643 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
644 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
648 return UgaDraw
->Blt (
650 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
651 EfiUgaBltBufferToVideo
,
656 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
657 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
665 DevNullTextOutOutputString (
666 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
672 Write a Unicode string to the output device.
675 Private - Pointer to the console output splitter's private data. It
676 indicates the calling context.
677 WString - The NULL-terminated Unicode string to be displayed on the output
678 device(s). All output devices must also support the Unicode
679 drawing defined in this file.
682 EFI_SUCCESS - The string was output to the device.
683 EFI_DEVICE_ERROR - The device reported an error while attempting to
685 EFI_UNSUPPORTED - The output device's mode is not currently in a
687 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
688 characters in the Unicode string could not be
689 rendered and were skipped.
696 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
703 INT32
*NullAttributes
;
708 Mode
= &Private
->TextOutMode
;
709 NullScreen
= Private
->DevNullScreen
;
710 NullAttributes
= Private
->DevNullAttributes
;
711 LastRow
= Private
->DevNullRows
- 1;
712 MaxColumn
= Private
->DevNullColumns
;
714 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
722 if (*WString
== CHAR_BACKSPACE
) {
724 // If the cursor is at the left edge of the display, then move the cursor
727 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
729 Mode
->CursorColumn
= (INT32
) MaxColumn
;
733 // If the cursor is not at the left edge of the display,
734 // then move the cursor left one column.
736 if (Mode
->CursorColumn
> 0) {
737 Mode
->CursorColumn
--;
738 if (Mode
->CursorColumn
> 0 &&
739 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
741 Mode
->CursorColumn
--;
744 // Insert an extra backspace
746 InsertChar
= CHAR_BACKSPACE
;
751 InsertChar
= TempChar
;
764 } else if (*WString
== CHAR_LINEFEED
) {
766 // If the cursor is at the bottom of the display,
767 // then scroll the display one row, and do not update
768 // the cursor position. Otherwise, move the cursor down one row.
770 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
772 // Scroll Screen Up One Row
774 SizeAttribute
= LastRow
* MaxColumn
;
777 NullAttributes
+ MaxColumn
,
778 SizeAttribute
* sizeof (INT32
)
782 // Each row has an ending CHAR_NULL. So one more character each line
783 // for DevNullScreen than DevNullAttributes
785 SizeScreen
= SizeAttribute
+ LastRow
;
788 NullScreen
+ (MaxColumn
+ 1),
789 SizeScreen
* sizeof (CHAR16
)
793 // Print Blank Line at last line
795 Screen
= NullScreen
+ SizeScreen
;
796 Attribute
= NullAttributes
+ SizeAttribute
;
798 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
800 *Attribute
= Mode
->Attribute
;
807 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
809 // Move the cursor to the beginning of the current row.
811 Mode
->CursorColumn
= 0;
815 // Print the character at the current cursor position and
816 // move the cursor right one column. If this moves the cursor
817 // past the right edge of the display, then the line should wrap to
818 // the beginning of the next line. This is equivalent to inserting
819 // a CR and an LF. Note that if the cursor is at the bottom of the
820 // display, and the line wraps, then the display will be scrolled
823 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
825 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
826 if (*WString
== CHAR_NULL
) {
830 if (*WString
== CHAR_BACKSPACE
) {
834 if (*WString
== CHAR_LINEFEED
) {
838 if (*WString
== CHAR_CARRIAGE_RETURN
) {
842 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
843 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
848 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
850 // If a wide char is at the rightmost column, then move the char
851 // to the beginning of the next row
853 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
854 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
856 Mode
->CursorColumn
++;
858 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
859 NullAttributes
[Index
] = Mode
->Attribute
;
860 if (CurrentWidth
== 1) {
861 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
863 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
864 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
867 Index
+= CurrentWidth
;
869 Mode
->CursorColumn
+= CurrentWidth
;
873 // At the end of line, output carriage return and line feed
875 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
876 DevNullTextOutOutputString (Private
, mCrLfString
);
885 DevNullTextOutSetMode (
886 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
892 Sets the output device(s) to a specified mode.
895 Private - Private data structure pointer.
896 ModeNumber - The mode number to set.
899 EFI_SUCCESS - The requested text mode was set.
900 EFI_DEVICE_ERROR - The device had an error and
901 could not complete the request.
902 EFI_UNSUPPORTED - The mode number was not valid.
903 EFI_OUT_OF_RESOURCES - Out of resources.
910 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
913 // No extra check for ModeNumber here, as it has been checked in
914 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
916 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
918 Column
= Mode
->Columns
;
920 if (Row
<= 0 && Column
<= 0) {
921 return EFI_UNSUPPORTED
;
924 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
926 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
927 Private
->DevNullColumns
= Column
;
928 Private
->DevNullRows
= Row
;
930 if (Private
->DevNullScreen
!= NULL
) {
931 FreePool (Private
->DevNullScreen
);
934 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
935 Private
->DevNullScreen
= AllocateZeroPool (Size
);
936 if (Private
->DevNullScreen
== NULL
) {
937 return EFI_OUT_OF_RESOURCES
;
940 if (Private
->DevNullAttributes
!= NULL
) {
941 FreePool (Private
->DevNullAttributes
);
944 Size
= Row
* Column
* sizeof (INT32
);
945 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
946 if (Private
->DevNullAttributes
== NULL
) {
947 return EFI_OUT_OF_RESOURCES
;
951 DevNullTextOutClearScreen (Private
);
957 DevNullTextOutClearScreen (
958 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
963 Clears the output device(s) display to the currently selected background
967 Private - Protocol instance pointer.
970 EFI_SUCCESS - The operation completed successfully.
971 EFI_DEVICE_ERROR - The device had an error and
972 could not complete the request.
973 EFI_UNSUPPORTED - The output device is not in a valid text mode.
981 INT32 CurrentAttribute
;
984 // Clear the DevNull Text Out Buffers.
985 // The screen is filled with spaces.
986 // The attributes are all synced with the current Simple Text Out Attribute
988 Screen
= Private
->DevNullScreen
;
989 Attributes
= Private
->DevNullAttributes
;
990 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
992 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
993 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
995 *Attributes
= CurrentAttribute
;
998 // Each line of the screen has a NULL on the end so we must skip over it
1003 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1005 return DevNullTextOutEnableCursor (Private
, TRUE
);
1009 DevNullTextOutSetCursorPosition (
1010 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1016 Routine Description:
1017 Sets the current coordinates of the cursor position
1020 Private - Protocol instance pointer.
1021 Column, Row - the position to set the cursor to. Must be greater than or
1022 equal to zero and less than the number of columns and rows
1026 EFI_SUCCESS - The operation completed successfully.
1027 EFI_DEVICE_ERROR - The device had an error and
1028 could not complete the request.
1029 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1030 cursor position is invalid for the current mode.
1035 // No need to do extra check here as whether (Column, Row) is valid has
1036 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1037 // always be supported.
1039 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1040 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1046 DevNullTextOutEnableCursor (
1047 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1051 Routine Description:
1053 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1054 In this driver, the cursor cannot be hidden.
1058 Private - Indicates the calling context.
1060 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1061 is set to be invisible.
1065 EFI_SUCCESS - The request is valid.
1070 Private
->TextOutMode
.CursorVisible
= Visible
;
1076 DevNullSyncGopStdOut (
1077 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1080 Routine Description:
1081 Take the DevNull TextOut device and update the Simple Text Out on every
1085 Private - Indicates the calling context.
1088 EFI_SUCCESS - The request is valid.
1089 other - Return status of TextOut->OutputString ()
1094 EFI_STATUS ReturnStatus
;
1099 UINTN CurrentColumn
;
1102 INT32 StartAttribute
;
1103 BOOLEAN StartCursorState
;
1108 CHAR16
*ScreenStart
;
1109 INT32 CurrentAttribute
;
1111 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1114 // Save the devices Attributes, Cursor enable state and location
1116 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1117 StartRow
= Private
->TextOutMode
.CursorRow
;
1118 StartAttribute
= Private
->TextOutMode
.Attribute
;
1119 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1121 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1123 Sto
= Private
->TextOutList
[List
].TextOut
;
1126 // Skip non GOP/UGA devices
1128 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1129 Sto
->EnableCursor (Sto
, FALSE
);
1130 Sto
->ClearScreen (Sto
);
1134 ReturnStatus
= EFI_SUCCESS
;
1135 Screen
= Private
->DevNullScreen
;
1136 Attributes
= Private
->DevNullAttributes
;
1137 MaxColumn
= Private
->DevNullColumns
;
1139 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1141 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1143 if (Row
== (Private
->DevNullRows
- 1)) {
1145 // Don't ever sync the last character as it will scroll the screen
1147 Screen
[MaxColumn
- 1] = 0x00;
1151 while (Column
< MaxColumn
) {
1152 if (Screen
[Column
]) {
1153 CurrentAttribute
= Attributes
[Column
];
1154 CurrentColumn
= Column
;
1155 ScreenStart
= &Screen
[Column
];
1158 // the line end is alway 0x0. So Column should be less than MaxColumn
1159 // It should be still in the same row
1161 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1163 if (Attributes
[Column
] != CurrentAttribute
) {
1170 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1178 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1180 Sto
= Private
->TextOutList
[List
].TextOut
;
1183 // Skip non GOP/UGA devices
1185 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1186 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1187 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1188 Status
= Sto
->OutputString (Sto
, Buffer
);
1189 if (EFI_ERROR (Status
)) {
1190 ReturnStatus
= Status
;
1201 // Restore the devices Attributes, Cursor enable state and location
1203 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1204 Sto
= Private
->TextOutList
[List
].TextOut
;
1207 // Skip non GOP/UGA devices
1209 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1210 Sto
->SetAttribute (Sto
, StartAttribute
);
1211 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1212 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1213 if (EFI_ERROR (Status
)) {
1214 ReturnStatus
= Status
;
1221 return ReturnStatus
;