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
25 #include "ConSplitter.h"
28 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
32 ConSpliterConsoleControlGetMode (
33 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
34 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE
*Mode
,
35 OUT BOOLEAN
*GopExists
,
36 OUT BOOLEAN
*StdInLocked
41 Return the current video mode information. Also returns info about existence
42 of UGA Draw devices in system, and if the Std In device is locked. All the
43 arguments are optional and only returned if a non NULL pointer is passed in.
46 This - Protocol instance pointer.
47 Mode - Are we in text of grahics mode.
48 UgaExists - TRUE if UGA Spliter has found a UGA device
49 StdInLocked - TRUE if StdIn device is keyboard locked
52 EFI_SUCCESS - Mode information returned.
53 EFI_INVALID_PARAMETER - Invalid parameters.
57 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
60 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
63 return EFI_INVALID_PARAMETER
;
66 *Mode
= Private
->ConsoleOutputMode
;
68 if (GopExists
!= NULL
) {
70 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
71 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
78 if (StdInLocked
!= NULL
) {
79 *StdInLocked
= ConSpliterConssoleControlStdInLocked ();
87 ConSpliterConsoleControlSetMode (
88 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
89 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
94 Set the current mode to either text or graphics. Graphics is
98 This - Protocol instance pointer.
99 Mode - Mode to set the
102 EFI_SUCCESS - Mode information returned.
103 EFI_INVALID_PARAMETER - Invalid parameter.
104 EFI_UNSUPPORTED - Operation unsupported.
108 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
110 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
113 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
115 if (Mode
>= EfiConsoleControlScreenMaxValue
) {
116 return EFI_INVALID_PARAMETER
;
120 // Judge current mode with wanted mode at first.
122 if (Private
->ConsoleOutputMode
== Mode
) {
127 TextAndGop
= &Private
->TextOutList
[0];
128 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
129 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
135 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
136 return EFI_UNSUPPORTED
;
139 Private
->ConsoleOutputMode
= Mode
;
141 TextAndGop
= &Private
->TextOutList
[0];
142 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
144 TextAndGop
->TextOutEnabled
= TRUE
;
146 // If we are going into Graphics mode disable ConOut to any UGA device
148 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
149 TextAndGop
->TextOutEnabled
= FALSE
;
150 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
154 if (Mode
== EfiConsoleControlScreenText
) {
155 DevNullSyncGopStdOut (Private
);
163 ConSpliterGraphicsOutputQueryMode (
164 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
165 IN UINT32 ModeNumber
,
166 OUT UINTN
*SizeOfInfo
,
167 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
172 Return the current video mode information.
175 This - Protocol instance pointer.
176 ModeNumber - The mode number to return information on.
177 Info - Caller allocated buffer that returns information about ModeNumber.
178 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
181 EFI_SUCCESS - Mode information returned.
182 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
183 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
184 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
185 EFI_INVALID_PARAMETER - One of the input args was NULL.
189 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
190 TEXT_OUT_GOP_MODE
*Mode
;
192 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
193 return EFI_INVALID_PARAMETER
;
197 // retrieve private data
199 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
201 if (Private
->HardwareNeedsStarting
) {
202 return EFI_NOT_STARTED
;
205 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
208 return EFI_OUT_OF_RESOURCES
;
211 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
213 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
214 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
215 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
216 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
217 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
224 ConSpliterGraphicsOutputSetMode (
225 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
232 Graphics output protocol interface to set video mode
235 This - Protocol instance pointer.
236 ModeNumber - The mode number to be set.
239 EFI_SUCCESS - Graphics mode was changed.
240 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
241 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
246 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
248 EFI_STATUS ReturnStatus
;
249 TEXT_OUT_GOP_MODE
*Mode
;
251 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
254 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
255 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
257 if (ModeNumber
>= This
->Mode
->MaxMode
) {
258 return EFI_UNSUPPORTED
;
261 if (ModeNumber
== This
->Mode
->Mode
) {
265 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
268 // GopDevNullSetMode ()
270 ReturnStatus
= EFI_SUCCESS
;
273 // Free the old version
275 if (Private
->GraphicsOutputBlt
!= NULL
) {
276 FreePool (Private
->GraphicsOutputBlt
);
280 // Allocate the virtual Blt buffer
282 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
283 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
284 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
286 if (Private
->GraphicsOutputBlt
== NULL
) {
287 return EFI_OUT_OF_RESOURCES
;
290 if (!Private
->HardwareNeedsStarting
) {
291 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
292 return EFI_UNSUPPORTED
;
296 // return the worst status met
298 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
299 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
300 if (GraphicsOutput
!= NULL
) {
302 // Find corresponding ModeNumber of this GraphicsOutput instance
304 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
305 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
306 if (EFI_ERROR (Status
)) {
309 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
316 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
317 if (EFI_ERROR (Status
)) {
318 ReturnStatus
= Status
;
322 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
323 if (UgaDraw
!= NULL
) {
324 Status
= UgaDraw
->SetMode (
326 Mode
->HorizontalResolution
,
327 Mode
->VerticalResolution
,
331 if (EFI_ERROR (Status
)) {
332 ReturnStatus
= Status
;
337 This
->Mode
->Mode
= ModeNumber
;
339 Info
= This
->Mode
->Info
;
340 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
341 Info
->VerticalResolution
= Mode
->VerticalResolution
;
342 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
345 // Information is not enough here, so the following items remain unchanged:
346 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
347 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
348 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
351 Private
->HardwareNeedsStarting
= FALSE
;
358 DevNullGraphicsOutputBlt (
359 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
360 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
361 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
364 IN UINTN DestinationX
,
365 IN UINTN DestinationY
,
368 IN UINTN Delta OPTIONAL
374 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
375 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
376 UINTN HorizontalResolution
;
377 UINTN VerticalResolution
;
379 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
380 return EFI_INVALID_PARAMETER
;
383 if (Width
== 0 || Height
== 0) {
384 return EFI_INVALID_PARAMETER
;
388 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
391 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
392 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
395 // We need to fill the Virtual Screen buffer with the blt data.
397 if (BltOperation
== EfiBltVideoToBltBuffer
) {
399 // Video to BltBuffer: Source is Video, destination is BltBuffer
401 if ((SourceY
+ Height
) > VerticalResolution
) {
402 return EFI_INVALID_PARAMETER
;
405 if ((SourceX
+ Width
) > HorizontalResolution
) {
406 return EFI_INVALID_PARAMETER
;
409 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
410 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
412 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
413 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
414 ScreenPtr
+= HorizontalResolution
;
419 // BltBuffer to Video: Source is BltBuffer, destination is Video
421 if (DestinationY
+ Height
> VerticalResolution
) {
422 return EFI_INVALID_PARAMETER
;
425 if (DestinationX
+ Width
> HorizontalResolution
) {
426 return EFI_INVALID_PARAMETER
;
429 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
431 // Copy backwards, only care the Video to Video Blt
433 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
434 SrcY
= SourceY
+ Height
- 1;
438 // Copy forwards, for other cases
440 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
445 while (Height
!= 0) {
446 if (BltOperation
== EfiBltVideoFill
) {
447 for (Index
= 0; Index
< Width
; Index
++) {
448 ScreenPtr
[Index
] = *BltBuffer
;
451 if (BltOperation
== EfiBltBufferToVideo
) {
452 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
454 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
457 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
461 ScreenPtr
+= HorizontalResolution
;
464 ScreenPtr
-= HorizontalResolution
;
476 ConSpliterGraphicsOutputBlt (
477 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
478 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
479 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
482 IN UINTN DestinationX
,
483 IN UINTN DestinationY
,
486 IN UINTN Delta OPTIONAL
491 The following table defines actions for BltOperations:
492 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
493 directly to every pixel of the video display rectangle
494 (DestinationX, DestinationY)
495 (DestinationX + Width, DestinationY + Height).
496 Only one pixel will be used from the BltBuffer. Delta is NOT used.
497 EfiBltVideoToBltBuffer - Read data from the video display rectangle
498 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
499 the BltBuffer rectangle (DestinationX, DestinationY )
500 (DestinationX + Width, DestinationY + Height). If DestinationX or
501 DestinationY is not zero then Delta must be set to the length in bytes
502 of a row in the BltBuffer.
503 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
504 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
505 video display rectangle (DestinationX, DestinationY)
506 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
507 not zero then Delta must be set to the length in bytes of a row in the
509 EfiBltVideoToVideo - Copy from the video display rectangle
510 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
511 to the video display rectangle (DestinationX, DestinationY)
512 (DestinationX + Width, DestinationY + Height).
513 The BltBuffer and Delta are not used in this mode.
516 This - Protocol instance pointer.
517 BltBuffer - Buffer containing data to blit into video buffer. This
518 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
519 BltOperation - Operation to perform on BlitBuffer and video memory
520 SourceX - X coordinate of source for the BltBuffer.
521 SourceY - Y coordinate of source for the BltBuffer.
522 DestinationX - X coordinate of destination for the BltBuffer.
523 DestinationY - Y coordinate of destination for the BltBuffer.
524 Width - Width of rectangle in BltBuffer in pixels.
525 Height - Hight of rectangle in BltBuffer in pixels.
529 EFI_SUCCESS - The Blt operation completed.
530 EFI_INVALID_PARAMETER - BltOperation is not valid.
531 EFI_DEVICE_ERROR - A hardware error occured writting to the video
537 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
539 EFI_STATUS ReturnStatus
;
540 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
541 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
543 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
546 // Sync up DevNull GOP device
548 ReturnStatus
= DevNullGraphicsOutputBlt (
561 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
565 // return the worst status met
567 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
568 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
569 if (GraphicsOutput
!= NULL
) {
570 Status
= GraphicsOutput
->Blt (
582 if (EFI_ERROR (Status
)) {
583 ReturnStatus
= Status
;
584 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
586 // Only need to read the data into buffer one time
592 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
593 if (UgaDraw
!= NULL
) {
594 Status
= UgaDraw
->Blt (
596 (EFI_UGA_PIXEL
*) BltBuffer
,
597 (EFI_UGA_BLT_OPERATION
) BltOperation
,
606 if (EFI_ERROR (Status
)) {
607 ReturnStatus
= Status
;
608 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
610 // Only need to read the data into buffer one time
622 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
623 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
624 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
627 if (GraphicsOutput
!= NULL
) {
628 return GraphicsOutput
->Blt (
630 Private
->GraphicsOutputBlt
,
636 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
637 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
641 return UgaDraw
->Blt (
643 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
644 EfiUgaBltBufferToVideo
,
649 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
650 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
658 DevNullTextOutOutputString (
659 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
665 Write a Unicode string to the output device.
668 Private - Pointer to the console output splitter's private data. It
669 indicates the calling context.
670 WString - The NULL-terminated Unicode string to be displayed on the output
671 device(s). All output devices must also support the Unicode
672 drawing defined in this file.
675 EFI_SUCCESS - The string was output to the device.
676 EFI_DEVICE_ERROR - The device reported an error while attempting to
678 EFI_UNSUPPORTED - The output device's mode is not currently in a
680 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
681 characters in the Unicode string could not be
682 rendered and were skipped.
689 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
696 INT32
*NullAttributes
;
701 Mode
= &Private
->TextOutMode
;
702 NullScreen
= Private
->DevNullScreen
;
703 NullAttributes
= Private
->DevNullAttributes
;
704 LastRow
= Private
->DevNullRows
- 1;
705 MaxColumn
= Private
->DevNullColumns
;
707 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
715 if (*WString
== CHAR_BACKSPACE
) {
717 // If the cursor is at the left edge of the display, then move the cursor
720 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
722 Mode
->CursorColumn
= (INT32
) MaxColumn
;
726 // If the cursor is not at the left edge of the display,
727 // then move the cursor left one column.
729 if (Mode
->CursorColumn
> 0) {
730 Mode
->CursorColumn
--;
731 if (Mode
->CursorColumn
> 0 &&
732 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
734 Mode
->CursorColumn
--;
737 // Insert an extra backspace
739 InsertChar
= CHAR_BACKSPACE
;
744 InsertChar
= TempChar
;
757 } else if (*WString
== CHAR_LINEFEED
) {
759 // If the cursor is at the bottom of the display,
760 // then scroll the display one row, and do not update
761 // the cursor position. Otherwise, move the cursor down one row.
763 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
765 // Scroll Screen Up One Row
767 SizeAttribute
= LastRow
* MaxColumn
;
770 NullAttributes
+ MaxColumn
,
771 SizeAttribute
* sizeof (INT32
)
775 // Each row has an ending CHAR_NULL. So one more character each line
776 // for DevNullScreen than DevNullAttributes
778 SizeScreen
= SizeAttribute
+ LastRow
;
781 NullScreen
+ (MaxColumn
+ 1),
782 SizeScreen
* sizeof (CHAR16
)
786 // Print Blank Line at last line
788 Screen
= NullScreen
+ SizeScreen
;
789 Attribute
= NullAttributes
+ SizeAttribute
;
791 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
793 *Attribute
= Mode
->Attribute
;
800 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
802 // Move the cursor to the beginning of the current row.
804 Mode
->CursorColumn
= 0;
808 // Print the character at the current cursor position and
809 // move the cursor right one column. If this moves the cursor
810 // past the right edge of the display, then the line should wrap to
811 // the beginning of the next line. This is equivalent to inserting
812 // a CR and an LF. Note that if the cursor is at the bottom of the
813 // display, and the line wraps, then the display will be scrolled
816 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
818 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
819 if (*WString
== CHAR_NULL
) {
823 if (*WString
== CHAR_BACKSPACE
) {
827 if (*WString
== CHAR_LINEFEED
) {
831 if (*WString
== CHAR_CARRIAGE_RETURN
) {
835 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
836 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
841 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
843 // If a wide char is at the rightmost column, then move the char
844 // to the beginning of the next row
846 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
847 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
849 Mode
->CursorColumn
++;
851 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
852 NullAttributes
[Index
] = Mode
->Attribute
;
853 if (CurrentWidth
== 1) {
854 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
856 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
857 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
860 Index
+= CurrentWidth
;
862 Mode
->CursorColumn
+= CurrentWidth
;
866 // At the end of line, output carriage return and line feed
868 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
869 DevNullTextOutOutputString (Private
, mCrLfString
);
878 DevNullTextOutSetMode (
879 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
885 Sets the output device(s) to a specified mode.
888 Private - Private data structure pointer.
889 ModeNumber - The mode number to set.
892 EFI_SUCCESS - The requested text mode was set.
893 EFI_DEVICE_ERROR - The device had an error and
894 could not complete the request.
895 EFI_UNSUPPORTED - The mode number was not valid.
896 EFI_OUT_OF_RESOURCES - Out of resources.
903 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
906 // No extra check for ModeNumber here, as it has been checked in
907 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
909 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
911 Column
= Mode
->Columns
;
913 if (Row
<= 0 && Column
<= 0) {
914 return EFI_UNSUPPORTED
;
917 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
919 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
920 Private
->DevNullColumns
= Column
;
921 Private
->DevNullRows
= Row
;
923 if (Private
->DevNullScreen
!= NULL
) {
924 FreePool (Private
->DevNullScreen
);
927 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
928 Private
->DevNullScreen
= AllocateZeroPool (Size
);
929 if (Private
->DevNullScreen
== NULL
) {
930 return EFI_OUT_OF_RESOURCES
;
933 if (Private
->DevNullAttributes
!= NULL
) {
934 FreePool (Private
->DevNullAttributes
);
937 Size
= Row
* Column
* sizeof (INT32
);
938 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
939 if (Private
->DevNullAttributes
== NULL
) {
940 return EFI_OUT_OF_RESOURCES
;
944 DevNullTextOutClearScreen (Private
);
950 DevNullTextOutClearScreen (
951 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
956 Clears the output device(s) display to the currently selected background
960 Private - Protocol instance pointer.
963 EFI_SUCCESS - The operation completed successfully.
964 EFI_DEVICE_ERROR - The device had an error and
965 could not complete the request.
966 EFI_UNSUPPORTED - The output device is not in a valid text mode.
974 INT32 CurrentAttribute
;
977 // Clear the DevNull Text Out Buffers.
978 // The screen is filled with spaces.
979 // The attributes are all synced with the current Simple Text Out Attribute
981 Screen
= Private
->DevNullScreen
;
982 Attributes
= Private
->DevNullAttributes
;
983 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
985 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
986 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
988 *Attributes
= CurrentAttribute
;
991 // Each line of the screen has a NULL on the end so we must skip over it
996 DevNullTextOutSetCursorPosition (Private
, 0, 0);
998 return DevNullTextOutEnableCursor (Private
, TRUE
);
1002 DevNullTextOutSetCursorPosition (
1003 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1009 Routine Description:
1010 Sets the current coordinates of the cursor position
1013 Private - Protocol instance pointer.
1014 Column, Row - the position to set the cursor to. Must be greater than or
1015 equal to zero and less than the number of columns and rows
1019 EFI_SUCCESS - The operation completed successfully.
1020 EFI_DEVICE_ERROR - The device had an error and
1021 could not complete the request.
1022 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1023 cursor position is invalid for the current mode.
1028 // No need to do extra check here as whether (Column, Row) is valid has
1029 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1030 // always be supported.
1032 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1033 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1039 DevNullTextOutEnableCursor (
1040 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1044 Routine Description:
1046 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1047 In this driver, the cursor cannot be hidden.
1051 Private - Indicates the calling context.
1053 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1054 is set to be invisible.
1058 EFI_SUCCESS - The request is valid.
1063 Private
->TextOutMode
.CursorVisible
= Visible
;
1069 DevNullSyncGopStdOut (
1070 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1073 Routine Description:
1074 Take the DevNull TextOut device and update the Simple Text Out on every
1078 Private - Indicates the calling context.
1081 EFI_SUCCESS - The request is valid.
1082 other - Return status of TextOut->OutputString ()
1087 EFI_STATUS ReturnStatus
;
1092 UINTN CurrentColumn
;
1095 INT32 StartAttribute
;
1096 BOOLEAN StartCursorState
;
1101 CHAR16
*ScreenStart
;
1102 INT32 CurrentAttribute
;
1104 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1107 // Save the devices Attributes, Cursor enable state and location
1109 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1110 StartRow
= Private
->TextOutMode
.CursorRow
;
1111 StartAttribute
= Private
->TextOutMode
.Attribute
;
1112 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1114 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1116 Sto
= Private
->TextOutList
[List
].TextOut
;
1119 // Skip non GOP/UGA devices
1121 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1122 Sto
->EnableCursor (Sto
, FALSE
);
1123 Sto
->ClearScreen (Sto
);
1127 ReturnStatus
= EFI_SUCCESS
;
1128 Screen
= Private
->DevNullScreen
;
1129 Attributes
= Private
->DevNullAttributes
;
1130 MaxColumn
= Private
->DevNullColumns
;
1132 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1134 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1136 if (Row
== (Private
->DevNullRows
- 1)) {
1138 // Don't ever sync the last character as it will scroll the screen
1140 Screen
[MaxColumn
- 1] = 0x00;
1144 while (Column
< MaxColumn
) {
1145 if (Screen
[Column
]) {
1146 CurrentAttribute
= Attributes
[Column
];
1147 CurrentColumn
= Column
;
1148 ScreenStart
= &Screen
[Column
];
1151 // the line end is alway 0x0. So Column should be less than MaxColumn
1152 // It should be still in the same row
1154 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1156 if (Attributes
[Column
] != CurrentAttribute
) {
1163 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1171 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1173 Sto
= Private
->TextOutList
[List
].TextOut
;
1176 // Skip non GOP/UGA devices
1178 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1179 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1180 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1181 Status
= Sto
->OutputString (Sto
, Buffer
);
1182 if (EFI_ERROR (Status
)) {
1183 ReturnStatus
= Status
;
1194 // Restore the devices Attributes, Cursor enable state and location
1196 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1197 Sto
= Private
->TextOutList
[List
].TextOut
;
1200 // Skip non GOP/UGA devices
1202 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1203 Sto
->SetAttribute (Sto
, StartAttribute
);
1204 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1205 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1206 if (EFI_ERROR (Status
)) {
1207 ReturnStatus
= Status
;
1214 return ReturnStatus
;