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
;
293 // return the worst status met
295 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
296 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
297 if (GraphicsOutput
!= NULL
) {
299 // Find corresponding ModeNumber of this GraphicsOutput instance
301 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
302 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
303 if (EFI_ERROR (Status
)) {
306 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
313 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
314 if (EFI_ERROR (Status
)) {
315 ReturnStatus
= Status
;
319 if (EFI_ERROR (ReturnStatus
)) {
320 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
321 if (UgaDraw
!= NULL
) {
322 Status
= UgaDraw
->SetMode (
324 Mode
->HorizontalResolution
,
325 Mode
->VerticalResolution
,
329 if (EFI_ERROR (Status
)) {
330 ReturnStatus
= Status
;
336 This
->Mode
->Mode
= ModeNumber
;
338 Info
= This
->Mode
->Info
;
339 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
340 Info
->VerticalResolution
= Mode
->VerticalResolution
;
341 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
344 // Information is not enough here, so the following items remain unchanged:
345 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
346 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
347 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
350 Private
->HardwareNeedsStarting
= FALSE
;
357 DevNullGraphicsOutputBlt (
358 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
359 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
360 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
363 IN UINTN DestinationX
,
364 IN UINTN DestinationY
,
367 IN UINTN Delta OPTIONAL
373 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
374 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
375 UINTN HorizontalResolution
;
376 UINTN VerticalResolution
;
378 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
379 return EFI_INVALID_PARAMETER
;
382 if (Width
== 0 || Height
== 0) {
383 return EFI_INVALID_PARAMETER
;
387 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
390 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
391 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
394 // We need to fill the Virtual Screen buffer with the blt data.
396 if (BltOperation
== EfiBltVideoToBltBuffer
) {
398 // Video to BltBuffer: Source is Video, destination is BltBuffer
400 if ((SourceY
+ Height
) > VerticalResolution
) {
401 return EFI_INVALID_PARAMETER
;
404 if ((SourceX
+ Width
) > HorizontalResolution
) {
405 return EFI_INVALID_PARAMETER
;
408 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
409 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
411 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
412 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
413 ScreenPtr
+= HorizontalResolution
;
418 // BltBuffer to Video: Source is BltBuffer, destination is Video
420 if (DestinationY
+ Height
> VerticalResolution
) {
421 return EFI_INVALID_PARAMETER
;
424 if (DestinationX
+ Width
> HorizontalResolution
) {
425 return EFI_INVALID_PARAMETER
;
428 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
430 // Copy backwards, only care the Video to Video Blt
432 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
433 SrcY
= SourceY
+ Height
- 1;
437 // Copy forwards, for other cases
439 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
444 while (Height
!= 0) {
445 if (BltOperation
== EfiBltVideoFill
) {
446 for (Index
= 0; Index
< Width
; Index
++) {
447 ScreenPtr
[Index
] = *BltBuffer
;
450 if (BltOperation
== EfiBltBufferToVideo
) {
451 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
453 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
456 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
460 ScreenPtr
+= HorizontalResolution
;
463 ScreenPtr
-= HorizontalResolution
;
475 ConSpliterGraphicsOutputBlt (
476 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
477 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
478 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
481 IN UINTN DestinationX
,
482 IN UINTN DestinationY
,
485 IN UINTN Delta OPTIONAL
490 The following table defines actions for BltOperations:
491 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
492 directly to every pixel of the video display rectangle
493 (DestinationX, DestinationY)
494 (DestinationX + Width, DestinationY + Height).
495 Only one pixel will be used from the BltBuffer. Delta is NOT used.
496 EfiBltVideoToBltBuffer - Read data from the video display rectangle
497 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
498 the BltBuffer rectangle (DestinationX, DestinationY )
499 (DestinationX + Width, DestinationY + Height). If DestinationX or
500 DestinationY is not zero then Delta must be set to the length in bytes
501 of a row in the BltBuffer.
502 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
503 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
504 video display rectangle (DestinationX, DestinationY)
505 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
506 not zero then Delta must be set to the length in bytes of a row in the
508 EfiBltVideoToVideo - Copy from the video display rectangle
509 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
510 to the video display rectangle (DestinationX, DestinationY)
511 (DestinationX + Width, DestinationY + Height).
512 The BltBuffer and Delta are not used in this mode.
515 This - Protocol instance pointer.
516 BltBuffer - Buffer containing data to blit into video buffer. This
517 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
518 BltOperation - Operation to perform on BlitBuffer and video memory
519 SourceX - X coordinate of source for the BltBuffer.
520 SourceY - Y coordinate of source for the BltBuffer.
521 DestinationX - X coordinate of destination for the BltBuffer.
522 DestinationY - Y coordinate of destination for the BltBuffer.
523 Width - Width of rectangle in BltBuffer in pixels.
524 Height - Hight of rectangle in BltBuffer in pixels.
528 EFI_SUCCESS - The Blt operation completed.
529 EFI_INVALID_PARAMETER - BltOperation is not valid.
530 EFI_DEVICE_ERROR - A hardware error occured writting to the video
536 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
538 EFI_STATUS ReturnStatus
;
539 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
540 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
542 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
545 // Sync up DevNull GOP device
547 ReturnStatus
= DevNullGraphicsOutputBlt (
560 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
564 // return the worst status met
566 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
567 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
568 if (GraphicsOutput
!= NULL
) {
569 Status
= GraphicsOutput
->Blt (
581 if (EFI_ERROR (Status
)) {
582 ReturnStatus
= Status
;
583 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
585 // Only need to read the data into buffer one time
591 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
592 if (UgaDraw
!= NULL
) {
593 Status
= UgaDraw
->Blt (
595 (EFI_UGA_PIXEL
*) BltBuffer
,
596 (EFI_UGA_BLT_OPERATION
) BltOperation
,
605 if (EFI_ERROR (Status
)) {
606 ReturnStatus
= Status
;
607 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
609 // Only need to read the data into buffer one time
621 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
622 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
623 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
626 if (GraphicsOutput
!= NULL
) {
627 return GraphicsOutput
->Blt (
629 Private
->GraphicsOutputBlt
,
635 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
636 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
640 return UgaDraw
->Blt (
642 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
643 EfiUgaBltBufferToVideo
,
648 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
649 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
657 ConSpliterUgaDrawGetMode (
658 IN EFI_UGA_DRAW_PROTOCOL
*This
,
659 OUT UINT32
*HorizontalResolution
,
660 OUT UINT32
*VerticalResolution
,
661 OUT UINT32
*ColorDepth
,
662 OUT UINT32
*RefreshRate
667 Return the current video mode information.
670 This - Protocol instance pointer.
671 HorizontalResolution - Current video horizontal resolution in pixels
672 VerticalResolution - Current video vertical resolution in pixels
673 ColorDepth - Current video color depth in bits per pixel
674 RefreshRate - Current video refresh rate in Hz.
677 EFI_SUCCESS - Mode information returned.
678 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
679 EFI_INVALID_PARAMETER - One of the input args was NULL.
683 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
685 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
686 return EFI_INVALID_PARAMETER
;
689 // retrieve private data
691 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
693 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
694 *VerticalResolution
= Private
->UgaVerticalResolution
;
695 *ColorDepth
= Private
->UgaColorDepth
;
696 *RefreshRate
= Private
->UgaRefreshRate
;
703 ConSpliterUgaDrawSetMode (
704 IN EFI_UGA_DRAW_PROTOCOL
*This
,
705 IN UINT32 HorizontalResolution
,
706 IN UINT32 VerticalResolution
,
707 IN UINT32 ColorDepth
,
708 IN UINT32 RefreshRate
713 Return the current video mode information.
716 This - Protocol instance pointer.
717 HorizontalResolution - Current video horizontal resolution in pixels
718 VerticalResolution - Current video vertical resolution in pixels
719 ColorDepth - Current video color depth in bits per pixel
720 RefreshRate - Current video refresh rate in Hz.
723 EFI_SUCCESS - Mode information returned.
724 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
725 EFI_OUT_OF_RESOURCES - Out of resources.
730 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
732 EFI_STATUS ReturnStatus
;
734 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
737 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
738 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
740 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
743 // UgaDevNullSetMode ()
745 ReturnStatus
= EFI_SUCCESS
;
748 // Free the old version
750 if (Private
->UgaBlt
!= NULL
) {
751 FreePool (Private
->UgaBlt
);
755 // Allocate the virtual Blt buffer
757 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
758 Private
->UgaBlt
= AllocateZeroPool (Size
);
759 if (Private
->UgaBlt
== NULL
) {
760 return EFI_OUT_OF_RESOURCES
;
764 // Update the Mode data
766 Private
->UgaHorizontalResolution
= HorizontalResolution
;
767 Private
->UgaVerticalResolution
= VerticalResolution
;
768 Private
->UgaColorDepth
= ColorDepth
;
769 Private
->UgaRefreshRate
= RefreshRate
;
771 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
775 // return the worst status met
777 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
778 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
779 if (UgaDraw
!= NULL
) {
780 Status
= UgaDraw
->SetMode (
782 HorizontalResolution
,
787 if (EFI_ERROR (Status
)) {
788 ReturnStatus
= Status
;
792 if (EFI_ERROR (ReturnStatus
)) {
793 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
794 if (GraphicsOutput
!= NULL
) {
796 // Find corresponding ModeNumber of this GraphicsOutput instance
798 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
799 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
800 if (EFI_ERROR (Status
)) {
803 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
810 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
811 if (EFI_ERROR (Status
)) {
812 ReturnStatus
= Status
;
823 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
824 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
825 IN EFI_UGA_BLT_OPERATION BltOperation
,
828 IN UINTN DestinationX
,
829 IN UINTN DestinationY
,
832 IN UINTN Delta OPTIONAL
838 EFI_UGA_PIXEL
*BltPtr
;
839 EFI_UGA_PIXEL
*ScreenPtr
;
840 UINT32 HorizontalResolution
;
841 UINT32 VerticalResolution
;
843 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
844 return EFI_INVALID_PARAMETER
;
847 if (Width
== 0 || Height
== 0) {
848 return EFI_INVALID_PARAMETER
;
852 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
855 HorizontalResolution
= Private
->UgaHorizontalResolution
;
856 VerticalResolution
= Private
->UgaVerticalResolution
;
859 // We need to fill the Virtual Screen buffer with the blt data.
861 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
863 // Video to BltBuffer: Source is Video, destination is BltBuffer
865 if ((SourceY
+ Height
) > VerticalResolution
) {
866 return EFI_INVALID_PARAMETER
;
869 if ((SourceX
+ Width
) > HorizontalResolution
) {
870 return EFI_INVALID_PARAMETER
;
873 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
874 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
876 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
877 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
878 ScreenPtr
+= HorizontalResolution
;
883 // BltBuffer to Video: Source is BltBuffer, destination is Video
885 if (DestinationY
+ Height
> VerticalResolution
) {
886 return EFI_INVALID_PARAMETER
;
889 if (DestinationX
+ Width
> HorizontalResolution
) {
890 return EFI_INVALID_PARAMETER
;
893 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
895 // Copy backwards, only care the Video to Video Blt
897 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
898 SrcY
= SourceY
+ Height
- 1;
902 // Copy forwards, for other cases
904 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
909 while (Height
!= 0) {
910 if (BltOperation
== EfiUgaVideoFill
) {
911 for (Index
= 0; Index
< Width
; Index
++) {
912 ScreenPtr
[Index
] = *BltBuffer
;
915 if (BltOperation
== EfiUgaBltBufferToVideo
) {
916 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
918 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
921 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
925 ScreenPtr
+= HorizontalResolution
;
928 ScreenPtr
-= HorizontalResolution
;
940 ConSpliterUgaDrawBlt (
941 IN EFI_UGA_DRAW_PROTOCOL
*This
,
942 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
943 IN EFI_UGA_BLT_OPERATION BltOperation
,
946 IN UINTN DestinationX
,
947 IN UINTN DestinationY
,
950 IN UINTN Delta OPTIONAL
955 The following table defines actions for BltOperations:
956 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
957 directly to every pixel of the video display rectangle
958 (DestinationX, DestinationY)
959 (DestinationX + Width, DestinationY + Height).
960 Only one pixel will be used from the BltBuffer. Delta is NOT used.
961 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
962 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
963 the BltBuffer rectangle (DestinationX, DestinationY )
964 (DestinationX + Width, DestinationY + Height). If DestinationX or
965 DestinationY is not zero then Delta must be set to the length in bytes
966 of a row in the BltBuffer.
967 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
968 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
969 video display rectangle (DestinationX, DestinationY)
970 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
971 not zero then Delta must be set to the length in bytes of a row in the
973 EfiUgaVideoToVideo - Copy from the video display rectangle
974 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
975 to the video display rectangle (DestinationX, DestinationY)
976 (DestinationX + Width, DestinationY + Height).
977 The BltBuffer and Delta are not used in this mode.
980 This - Protocol instance pointer.
981 BltBuffer - Buffer containing data to blit into video buffer. This
982 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
983 BltOperation - Operation to perform on BlitBuffer and video memory
984 SourceX - X coordinate of source for the BltBuffer.
985 SourceY - Y coordinate of source for the BltBuffer.
986 DestinationX - X coordinate of destination for the BltBuffer.
987 DestinationY - Y coordinate of destination for the BltBuffer.
988 Width - Width of rectangle in BltBuffer in pixels.
989 Height - Hight of rectangle in BltBuffer in pixels.
993 EFI_SUCCESS - The Blt operation completed.
994 EFI_INVALID_PARAMETER - BltOperation is not valid.
995 EFI_DEVICE_ERROR - A hardware error occured writting to the video
1001 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
1003 EFI_STATUS ReturnStatus
;
1004 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1006 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
1009 // Sync up DevNull UGA device
1011 ReturnStatus
= DevNullUgaBlt (
1023 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1024 return ReturnStatus
;
1027 // return the worst status met
1029 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1030 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1031 if (GraphicsOutput
!= NULL
) {
1032 Status
= GraphicsOutput
->Blt (
1034 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1035 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1044 if (EFI_ERROR (Status
)) {
1045 ReturnStatus
= Status
;
1046 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1048 // Only need to read the data into buffer one time
1054 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
1055 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1056 Private
->TextOutList
[Index
].UgaDraw
,
1067 if (EFI_ERROR (Status
)) {
1068 ReturnStatus
= Status
;
1069 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1071 // Only need to read the data into buffer one time
1078 return ReturnStatus
;
1083 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1084 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1085 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1088 if (UgaDraw
!= NULL
) {
1089 return UgaDraw
->Blt (
1092 EfiUgaBltBufferToVideo
,
1097 Private
->UgaHorizontalResolution
,
1098 Private
->UgaVerticalResolution
,
1099 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1102 return GraphicsOutput
->Blt (
1104 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1105 EfiBltBufferToVideo
,
1110 Private
->UgaHorizontalResolution
,
1111 Private
->UgaVerticalResolution
,
1118 DevNullTextOutOutputString (
1119 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1124 Routine Description:
1125 Write a Unicode string to the output device.
1128 Private - Pointer to the console output splitter's private data. It
1129 indicates the calling context.
1130 WString - The NULL-terminated Unicode string to be displayed on the output
1131 device(s). All output devices must also support the Unicode
1132 drawing defined in this file.
1135 EFI_SUCCESS - The string was output to the device.
1136 EFI_DEVICE_ERROR - The device reported an error while attempting to
1138 EFI_UNSUPPORTED - The output device's mode is not currently in a
1140 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1141 characters in the Unicode string could not be
1142 rendered and were skipped.
1147 UINTN SizeAttribute
;
1149 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1156 INT32
*NullAttributes
;
1161 Mode
= &Private
->TextOutMode
;
1162 NullScreen
= Private
->DevNullScreen
;
1163 NullAttributes
= Private
->DevNullAttributes
;
1164 LastRow
= Private
->DevNullRows
- 1;
1165 MaxColumn
= Private
->DevNullColumns
;
1167 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1175 if (*WString
== CHAR_BACKSPACE
) {
1177 // If the cursor is at the left edge of the display, then move the cursor
1180 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1182 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1186 // If the cursor is not at the left edge of the display,
1187 // then move the cursor left one column.
1189 if (Mode
->CursorColumn
> 0) {
1190 Mode
->CursorColumn
--;
1191 if (Mode
->CursorColumn
> 0 &&
1192 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1194 Mode
->CursorColumn
--;
1197 // Insert an extra backspace
1199 InsertChar
= CHAR_BACKSPACE
;
1204 InsertChar
= TempChar
;
1217 } else if (*WString
== CHAR_LINEFEED
) {
1219 // If the cursor is at the bottom of the display,
1220 // then scroll the display one row, and do not update
1221 // the cursor position. Otherwise, move the cursor down one row.
1223 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1225 // Scroll Screen Up One Row
1227 SizeAttribute
= LastRow
* MaxColumn
;
1230 NullAttributes
+ MaxColumn
,
1231 SizeAttribute
* sizeof (INT32
)
1235 // Each row has an ending CHAR_NULL. So one more character each line
1236 // for DevNullScreen than DevNullAttributes
1238 SizeScreen
= SizeAttribute
+ LastRow
;
1241 NullScreen
+ (MaxColumn
+ 1),
1242 SizeScreen
* sizeof (CHAR16
)
1246 // Print Blank Line at last line
1248 Screen
= NullScreen
+ SizeScreen
;
1249 Attribute
= NullAttributes
+ SizeAttribute
;
1251 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1253 *Attribute
= Mode
->Attribute
;
1260 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1262 // Move the cursor to the beginning of the current row.
1264 Mode
->CursorColumn
= 0;
1268 // Print the character at the current cursor position and
1269 // move the cursor right one column. If this moves the cursor
1270 // past the right edge of the display, then the line should wrap to
1271 // the beginning of the next line. This is equivalent to inserting
1272 // a CR and an LF. Note that if the cursor is at the bottom of the
1273 // display, and the line wraps, then the display will be scrolled
1276 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1278 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1279 if (*WString
== CHAR_NULL
) {
1283 if (*WString
== CHAR_BACKSPACE
) {
1287 if (*WString
== CHAR_LINEFEED
) {
1291 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1295 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1296 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1301 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1303 // If a wide char is at the rightmost column, then move the char
1304 // to the beginning of the next row
1306 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1307 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1309 Mode
->CursorColumn
++;
1311 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1312 NullAttributes
[Index
] = Mode
->Attribute
;
1313 if (CurrentWidth
== 1) {
1314 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1316 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1317 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1320 Index
+= CurrentWidth
;
1322 Mode
->CursorColumn
+= CurrentWidth
;
1326 // At the end of line, output carriage return and line feed
1328 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1329 DevNullTextOutOutputString (Private
, mCrLfString
);
1338 DevNullTextOutSetMode (
1339 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1344 Routine Description:
1345 Sets the output device(s) to a specified mode.
1348 Private - Private data structure pointer.
1349 ModeNumber - The mode number to set.
1352 EFI_SUCCESS - The requested text mode was set.
1353 EFI_DEVICE_ERROR - The device had an error and
1354 could not complete the request.
1355 EFI_UNSUPPORTED - The mode number was not valid.
1356 EFI_OUT_OF_RESOURCES - Out of resources.
1363 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1366 // No extra check for ModeNumber here, as it has been checked in
1367 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1369 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1371 Column
= Mode
->Columns
;
1373 if (Row
<= 0 && Column
<= 0) {
1374 return EFI_UNSUPPORTED
;
1377 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1379 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1380 Private
->DevNullColumns
= Column
;
1381 Private
->DevNullRows
= Row
;
1383 if (Private
->DevNullScreen
!= NULL
) {
1384 FreePool (Private
->DevNullScreen
);
1387 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1388 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1389 if (Private
->DevNullScreen
== NULL
) {
1390 return EFI_OUT_OF_RESOURCES
;
1393 if (Private
->DevNullAttributes
!= NULL
) {
1394 FreePool (Private
->DevNullAttributes
);
1397 Size
= Row
* Column
* sizeof (INT32
);
1398 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1399 if (Private
->DevNullAttributes
== NULL
) {
1400 return EFI_OUT_OF_RESOURCES
;
1404 DevNullTextOutClearScreen (Private
);
1410 DevNullTextOutClearScreen (
1411 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1415 Routine Description:
1416 Clears the output device(s) display to the currently selected background
1420 Private - Protocol instance pointer.
1423 EFI_SUCCESS - The operation completed successfully.
1424 EFI_DEVICE_ERROR - The device had an error and
1425 could not complete the request.
1426 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1434 INT32 CurrentAttribute
;
1437 // Clear the DevNull Text Out Buffers.
1438 // The screen is filled with spaces.
1439 // The attributes are all synced with the current Simple Text Out Attribute
1441 Screen
= Private
->DevNullScreen
;
1442 Attributes
= Private
->DevNullAttributes
;
1443 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1445 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1446 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1448 *Attributes
= CurrentAttribute
;
1451 // Each line of the screen has a NULL on the end so we must skip over it
1456 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1458 return DevNullTextOutEnableCursor (Private
, TRUE
);
1462 DevNullTextOutSetCursorPosition (
1463 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1469 Routine Description:
1470 Sets the current coordinates of the cursor position
1473 Private - Protocol instance pointer.
1474 Column, Row - the position to set the cursor to. Must be greater than or
1475 equal to zero and less than the number of columns and rows
1479 EFI_SUCCESS - The operation completed successfully.
1480 EFI_DEVICE_ERROR - The device had an error and
1481 could not complete the request.
1482 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1483 cursor position is invalid for the current mode.
1488 // No need to do extra check here as whether (Column, Row) is valid has
1489 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1490 // always be supported.
1492 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1493 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1499 DevNullTextOutEnableCursor (
1500 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1504 Routine Description:
1506 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1507 In this driver, the cursor cannot be hidden.
1511 Private - Indicates the calling context.
1513 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1514 is set to be invisible.
1518 EFI_SUCCESS - The request is valid.
1523 Private
->TextOutMode
.CursorVisible
= Visible
;
1529 DevNullSyncGopStdOut (
1530 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1533 Routine Description:
1534 Take the DevNull TextOut device and update the Simple Text Out on every
1538 Private - Indicates the calling context.
1541 EFI_SUCCESS - The request is valid.
1542 other - Return status of TextOut->OutputString ()
1547 EFI_STATUS ReturnStatus
;
1552 UINTN CurrentColumn
;
1555 INT32 StartAttribute
;
1556 BOOLEAN StartCursorState
;
1561 CHAR16
*ScreenStart
;
1562 INT32 CurrentAttribute
;
1564 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1567 // Save the devices Attributes, Cursor enable state and location
1569 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1570 StartRow
= Private
->TextOutMode
.CursorRow
;
1571 StartAttribute
= Private
->TextOutMode
.Attribute
;
1572 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1574 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1576 Sto
= Private
->TextOutList
[List
].TextOut
;
1579 // Skip non GOP/UGA devices
1581 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1582 Sto
->EnableCursor (Sto
, FALSE
);
1583 Sto
->ClearScreen (Sto
);
1587 ReturnStatus
= EFI_SUCCESS
;
1588 Screen
= Private
->DevNullScreen
;
1589 Attributes
= Private
->DevNullAttributes
;
1590 MaxColumn
= Private
->DevNullColumns
;
1592 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1593 if (Buffer
== NULL
) {
1594 return ReturnStatus
;
1597 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1599 if (Row
== (Private
->DevNullRows
- 1)) {
1601 // Don't ever sync the last character as it will scroll the screen
1603 Screen
[MaxColumn
- 1] = 0x00;
1607 while (Column
< MaxColumn
) {
1608 if (Screen
[Column
]) {
1609 CurrentAttribute
= Attributes
[Column
];
1610 CurrentColumn
= Column
;
1611 ScreenStart
= &Screen
[Column
];
1614 // the line end is alway 0x0. So Column should be less than MaxColumn
1615 // It should be still in the same row
1617 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1619 if (Attributes
[Column
] != CurrentAttribute
) {
1626 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1634 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1636 Sto
= Private
->TextOutList
[List
].TextOut
;
1639 // Skip non GOP/UGA devices
1641 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1642 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1643 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1644 Status
= Sto
->OutputString (Sto
, Buffer
);
1645 if (EFI_ERROR (Status
)) {
1646 ReturnStatus
= Status
;
1657 // Restore the devices Attributes, Cursor enable state and location
1659 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1660 Sto
= Private
->TextOutList
[List
].TextOut
;
1663 // Skip non GOP/UGA devices
1665 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1666 Sto
->SetAttribute (Sto
, StartAttribute
);
1667 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1668 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1669 if (EFI_ERROR (Status
)) {
1670 ReturnStatus
= Status
;
1677 return ReturnStatus
;