3 Copyright (c) 2006 - 2008, 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 Graphics output 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 Graphics Output devices or 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 GopExists - TRUE if GOP Spliter has found a GOP/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 if (FeaturePcdGet (PcdConOutGopSupport
)) {
151 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
152 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
153 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
157 if (Mode
== EfiConsoleControlScreenText
) {
158 DevNullSyncStdOut (Private
);
165 ConSpliterGraphicsOutputQueryMode (
166 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
167 IN UINT32 ModeNumber
,
168 OUT UINTN
*SizeOfInfo
,
169 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
174 Return the current video mode information.
177 This - Protocol instance pointer.
178 ModeNumber - The mode number to return information on.
179 Info - Caller allocated buffer that returns information about ModeNumber.
180 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
183 EFI_SUCCESS - Mode information returned.
184 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
185 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
186 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
187 EFI_INVALID_PARAMETER - One of the input args was NULL.
191 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
193 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
194 return EFI_INVALID_PARAMETER
;
198 // retrieve private data
200 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
202 if (Private
->HardwareNeedsStarting
) {
203 return EFI_NOT_STARTED
;
206 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
209 return EFI_OUT_OF_RESOURCES
;
212 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
214 CopyMem (*Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], *SizeOfInfo
);
221 ConSpliterGraphicsOutputSetMode (
222 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
229 Graphics output protocol interface to set video mode
232 This - Protocol instance pointer.
233 ModeNumber - The mode number to be set.
236 EFI_SUCCESS - Graphics mode was changed.
237 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
238 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
243 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
245 EFI_STATUS ReturnStatus
;
246 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
248 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
251 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
252 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
254 if (ModeNumber
>= This
->Mode
->MaxMode
) {
255 return EFI_UNSUPPORTED
;
258 if (ModeNumber
== This
->Mode
->Mode
) {
262 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
265 // GopDevNullSetMode ()
267 ReturnStatus
= EFI_SUCCESS
;
270 // Free the old version
272 if (Private
->GraphicsOutputBlt
!= NULL
) {
273 FreePool (Private
->GraphicsOutputBlt
);
277 // Allocate the virtual Blt buffer
279 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
280 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
281 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
283 if (Private
->GraphicsOutputBlt
== NULL
) {
284 return EFI_OUT_OF_RESOURCES
;
288 // return the worst status met
290 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
291 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
292 if (GraphicsOutput
!= NULL
) {
294 // Find corresponding ModeNumber of this GraphicsOutput instance
296 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
297 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
298 if (EFI_ERROR (Status
)) {
301 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
308 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
309 if (EFI_ERROR (Status
)) {
310 ReturnStatus
= Status
;
314 if (EFI_ERROR (ReturnStatus
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
315 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
316 if (UgaDraw
!= NULL
) {
317 Status
= UgaDraw
->SetMode (
319 Mode
->HorizontalResolution
,
320 Mode
->VerticalResolution
,
324 if (EFI_ERROR (Status
)) {
325 ReturnStatus
= Status
;
331 This
->Mode
->Mode
= ModeNumber
;
333 CopyMem (This
->Mode
->Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], This
->Mode
->SizeOfInfo
);
336 // Information is not enough here, so the following items remain unchanged:
337 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
338 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
339 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
342 Private
->HardwareNeedsStarting
= FALSE
;
349 DevNullGraphicsOutputBlt (
350 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
351 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
352 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
355 IN UINTN DestinationX
,
356 IN UINTN DestinationY
,
359 IN UINTN Delta OPTIONAL
365 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
366 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
367 UINTN HorizontalResolution
;
368 UINTN VerticalResolution
;
370 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
371 return EFI_INVALID_PARAMETER
;
374 if (Width
== 0 || Height
== 0) {
375 return EFI_INVALID_PARAMETER
;
379 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
382 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
383 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
386 // We need to fill the Virtual Screen buffer with the blt data.
388 if (BltOperation
== EfiBltVideoToBltBuffer
) {
390 // Video to BltBuffer: Source is Video, destination is BltBuffer
392 if ((SourceY
+ Height
) > VerticalResolution
) {
393 return EFI_INVALID_PARAMETER
;
396 if ((SourceX
+ Width
) > HorizontalResolution
) {
397 return EFI_INVALID_PARAMETER
;
400 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
401 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
403 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
404 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
405 ScreenPtr
+= HorizontalResolution
;
410 // BltBuffer to Video: Source is BltBuffer, destination is Video
412 if (DestinationY
+ Height
> VerticalResolution
) {
413 return EFI_INVALID_PARAMETER
;
416 if (DestinationX
+ Width
> HorizontalResolution
) {
417 return EFI_INVALID_PARAMETER
;
420 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
422 // Copy backwards, only care the Video to Video Blt
424 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
425 SrcY
= SourceY
+ Height
- 1;
429 // Copy forwards, for other cases
431 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
436 while (Height
!= 0) {
437 if (BltOperation
== EfiBltVideoFill
) {
438 for (Index
= 0; Index
< Width
; Index
++) {
439 ScreenPtr
[Index
] = *BltBuffer
;
442 if (BltOperation
== EfiBltBufferToVideo
) {
443 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
445 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
448 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
452 ScreenPtr
+= HorizontalResolution
;
455 ScreenPtr
-= HorizontalResolution
;
467 ConSpliterGraphicsOutputBlt (
468 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
469 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
470 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
473 IN UINTN DestinationX
,
474 IN UINTN DestinationY
,
477 IN UINTN Delta OPTIONAL
482 The following table defines actions for BltOperations:
483 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
484 directly to every pixel of the video display rectangle
485 (DestinationX, DestinationY)
486 (DestinationX + Width, DestinationY + Height).
487 Only one pixel will be used from the BltBuffer. Delta is NOT used.
488 EfiBltVideoToBltBuffer - Read data from the video display rectangle
489 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
490 the BltBuffer rectangle (DestinationX, DestinationY )
491 (DestinationX + Width, DestinationY + Height). If DestinationX or
492 DestinationY is not zero then Delta must be set to the length in bytes
493 of a row in the BltBuffer.
494 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
495 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
496 video display rectangle (DestinationX, DestinationY)
497 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
498 not zero then Delta must be set to the length in bytes of a row in the
500 EfiBltVideoToVideo - Copy from the video display rectangle
501 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
502 to the video display rectangle (DestinationX, DestinationY)
503 (DestinationX + Width, DestinationY + Height).
504 The BltBuffer and Delta are not used in this mode.
507 This - Protocol instance pointer.
508 BltBuffer - Buffer containing data to blit into video buffer. This
509 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
510 BltOperation - Operation to perform on BlitBuffer and video memory
511 SourceX - X coordinate of source for the BltBuffer.
512 SourceY - Y coordinate of source for the BltBuffer.
513 DestinationX - X coordinate of destination for the BltBuffer.
514 DestinationY - Y coordinate of destination for the BltBuffer.
515 Width - Width of rectangle in BltBuffer in pixels.
516 Height - Hight of rectangle in BltBuffer in pixels.
520 EFI_SUCCESS - The Blt operation completed.
521 EFI_INVALID_PARAMETER - BltOperation is not valid.
522 EFI_DEVICE_ERROR - A hardware error occured writting to the video
528 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
530 EFI_STATUS ReturnStatus
;
531 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
532 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
534 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
537 // Sync up DevNull GOP device
539 ReturnStatus
= DevNullGraphicsOutputBlt (
552 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
556 // return the worst status met
558 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
559 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
560 if (GraphicsOutput
!= NULL
) {
561 Status
= GraphicsOutput
->Blt (
573 if (EFI_ERROR (Status
)) {
574 ReturnStatus
= Status
;
575 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
577 // Only need to read the data into buffer one time
583 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
584 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
585 Status
= UgaDraw
->Blt (
587 (EFI_UGA_PIXEL
*) BltBuffer
,
588 (EFI_UGA_BLT_OPERATION
) BltOperation
,
597 if (EFI_ERROR (Status
)) {
598 ReturnStatus
= Status
;
599 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
601 // Only need to read the data into buffer one time
613 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
614 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
615 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
618 if (GraphicsOutput
!= NULL
) {
619 return GraphicsOutput
->Blt (
621 Private
->GraphicsOutputBlt
,
627 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
628 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
631 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
632 return UgaDraw
->Blt (
634 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
635 EfiUgaBltBufferToVideo
,
640 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
641 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
645 return EFI_UNSUPPORTED
;
651 ConSpliterUgaDrawGetMode (
652 IN EFI_UGA_DRAW_PROTOCOL
*This
,
653 OUT UINT32
*HorizontalResolution
,
654 OUT UINT32
*VerticalResolution
,
655 OUT UINT32
*ColorDepth
,
656 OUT UINT32
*RefreshRate
661 Return the current video mode information.
664 This - Protocol instance pointer.
665 HorizontalResolution - Current video horizontal resolution in pixels
666 VerticalResolution - Current video vertical resolution in pixels
667 ColorDepth - Current video color depth in bits per pixel
668 RefreshRate - Current video refresh rate in Hz.
671 EFI_SUCCESS - Mode information returned.
672 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
673 EFI_INVALID_PARAMETER - One of the input args was NULL.
677 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
679 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
680 return EFI_INVALID_PARAMETER
;
683 // retrieve private data
685 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
687 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
688 *VerticalResolution
= Private
->UgaVerticalResolution
;
689 *ColorDepth
= Private
->UgaColorDepth
;
690 *RefreshRate
= Private
->UgaRefreshRate
;
697 ConSpliterUgaDrawSetMode (
698 IN EFI_UGA_DRAW_PROTOCOL
*This
,
699 IN UINT32 HorizontalResolution
,
700 IN UINT32 VerticalResolution
,
701 IN UINT32 ColorDepth
,
702 IN UINT32 RefreshRate
707 Return the current video mode information.
710 This - Protocol instance pointer.
711 HorizontalResolution - Current video horizontal resolution in pixels
712 VerticalResolution - Current video vertical resolution in pixels
713 ColorDepth - Current video color depth in bits per pixel
714 RefreshRate - Current video refresh rate in Hz.
717 EFI_SUCCESS - Mode information returned.
718 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
719 EFI_OUT_OF_RESOURCES - Out of resources.
724 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
726 EFI_STATUS ReturnStatus
;
728 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
731 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
732 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
734 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
737 // UgaDevNullSetMode ()
739 ReturnStatus
= EFI_SUCCESS
;
742 // Free the old version
744 if (Private
->UgaBlt
!= NULL
) {
745 FreePool (Private
->UgaBlt
);
749 // Allocate the virtual Blt buffer
751 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
752 Private
->UgaBlt
= AllocateZeroPool (Size
);
753 if (Private
->UgaBlt
== NULL
) {
754 return EFI_OUT_OF_RESOURCES
;
758 // Update the Mode data
760 Private
->UgaHorizontalResolution
= HorizontalResolution
;
761 Private
->UgaVerticalResolution
= VerticalResolution
;
762 Private
->UgaColorDepth
= ColorDepth
;
763 Private
->UgaRefreshRate
= RefreshRate
;
765 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
769 // return the worst status met
771 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
773 ReturnStatus
= EFI_UNSUPPORTED
;
775 if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
776 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
777 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
778 Status
= UgaDraw
->SetMode (
780 HorizontalResolution
,
785 if (EFI_ERROR (Status
)) {
786 ReturnStatus
= Status
;
791 if (EFI_ERROR (ReturnStatus
)) {
792 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
793 if (GraphicsOutput
!= NULL
) {
795 // Find corresponding ModeNumber of this GraphicsOutput instance
797 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
798 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
799 if (EFI_ERROR (Status
)) {
802 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
809 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
810 if (EFI_ERROR (Status
)) {
811 ReturnStatus
= Status
;
822 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
823 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
824 IN EFI_UGA_BLT_OPERATION BltOperation
,
827 IN UINTN DestinationX
,
828 IN UINTN DestinationY
,
831 IN UINTN Delta OPTIONAL
837 EFI_UGA_PIXEL
*BltPtr
;
838 EFI_UGA_PIXEL
*ScreenPtr
;
839 UINT32 HorizontalResolution
;
840 UINT32 VerticalResolution
;
842 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
843 return EFI_INVALID_PARAMETER
;
846 if (Width
== 0 || Height
== 0) {
847 return EFI_INVALID_PARAMETER
;
851 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
854 HorizontalResolution
= Private
->UgaHorizontalResolution
;
855 VerticalResolution
= Private
->UgaVerticalResolution
;
858 // We need to fill the Virtual Screen buffer with the blt data.
860 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
862 // Video to BltBuffer: Source is Video, destination is BltBuffer
864 if ((SourceY
+ Height
) > VerticalResolution
) {
865 return EFI_INVALID_PARAMETER
;
868 if ((SourceX
+ Width
) > HorizontalResolution
) {
869 return EFI_INVALID_PARAMETER
;
872 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
873 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
875 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
876 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
877 ScreenPtr
+= HorizontalResolution
;
882 // BltBuffer to Video: Source is BltBuffer, destination is Video
884 if (DestinationY
+ Height
> VerticalResolution
) {
885 return EFI_INVALID_PARAMETER
;
888 if (DestinationX
+ Width
> HorizontalResolution
) {
889 return EFI_INVALID_PARAMETER
;
892 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
894 // Copy backwards, only care the Video to Video Blt
896 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
897 SrcY
= SourceY
+ Height
- 1;
901 // Copy forwards, for other cases
903 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
908 while (Height
!= 0) {
909 if (BltOperation
== EfiUgaVideoFill
) {
910 for (Index
= 0; Index
< Width
; Index
++) {
911 ScreenPtr
[Index
] = *BltBuffer
;
914 if (BltOperation
== EfiUgaBltBufferToVideo
) {
915 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
917 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
920 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
924 ScreenPtr
+= HorizontalResolution
;
927 ScreenPtr
-= HorizontalResolution
;
939 ConSpliterUgaDrawBlt (
940 IN EFI_UGA_DRAW_PROTOCOL
*This
,
941 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
942 IN EFI_UGA_BLT_OPERATION BltOperation
,
945 IN UINTN DestinationX
,
946 IN UINTN DestinationY
,
949 IN UINTN Delta OPTIONAL
954 The following table defines actions for BltOperations:
955 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
956 directly to every pixel of the video display rectangle
957 (DestinationX, DestinationY)
958 (DestinationX + Width, DestinationY + Height).
959 Only one pixel will be used from the BltBuffer. Delta is NOT used.
960 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
961 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
962 the BltBuffer rectangle (DestinationX, DestinationY )
963 (DestinationX + Width, DestinationY + Height). If DestinationX or
964 DestinationY is not zero then Delta must be set to the length in bytes
965 of a row in the BltBuffer.
966 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
967 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
968 video display rectangle (DestinationX, DestinationY)
969 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
970 not zero then Delta must be set to the length in bytes of a row in the
972 EfiUgaVideoToVideo - Copy from the video display rectangle
973 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
974 to the video display rectangle (DestinationX, DestinationY)
975 (DestinationX + Width, DestinationY + Height).
976 The BltBuffer and Delta are not used in this mode.
979 This - Protocol instance pointer.
980 BltBuffer - Buffer containing data to blit into video buffer. This
981 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
982 BltOperation - Operation to perform on BlitBuffer and video memory
983 SourceX - X coordinate of source for the BltBuffer.
984 SourceY - Y coordinate of source for the BltBuffer.
985 DestinationX - X coordinate of destination for the BltBuffer.
986 DestinationY - Y coordinate of destination for the BltBuffer.
987 Width - Width of rectangle in BltBuffer in pixels.
988 Height - Hight of rectangle in BltBuffer in pixels.
992 EFI_SUCCESS - The Blt operation completed.
993 EFI_INVALID_PARAMETER - BltOperation is not valid.
994 EFI_DEVICE_ERROR - A hardware error occured writting to the video
1000 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
1002 EFI_STATUS ReturnStatus
;
1003 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1005 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
1008 // Sync up DevNull UGA device
1010 ReturnStatus
= DevNullUgaBlt (
1022 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1023 return ReturnStatus
;
1026 // return the worst status met
1028 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1029 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1030 if (GraphicsOutput
!= NULL
) {
1031 Status
= GraphicsOutput
->Blt (
1033 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1034 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1043 if (EFI_ERROR (Status
)) {
1044 ReturnStatus
= Status
;
1045 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1047 // Only need to read the data into buffer one time
1053 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1054 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1055 Private
->TextOutList
[Index
].UgaDraw
,
1066 if (EFI_ERROR (Status
)) {
1067 ReturnStatus
= Status
;
1068 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1070 // Only need to read the data into buffer one time
1077 return ReturnStatus
;
1082 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1083 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1084 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1087 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1088 return UgaDraw
->Blt (
1091 EfiUgaBltBufferToVideo
,
1096 Private
->UgaHorizontalResolution
,
1097 Private
->UgaVerticalResolution
,
1098 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1100 } else if (GraphicsOutput
!= NULL
) {
1101 return GraphicsOutput
->Blt (
1103 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1104 EfiBltBufferToVideo
,
1109 Private
->UgaHorizontalResolution
,
1110 Private
->UgaVerticalResolution
,
1114 return EFI_UNSUPPORTED
;
1119 DevNullTextOutOutputString (
1120 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1125 Routine Description:
1126 Write a Unicode string to the output device.
1129 Private - Pointer to the console output splitter's private data. It
1130 indicates the calling context.
1131 WString - The NULL-terminated Unicode string to be displayed on the output
1132 device(s). All output devices must also support the Unicode
1133 drawing defined in this file.
1136 EFI_SUCCESS - The string was output to the device.
1137 EFI_DEVICE_ERROR - The device reported an error while attempting to
1139 EFI_UNSUPPORTED - The output device's mode is not currently in a
1141 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1142 characters in the Unicode string could not be
1143 rendered and were skipped.
1148 UINTN SizeAttribute
;
1150 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1157 INT32
*NullAttributes
;
1162 Mode
= &Private
->TextOutMode
;
1163 NullScreen
= Private
->DevNullScreen
;
1164 NullAttributes
= Private
->DevNullAttributes
;
1165 LastRow
= Private
->DevNullRows
- 1;
1166 MaxColumn
= Private
->DevNullColumns
;
1168 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1176 if (*WString
== CHAR_BACKSPACE
) {
1178 // If the cursor is at the left edge of the display, then move the cursor
1181 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1183 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1187 // If the cursor is not at the left edge of the display,
1188 // then move the cursor left one column.
1190 if (Mode
->CursorColumn
> 0) {
1191 Mode
->CursorColumn
--;
1192 if (Mode
->CursorColumn
> 0 &&
1193 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1195 Mode
->CursorColumn
--;
1198 // Insert an extra backspace
1200 InsertChar
= CHAR_BACKSPACE
;
1205 InsertChar
= TempChar
;
1218 } else if (*WString
== CHAR_LINEFEED
) {
1220 // If the cursor is at the bottom of the display,
1221 // then scroll the display one row, and do not update
1222 // the cursor position. Otherwise, move the cursor down one row.
1224 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1226 // Scroll Screen Up One Row
1228 SizeAttribute
= LastRow
* MaxColumn
;
1231 NullAttributes
+ MaxColumn
,
1232 SizeAttribute
* sizeof (INT32
)
1236 // Each row has an ending CHAR_NULL. So one more character each line
1237 // for DevNullScreen than DevNullAttributes
1239 SizeScreen
= SizeAttribute
+ LastRow
;
1242 NullScreen
+ (MaxColumn
+ 1),
1243 SizeScreen
* sizeof (CHAR16
)
1247 // Print Blank Line at last line
1249 Screen
= NullScreen
+ SizeScreen
;
1250 Attribute
= NullAttributes
+ SizeAttribute
;
1252 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1254 *Attribute
= Mode
->Attribute
;
1261 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1263 // Move the cursor to the beginning of the current row.
1265 Mode
->CursorColumn
= 0;
1269 // Print the character at the current cursor position and
1270 // move the cursor right one column. If this moves the cursor
1271 // past the right edge of the display, then the line should wrap to
1272 // the beginning of the next line. This is equivalent to inserting
1273 // a CR and an LF. Note that if the cursor is at the bottom of the
1274 // display, and the line wraps, then the display will be scrolled
1277 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1279 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1280 if (*WString
== CHAR_NULL
) {
1284 if (*WString
== CHAR_BACKSPACE
) {
1288 if (*WString
== CHAR_LINEFEED
) {
1292 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1296 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1297 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1302 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1304 // If a wide char is at the rightmost column, then move the char
1305 // to the beginning of the next row
1307 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1308 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1310 Mode
->CursorColumn
++;
1312 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1313 NullAttributes
[Index
] = Mode
->Attribute
;
1314 if (CurrentWidth
== 1) {
1315 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1317 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1318 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1321 Index
+= CurrentWidth
;
1323 Mode
->CursorColumn
+= CurrentWidth
;
1327 // At the end of line, output carriage return and line feed
1329 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1330 DevNullTextOutOutputString (Private
, mCrLfString
);
1339 DevNullTextOutSetMode (
1340 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1345 Routine Description:
1346 Sets the output device(s) to a specified mode.
1349 Private - Private data structure pointer.
1350 ModeNumber - The mode number to set.
1353 EFI_SUCCESS - The requested text mode was set.
1354 EFI_DEVICE_ERROR - The device had an error and
1355 could not complete the request.
1356 EFI_UNSUPPORTED - The mode number was not valid.
1357 EFI_OUT_OF_RESOURCES - Out of resources.
1365 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1368 // No extra check for ModeNumber here, as it has been checked in
1369 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1370 // Row and Column should be fetched from intersection map.
1372 if (Private
->TextOutModeMap
!= NULL
) {
1373 CurrentMode
= *(Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
);
1375 CurrentMode
= (INT32
)(ModeNumber
);
1377 Mode
= &(Private
->TextOutQueryData
[CurrentMode
]);
1379 Column
= Mode
->Columns
;
1381 if (Row
<= 0 && Column
<= 0) {
1382 return EFI_UNSUPPORTED
;
1385 if (Private
->TextOutMode
.Mode
!= (INT32
) ModeNumber
) {
1387 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1388 Private
->DevNullColumns
= Column
;
1389 Private
->DevNullRows
= Row
;
1391 if (Private
->DevNullScreen
!= NULL
) {
1392 FreePool (Private
->DevNullScreen
);
1395 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1396 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1397 if (Private
->DevNullScreen
== NULL
) {
1398 return EFI_OUT_OF_RESOURCES
;
1401 if (Private
->DevNullAttributes
!= NULL
) {
1402 FreePool (Private
->DevNullAttributes
);
1405 Size
= Row
* Column
* sizeof (INT32
);
1406 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1407 if (Private
->DevNullAttributes
== NULL
) {
1408 return EFI_OUT_OF_RESOURCES
;
1412 DevNullTextOutClearScreen (Private
);
1418 DevNullTextOutClearScreen (
1419 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1423 Routine Description:
1424 Clears the output device(s) display to the currently selected background
1428 Private - Protocol instance pointer.
1431 EFI_SUCCESS - The operation completed successfully.
1432 EFI_DEVICE_ERROR - The device had an error and
1433 could not complete the request.
1434 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1442 INT32 CurrentAttribute
;
1445 // Clear the DevNull Text Out Buffers.
1446 // The screen is filled with spaces.
1447 // The attributes are all synced with the current Simple Text Out Attribute
1449 Screen
= Private
->DevNullScreen
;
1450 Attributes
= Private
->DevNullAttributes
;
1451 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1453 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1454 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1456 *Attributes
= CurrentAttribute
;
1459 // Each line of the screen has a NULL on the end so we must skip over it
1464 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1466 return DevNullTextOutEnableCursor (Private
, TRUE
);
1470 DevNullTextOutSetCursorPosition (
1471 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1477 Routine Description:
1478 Sets the current coordinates of the cursor position
1481 Private - Protocol instance pointer.
1482 Column, Row - the position to set the cursor to. Must be greater than or
1483 equal to zero and less than the number of columns and rows
1487 EFI_SUCCESS - The operation completed successfully.
1488 EFI_DEVICE_ERROR - The device had an error and
1489 could not complete the request.
1490 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1491 cursor position is invalid for the current mode.
1496 // No need to do extra check here as whether (Column, Row) is valid has
1497 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1498 // always be supported.
1500 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1501 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1507 DevNullTextOutEnableCursor (
1508 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1512 Routine Description:
1514 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1515 In this driver, the cursor cannot be hidden.
1519 Private - Indicates the calling context.
1521 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1522 is set to be invisible.
1526 EFI_SUCCESS - The request is valid.
1531 Private
->TextOutMode
.CursorVisible
= Visible
;
1538 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1541 Routine Description:
1542 Take the DevNull TextOut device and update the Simple Text Out on every
1546 Private - Indicates the calling context.
1549 EFI_SUCCESS - The request is valid.
1550 other - Return status of TextOut->OutputString ()
1555 EFI_STATUS ReturnStatus
;
1560 UINTN CurrentColumn
;
1563 INT32 StartAttribute
;
1564 BOOLEAN StartCursorState
;
1569 CHAR16
*ScreenStart
;
1570 INT32 CurrentAttribute
;
1572 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1575 // Save the devices Attributes, Cursor enable state and location
1577 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1578 StartRow
= Private
->TextOutMode
.CursorRow
;
1579 StartAttribute
= Private
->TextOutMode
.Attribute
;
1580 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1582 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1584 Sto
= Private
->TextOutList
[List
].TextOut
;
1587 // Skip non GOP/UGA devices
1589 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1590 Sto
->EnableCursor (Sto
, FALSE
);
1591 Sto
->ClearScreen (Sto
);
1595 ReturnStatus
= EFI_SUCCESS
;
1596 Screen
= Private
->DevNullScreen
;
1597 Attributes
= Private
->DevNullAttributes
;
1598 MaxColumn
= Private
->DevNullColumns
;
1600 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1601 if (Buffer
== NULL
) {
1602 return ReturnStatus
;
1605 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1607 if (Row
== (Private
->DevNullRows
- 1)) {
1609 // Don't ever sync the last character as it will scroll the screen
1611 Screen
[MaxColumn
- 1] = 0x00;
1615 while (Column
< MaxColumn
) {
1616 if (Screen
[Column
]) {
1617 CurrentAttribute
= Attributes
[Column
];
1618 CurrentColumn
= Column
;
1619 ScreenStart
= &Screen
[Column
];
1622 // the line end is alway 0x0. So Column should be less than MaxColumn
1623 // It should be still in the same row
1625 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1627 if (Attributes
[Column
] != CurrentAttribute
) {
1634 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1642 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1644 Sto
= Private
->TextOutList
[List
].TextOut
;
1647 // Skip non GOP/UGA devices
1649 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1650 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1651 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1652 Status
= Sto
->OutputString (Sto
, Buffer
);
1653 if (EFI_ERROR (Status
)) {
1654 ReturnStatus
= Status
;
1665 // Restore the devices Attributes, Cursor enable state and location
1667 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1668 Sto
= Private
->TextOutList
[List
].TextOut
;
1671 // Skip non GOP/UGA devices
1673 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1674 Sto
->SetAttribute (Sto
, StartAttribute
);
1675 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1676 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1677 if (EFI_ERROR (Status
)) {
1678 ReturnStatus
= Status
;
1685 return ReturnStatus
;