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 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 DevNullSyncGopStdOut (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
;
192 TEXT_OUT_GOP_MODE
*Mode
;
194 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
195 return EFI_INVALID_PARAMETER
;
199 // retrieve private data
201 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
203 if (Private
->HardwareNeedsStarting
) {
204 return EFI_NOT_STARTED
;
207 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
210 return EFI_OUT_OF_RESOURCES
;
213 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
215 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
216 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
217 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
218 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
219 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
226 ConSpliterGraphicsOutputSetMode (
227 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
234 Graphics output protocol interface to set video mode
237 This - Protocol instance pointer.
238 ModeNumber - The mode number to be set.
241 EFI_SUCCESS - Graphics mode was changed.
242 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
243 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
248 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
250 EFI_STATUS ReturnStatus
;
251 TEXT_OUT_GOP_MODE
*Mode
;
253 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
256 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
257 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
259 if (ModeNumber
>= This
->Mode
->MaxMode
) {
260 return EFI_UNSUPPORTED
;
263 if (ModeNumber
== This
->Mode
->Mode
) {
267 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
270 // GopDevNullSetMode ()
272 ReturnStatus
= EFI_SUCCESS
;
275 // Free the old version
277 if (Private
->GraphicsOutputBlt
!= NULL
) {
278 FreePool (Private
->GraphicsOutputBlt
);
282 // Allocate the virtual Blt buffer
284 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
285 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
286 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
288 if (Private
->GraphicsOutputBlt
== NULL
) {
289 return EFI_OUT_OF_RESOURCES
;
292 if (!Private
->HardwareNeedsStarting
) {
293 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
294 return EFI_UNSUPPORTED
;
298 // return the worst status met
300 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
301 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
302 if (GraphicsOutput
!= NULL
) {
304 // Find corresponding ModeNumber of this GraphicsOutput instance
306 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
307 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
308 if (EFI_ERROR (Status
)) {
311 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
318 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
319 if (EFI_ERROR (Status
)) {
320 ReturnStatus
= Status
;
324 if (EFI_ERROR (ReturnStatus
)) {
325 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
326 if (UgaDraw
!= NULL
) {
327 Status
= UgaDraw
->SetMode (
329 Mode
->HorizontalResolution
,
330 Mode
->VerticalResolution
,
334 if (EFI_ERROR (Status
)) {
335 ReturnStatus
= Status
;
341 This
->Mode
->Mode
= ModeNumber
;
343 Info
= This
->Mode
->Info
;
344 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
345 Info
->VerticalResolution
= Mode
->VerticalResolution
;
346 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
349 // Information is not enough here, so the following items remain unchanged:
350 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
351 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
352 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
355 Private
->HardwareNeedsStarting
= FALSE
;
362 DevNullGraphicsOutputBlt (
363 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
364 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
365 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
368 IN UINTN DestinationX
,
369 IN UINTN DestinationY
,
372 IN UINTN Delta OPTIONAL
378 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
379 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
380 UINTN HorizontalResolution
;
381 UINTN VerticalResolution
;
383 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
384 return EFI_INVALID_PARAMETER
;
387 if (Width
== 0 || Height
== 0) {
388 return EFI_INVALID_PARAMETER
;
392 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
395 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
396 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
399 // We need to fill the Virtual Screen buffer with the blt data.
401 if (BltOperation
== EfiBltVideoToBltBuffer
) {
403 // Video to BltBuffer: Source is Video, destination is BltBuffer
405 if ((SourceY
+ Height
) > VerticalResolution
) {
406 return EFI_INVALID_PARAMETER
;
409 if ((SourceX
+ Width
) > HorizontalResolution
) {
410 return EFI_INVALID_PARAMETER
;
413 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
414 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
416 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
417 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
418 ScreenPtr
+= HorizontalResolution
;
423 // BltBuffer to Video: Source is BltBuffer, destination is Video
425 if (DestinationY
+ Height
> VerticalResolution
) {
426 return EFI_INVALID_PARAMETER
;
429 if (DestinationX
+ Width
> HorizontalResolution
) {
430 return EFI_INVALID_PARAMETER
;
433 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
435 // Copy backwards, only care the Video to Video Blt
437 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
438 SrcY
= SourceY
+ Height
- 1;
442 // Copy forwards, for other cases
444 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
449 while (Height
!= 0) {
450 if (BltOperation
== EfiBltVideoFill
) {
451 for (Index
= 0; Index
< Width
; Index
++) {
452 ScreenPtr
[Index
] = *BltBuffer
;
455 if (BltOperation
== EfiBltBufferToVideo
) {
456 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
458 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
461 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
465 ScreenPtr
+= HorizontalResolution
;
468 ScreenPtr
-= HorizontalResolution
;
480 ConSpliterGraphicsOutputBlt (
481 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
482 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
483 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
486 IN UINTN DestinationX
,
487 IN UINTN DestinationY
,
490 IN UINTN Delta OPTIONAL
495 The following table defines actions for BltOperations:
496 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
497 directly to every pixel of the video display rectangle
498 (DestinationX, DestinationY)
499 (DestinationX + Width, DestinationY + Height).
500 Only one pixel will be used from the BltBuffer. Delta is NOT used.
501 EfiBltVideoToBltBuffer - Read data from the video display rectangle
502 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
503 the BltBuffer rectangle (DestinationX, DestinationY )
504 (DestinationX + Width, DestinationY + Height). If DestinationX or
505 DestinationY is not zero then Delta must be set to the length in bytes
506 of a row in the BltBuffer.
507 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
508 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
509 video display rectangle (DestinationX, DestinationY)
510 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
511 not zero then Delta must be set to the length in bytes of a row in the
513 EfiBltVideoToVideo - Copy from the video display rectangle
514 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
515 to the video display rectangle (DestinationX, DestinationY)
516 (DestinationX + Width, DestinationY + Height).
517 The BltBuffer and Delta are not used in this mode.
520 This - Protocol instance pointer.
521 BltBuffer - Buffer containing data to blit into video buffer. This
522 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
523 BltOperation - Operation to perform on BlitBuffer and video memory
524 SourceX - X coordinate of source for the BltBuffer.
525 SourceY - Y coordinate of source for the BltBuffer.
526 DestinationX - X coordinate of destination for the BltBuffer.
527 DestinationY - Y coordinate of destination for the BltBuffer.
528 Width - Width of rectangle in BltBuffer in pixels.
529 Height - Hight of rectangle in BltBuffer in pixels.
533 EFI_SUCCESS - The Blt operation completed.
534 EFI_INVALID_PARAMETER - BltOperation is not valid.
535 EFI_DEVICE_ERROR - A hardware error occured writting to the video
541 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
543 EFI_STATUS ReturnStatus
;
544 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
545 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
547 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
550 // Sync up DevNull GOP device
552 ReturnStatus
= DevNullGraphicsOutputBlt (
565 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
569 // return the worst status met
571 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
572 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
573 if (GraphicsOutput
!= NULL
) {
574 Status
= GraphicsOutput
->Blt (
586 if (EFI_ERROR (Status
)) {
587 ReturnStatus
= Status
;
588 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
590 // Only need to read the data into buffer one time
596 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
597 if (UgaDraw
!= NULL
) {
598 Status
= UgaDraw
->Blt (
600 (EFI_UGA_PIXEL
*) BltBuffer
,
601 (EFI_UGA_BLT_OPERATION
) BltOperation
,
610 if (EFI_ERROR (Status
)) {
611 ReturnStatus
= Status
;
612 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
614 // Only need to read the data into buffer one time
626 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
627 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
628 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
631 if (GraphicsOutput
!= NULL
) {
632 return GraphicsOutput
->Blt (
634 Private
->GraphicsOutputBlt
,
640 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
641 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
645 return UgaDraw
->Blt (
647 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
648 EfiUgaBltBufferToVideo
,
653 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
654 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
662 ConSpliterUgaDrawGetMode (
663 IN EFI_UGA_DRAW_PROTOCOL
*This
,
664 OUT UINT32
*HorizontalResolution
,
665 OUT UINT32
*VerticalResolution
,
666 OUT UINT32
*ColorDepth
,
667 OUT UINT32
*RefreshRate
672 Return the current video mode information.
675 This - Protocol instance pointer.
676 HorizontalResolution - Current video horizontal resolution in pixels
677 VerticalResolution - Current video vertical resolution in pixels
678 ColorDepth - Current video color depth in bits per pixel
679 RefreshRate - Current video refresh rate in Hz.
682 EFI_SUCCESS - Mode information returned.
683 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
684 EFI_INVALID_PARAMETER - One of the input args was NULL.
688 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
690 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
691 return EFI_INVALID_PARAMETER
;
694 // retrieve private data
696 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
698 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
699 *VerticalResolution
= Private
->UgaVerticalResolution
;
700 *ColorDepth
= Private
->UgaColorDepth
;
701 *RefreshRate
= Private
->UgaRefreshRate
;
708 ConSpliterUgaDrawSetMode (
709 IN EFI_UGA_DRAW_PROTOCOL
*This
,
710 IN UINT32 HorizontalResolution
,
711 IN UINT32 VerticalResolution
,
712 IN UINT32 ColorDepth
,
713 IN UINT32 RefreshRate
718 Return the current video mode information.
721 This - Protocol instance pointer.
722 HorizontalResolution - Current video horizontal resolution in pixels
723 VerticalResolution - Current video vertical resolution in pixels
724 ColorDepth - Current video color depth in bits per pixel
725 RefreshRate - Current video refresh rate in Hz.
728 EFI_SUCCESS - Mode information returned.
729 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
730 EFI_OUT_OF_RESOURCES - Out of resources.
735 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
737 EFI_STATUS ReturnStatus
;
739 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
742 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
743 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
745 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
748 // UgaDevNullSetMode ()
750 ReturnStatus
= EFI_SUCCESS
;
753 // Free the old version
755 if (Private
->UgaBlt
!= NULL
) {
756 FreePool (Private
->UgaBlt
);
760 // Allocate the virtual Blt buffer
762 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
763 Private
->UgaBlt
= AllocateZeroPool (Size
);
764 if (Private
->UgaBlt
== NULL
) {
765 return EFI_OUT_OF_RESOURCES
;
769 // Update the Mode data
771 Private
->UgaHorizontalResolution
= HorizontalResolution
;
772 Private
->UgaVerticalResolution
= VerticalResolution
;
773 Private
->UgaColorDepth
= ColorDepth
;
774 Private
->UgaRefreshRate
= RefreshRate
;
776 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
780 // return the worst status met
782 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
783 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
784 if (UgaDraw
!= NULL
) {
785 Status
= UgaDraw
->SetMode (
787 HorizontalResolution
,
792 if (EFI_ERROR (Status
)) {
793 ReturnStatus
= Status
;
797 if (EFI_ERROR (ReturnStatus
)) {
798 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
799 if (GraphicsOutput
!= NULL
) {
801 // Find corresponding ModeNumber of this GraphicsOutput instance
803 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
804 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
805 if (EFI_ERROR (Status
)) {
808 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
815 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
816 if (EFI_ERROR (Status
)) {
817 ReturnStatus
= Status
;
828 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
829 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
830 IN EFI_UGA_BLT_OPERATION BltOperation
,
833 IN UINTN DestinationX
,
834 IN UINTN DestinationY
,
837 IN UINTN Delta OPTIONAL
843 EFI_UGA_PIXEL
*BltPtr
;
844 EFI_UGA_PIXEL
*ScreenPtr
;
845 UINT32 HorizontalResolution
;
846 UINT32 VerticalResolution
;
848 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
849 return EFI_INVALID_PARAMETER
;
852 if (Width
== 0 || Height
== 0) {
853 return EFI_INVALID_PARAMETER
;
857 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
860 HorizontalResolution
= Private
->UgaHorizontalResolution
;
861 VerticalResolution
= Private
->UgaVerticalResolution
;
864 // We need to fill the Virtual Screen buffer with the blt data.
866 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
868 // Video to BltBuffer: Source is Video, destination is BltBuffer
870 if ((SourceY
+ Height
) > VerticalResolution
) {
871 return EFI_INVALID_PARAMETER
;
874 if ((SourceX
+ Width
) > HorizontalResolution
) {
875 return EFI_INVALID_PARAMETER
;
878 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
879 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
881 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
882 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
883 ScreenPtr
+= HorizontalResolution
;
888 // BltBuffer to Video: Source is BltBuffer, destination is Video
890 if (DestinationY
+ Height
> VerticalResolution
) {
891 return EFI_INVALID_PARAMETER
;
894 if (DestinationX
+ Width
> HorizontalResolution
) {
895 return EFI_INVALID_PARAMETER
;
898 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
900 // Copy backwards, only care the Video to Video Blt
902 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
903 SrcY
= SourceY
+ Height
- 1;
907 // Copy forwards, for other cases
909 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
914 while (Height
!= 0) {
915 if (BltOperation
== EfiUgaVideoFill
) {
916 for (Index
= 0; Index
< Width
; Index
++) {
917 ScreenPtr
[Index
] = *BltBuffer
;
920 if (BltOperation
== EfiUgaBltBufferToVideo
) {
921 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
923 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
926 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
930 ScreenPtr
+= HorizontalResolution
;
933 ScreenPtr
-= HorizontalResolution
;
945 ConSpliterUgaDrawBlt (
946 IN EFI_UGA_DRAW_PROTOCOL
*This
,
947 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
948 IN EFI_UGA_BLT_OPERATION BltOperation
,
951 IN UINTN DestinationX
,
952 IN UINTN DestinationY
,
955 IN UINTN Delta OPTIONAL
960 The following table defines actions for BltOperations:
961 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
962 directly to every pixel of the video display rectangle
963 (DestinationX, DestinationY)
964 (DestinationX + Width, DestinationY + Height).
965 Only one pixel will be used from the BltBuffer. Delta is NOT used.
966 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
967 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
968 the BltBuffer rectangle (DestinationX, DestinationY )
969 (DestinationX + Width, DestinationY + Height). If DestinationX or
970 DestinationY is not zero then Delta must be set to the length in bytes
971 of a row in the BltBuffer.
972 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
973 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
974 video display rectangle (DestinationX, DestinationY)
975 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
976 not zero then Delta must be set to the length in bytes of a row in the
978 EfiUgaVideoToVideo - Copy from the video display rectangle
979 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
980 to the video display rectangle (DestinationX, DestinationY)
981 (DestinationX + Width, DestinationY + Height).
982 The BltBuffer and Delta are not used in this mode.
985 This - Protocol instance pointer.
986 BltBuffer - Buffer containing data to blit into video buffer. This
987 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
988 BltOperation - Operation to perform on BlitBuffer and video memory
989 SourceX - X coordinate of source for the BltBuffer.
990 SourceY - Y coordinate of source for the BltBuffer.
991 DestinationX - X coordinate of destination for the BltBuffer.
992 DestinationY - Y coordinate of destination for the BltBuffer.
993 Width - Width of rectangle in BltBuffer in pixels.
994 Height - Hight of rectangle in BltBuffer in pixels.
998 EFI_SUCCESS - The Blt operation completed.
999 EFI_INVALID_PARAMETER - BltOperation is not valid.
1000 EFI_DEVICE_ERROR - A hardware error occured writting to the video
1006 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
1008 EFI_STATUS ReturnStatus
;
1009 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1011 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
1014 // Sync up DevNull UGA device
1016 ReturnStatus
= DevNullUgaBlt (
1028 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1029 return ReturnStatus
;
1032 // return the worst status met
1034 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1035 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1036 if (GraphicsOutput
!= NULL
) {
1037 Status
= GraphicsOutput
->Blt (
1039 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1040 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1049 if (EFI_ERROR (Status
)) {
1050 ReturnStatus
= Status
;
1051 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1053 // Only need to read the data into buffer one time
1059 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
1060 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1061 Private
->TextOutList
[Index
].UgaDraw
,
1072 if (EFI_ERROR (Status
)) {
1073 ReturnStatus
= Status
;
1074 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1076 // Only need to read the data into buffer one time
1083 return ReturnStatus
;
1088 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1089 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1090 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1093 if (UgaDraw
!= NULL
) {
1094 return UgaDraw
->Blt (
1097 EfiUgaBltBufferToVideo
,
1102 Private
->UgaHorizontalResolution
,
1103 Private
->UgaVerticalResolution
,
1104 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1107 return GraphicsOutput
->Blt (
1109 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1110 EfiBltBufferToVideo
,
1115 Private
->UgaHorizontalResolution
,
1116 Private
->UgaVerticalResolution
,
1123 DevNullTextOutOutputString (
1124 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1129 Routine Description:
1130 Write a Unicode string to the output device.
1133 Private - Pointer to the console output splitter's private data. It
1134 indicates the calling context.
1135 WString - The NULL-terminated Unicode string to be displayed on the output
1136 device(s). All output devices must also support the Unicode
1137 drawing defined in this file.
1140 EFI_SUCCESS - The string was output to the device.
1141 EFI_DEVICE_ERROR - The device reported an error while attempting to
1143 EFI_UNSUPPORTED - The output device's mode is not currently in a
1145 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1146 characters in the Unicode string could not be
1147 rendered and were skipped.
1152 UINTN SizeAttribute
;
1154 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1161 INT32
*NullAttributes
;
1166 Mode
= &Private
->TextOutMode
;
1167 NullScreen
= Private
->DevNullScreen
;
1168 NullAttributes
= Private
->DevNullAttributes
;
1169 LastRow
= Private
->DevNullRows
- 1;
1170 MaxColumn
= Private
->DevNullColumns
;
1172 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1180 if (*WString
== CHAR_BACKSPACE
) {
1182 // If the cursor is at the left edge of the display, then move the cursor
1185 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1187 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1191 // If the cursor is not at the left edge of the display,
1192 // then move the cursor left one column.
1194 if (Mode
->CursorColumn
> 0) {
1195 Mode
->CursorColumn
--;
1196 if (Mode
->CursorColumn
> 0 &&
1197 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1199 Mode
->CursorColumn
--;
1202 // Insert an extra backspace
1204 InsertChar
= CHAR_BACKSPACE
;
1209 InsertChar
= TempChar
;
1222 } else if (*WString
== CHAR_LINEFEED
) {
1224 // If the cursor is at the bottom of the display,
1225 // then scroll the display one row, and do not update
1226 // the cursor position. Otherwise, move the cursor down one row.
1228 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1230 // Scroll Screen Up One Row
1232 SizeAttribute
= LastRow
* MaxColumn
;
1235 NullAttributes
+ MaxColumn
,
1236 SizeAttribute
* sizeof (INT32
)
1240 // Each row has an ending CHAR_NULL. So one more character each line
1241 // for DevNullScreen than DevNullAttributes
1243 SizeScreen
= SizeAttribute
+ LastRow
;
1246 NullScreen
+ (MaxColumn
+ 1),
1247 SizeScreen
* sizeof (CHAR16
)
1251 // Print Blank Line at last line
1253 Screen
= NullScreen
+ SizeScreen
;
1254 Attribute
= NullAttributes
+ SizeAttribute
;
1256 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1258 *Attribute
= Mode
->Attribute
;
1265 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1267 // Move the cursor to the beginning of the current row.
1269 Mode
->CursorColumn
= 0;
1273 // Print the character at the current cursor position and
1274 // move the cursor right one column. If this moves the cursor
1275 // past the right edge of the display, then the line should wrap to
1276 // the beginning of the next line. This is equivalent to inserting
1277 // a CR and an LF. Note that if the cursor is at the bottom of the
1278 // display, and the line wraps, then the display will be scrolled
1281 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1283 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1284 if (*WString
== CHAR_NULL
) {
1288 if (*WString
== CHAR_BACKSPACE
) {
1292 if (*WString
== CHAR_LINEFEED
) {
1296 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1300 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1301 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1306 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1308 // If a wide char is at the rightmost column, then move the char
1309 // to the beginning of the next row
1311 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1312 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1314 Mode
->CursorColumn
++;
1316 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1317 NullAttributes
[Index
] = Mode
->Attribute
;
1318 if (CurrentWidth
== 1) {
1319 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1321 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1322 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1325 Index
+= CurrentWidth
;
1327 Mode
->CursorColumn
+= CurrentWidth
;
1331 // At the end of line, output carriage return and line feed
1333 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1334 DevNullTextOutOutputString (Private
, mCrLfString
);
1343 DevNullTextOutSetMode (
1344 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1349 Routine Description:
1350 Sets the output device(s) to a specified mode.
1353 Private - Private data structure pointer.
1354 ModeNumber - The mode number to set.
1357 EFI_SUCCESS - The requested text mode was set.
1358 EFI_DEVICE_ERROR - The device had an error and
1359 could not complete the request.
1360 EFI_UNSUPPORTED - The mode number was not valid.
1361 EFI_OUT_OF_RESOURCES - Out of resources.
1368 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1371 // No extra check for ModeNumber here, as it has been checked in
1372 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1374 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1376 Column
= Mode
->Columns
;
1378 if (Row
<= 0 && Column
<= 0) {
1379 return EFI_UNSUPPORTED
;
1382 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1384 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1385 Private
->DevNullColumns
= Column
;
1386 Private
->DevNullRows
= Row
;
1388 if (Private
->DevNullScreen
!= NULL
) {
1389 FreePool (Private
->DevNullScreen
);
1392 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1393 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1394 if (Private
->DevNullScreen
== NULL
) {
1395 return EFI_OUT_OF_RESOURCES
;
1398 if (Private
->DevNullAttributes
!= NULL
) {
1399 FreePool (Private
->DevNullAttributes
);
1402 Size
= Row
* Column
* sizeof (INT32
);
1403 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1404 if (Private
->DevNullAttributes
== NULL
) {
1405 return EFI_OUT_OF_RESOURCES
;
1409 DevNullTextOutClearScreen (Private
);
1415 DevNullTextOutClearScreen (
1416 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1420 Routine Description:
1421 Clears the output device(s) display to the currently selected background
1425 Private - Protocol instance pointer.
1428 EFI_SUCCESS - The operation completed successfully.
1429 EFI_DEVICE_ERROR - The device had an error and
1430 could not complete the request.
1431 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1439 INT32 CurrentAttribute
;
1442 // Clear the DevNull Text Out Buffers.
1443 // The screen is filled with spaces.
1444 // The attributes are all synced with the current Simple Text Out Attribute
1446 Screen
= Private
->DevNullScreen
;
1447 Attributes
= Private
->DevNullAttributes
;
1448 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1450 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1451 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1453 *Attributes
= CurrentAttribute
;
1456 // Each line of the screen has a NULL on the end so we must skip over it
1461 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1463 return DevNullTextOutEnableCursor (Private
, TRUE
);
1467 DevNullTextOutSetCursorPosition (
1468 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1474 Routine Description:
1475 Sets the current coordinates of the cursor position
1478 Private - Protocol instance pointer.
1479 Column, Row - the position to set the cursor to. Must be greater than or
1480 equal to zero and less than the number of columns and rows
1484 EFI_SUCCESS - The operation completed successfully.
1485 EFI_DEVICE_ERROR - The device had an error and
1486 could not complete the request.
1487 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1488 cursor position is invalid for the current mode.
1493 // No need to do extra check here as whether (Column, Row) is valid has
1494 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1495 // always be supported.
1497 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1498 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1504 DevNullTextOutEnableCursor (
1505 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1509 Routine Description:
1511 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1512 In this driver, the cursor cannot be hidden.
1516 Private - Indicates the calling context.
1518 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1519 is set to be invisible.
1523 EFI_SUCCESS - The request is valid.
1528 Private
->TextOutMode
.CursorVisible
= Visible
;
1534 DevNullSyncGopStdOut (
1535 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1538 Routine Description:
1539 Take the DevNull TextOut device and update the Simple Text Out on every
1543 Private - Indicates the calling context.
1546 EFI_SUCCESS - The request is valid.
1547 other - Return status of TextOut->OutputString ()
1552 EFI_STATUS ReturnStatus
;
1557 UINTN CurrentColumn
;
1560 INT32 StartAttribute
;
1561 BOOLEAN StartCursorState
;
1566 CHAR16
*ScreenStart
;
1567 INT32 CurrentAttribute
;
1569 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1572 // Save the devices Attributes, Cursor enable state and location
1574 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1575 StartRow
= Private
->TextOutMode
.CursorRow
;
1576 StartAttribute
= Private
->TextOutMode
.Attribute
;
1577 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1579 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1581 Sto
= Private
->TextOutList
[List
].TextOut
;
1584 // Skip non GOP/UGA devices
1586 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1587 Sto
->EnableCursor (Sto
, FALSE
);
1588 Sto
->ClearScreen (Sto
);
1592 ReturnStatus
= EFI_SUCCESS
;
1593 Screen
= Private
->DevNullScreen
;
1594 Attributes
= Private
->DevNullAttributes
;
1595 MaxColumn
= Private
->DevNullColumns
;
1597 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1598 if (Buffer
== NULL
) {
1599 return ReturnStatus
;
1602 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1604 if (Row
== (Private
->DevNullRows
- 1)) {
1606 // Don't ever sync the last character as it will scroll the screen
1608 Screen
[MaxColumn
- 1] = 0x00;
1612 while (Column
< MaxColumn
) {
1613 if (Screen
[Column
]) {
1614 CurrentAttribute
= Attributes
[Column
];
1615 CurrentColumn
= Column
;
1616 ScreenStart
= &Screen
[Column
];
1619 // the line end is alway 0x0. So Column should be less than MaxColumn
1620 // It should be still in the same row
1622 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1624 if (Attributes
[Column
] != CurrentAttribute
) {
1631 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1639 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1641 Sto
= Private
->TextOutList
[List
].TextOut
;
1644 // Skip non GOP/UGA devices
1646 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1647 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1648 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1649 Status
= Sto
->OutputString (Sto
, Buffer
);
1650 if (EFI_ERROR (Status
)) {
1651 ReturnStatus
= Status
;
1662 // Restore the devices Attributes, Cursor enable state and location
1664 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1665 Sto
= Private
->TextOutList
[List
].TextOut
;
1668 // Skip non GOP/UGA devices
1670 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1671 Sto
->SetAttribute (Sto
, StartAttribute
);
1672 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1673 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1674 if (EFI_ERROR (Status
)) {
1675 ReturnStatus
= Status
;
1682 return ReturnStatus
;