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
)) {
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
) {
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
,
632 return UgaDraw
->Blt (
634 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
635 EfiUgaBltBufferToVideo
,
640 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
641 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
649 ConSpliterUgaDrawGetMode (
650 IN EFI_UGA_DRAW_PROTOCOL
*This
,
651 OUT UINT32
*HorizontalResolution
,
652 OUT UINT32
*VerticalResolution
,
653 OUT UINT32
*ColorDepth
,
654 OUT UINT32
*RefreshRate
659 Return the current video mode information.
662 This - Protocol instance pointer.
663 HorizontalResolution - Current video horizontal resolution in pixels
664 VerticalResolution - Current video vertical resolution in pixels
665 ColorDepth - Current video color depth in bits per pixel
666 RefreshRate - Current video refresh rate in Hz.
669 EFI_SUCCESS - Mode information returned.
670 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
671 EFI_INVALID_PARAMETER - One of the input args was NULL.
675 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
677 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
678 return EFI_INVALID_PARAMETER
;
681 // retrieve private data
683 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
685 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
686 *VerticalResolution
= Private
->UgaVerticalResolution
;
687 *ColorDepth
= Private
->UgaColorDepth
;
688 *RefreshRate
= Private
->UgaRefreshRate
;
695 ConSpliterUgaDrawSetMode (
696 IN EFI_UGA_DRAW_PROTOCOL
*This
,
697 IN UINT32 HorizontalResolution
,
698 IN UINT32 VerticalResolution
,
699 IN UINT32 ColorDepth
,
700 IN UINT32 RefreshRate
705 Return the current video mode information.
708 This - Protocol instance pointer.
709 HorizontalResolution - Current video horizontal resolution in pixels
710 VerticalResolution - Current video vertical resolution in pixels
711 ColorDepth - Current video color depth in bits per pixel
712 RefreshRate - Current video refresh rate in Hz.
715 EFI_SUCCESS - Mode information returned.
716 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
717 EFI_OUT_OF_RESOURCES - Out of resources.
722 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
724 EFI_STATUS ReturnStatus
;
726 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
729 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
730 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
732 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
735 // UgaDevNullSetMode ()
737 ReturnStatus
= EFI_SUCCESS
;
740 // Free the old version
742 if (Private
->UgaBlt
!= NULL
) {
743 FreePool (Private
->UgaBlt
);
747 // Allocate the virtual Blt buffer
749 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
750 Private
->UgaBlt
= AllocateZeroPool (Size
);
751 if (Private
->UgaBlt
== NULL
) {
752 return EFI_OUT_OF_RESOURCES
;
756 // Update the Mode data
758 Private
->UgaHorizontalResolution
= HorizontalResolution
;
759 Private
->UgaVerticalResolution
= VerticalResolution
;
760 Private
->UgaColorDepth
= ColorDepth
;
761 Private
->UgaRefreshRate
= RefreshRate
;
763 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
767 // return the worst status met
769 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
770 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
771 if (UgaDraw
!= NULL
) {
772 Status
= UgaDraw
->SetMode (
774 HorizontalResolution
,
779 if (EFI_ERROR (Status
)) {
780 ReturnStatus
= Status
;
784 if (EFI_ERROR (ReturnStatus
)) {
785 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
786 if (GraphicsOutput
!= NULL
) {
788 // Find corresponding ModeNumber of this GraphicsOutput instance
790 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
791 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
792 if (EFI_ERROR (Status
)) {
795 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
802 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
803 if (EFI_ERROR (Status
)) {
804 ReturnStatus
= Status
;
815 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
816 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
817 IN EFI_UGA_BLT_OPERATION BltOperation
,
820 IN UINTN DestinationX
,
821 IN UINTN DestinationY
,
824 IN UINTN Delta OPTIONAL
830 EFI_UGA_PIXEL
*BltPtr
;
831 EFI_UGA_PIXEL
*ScreenPtr
;
832 UINT32 HorizontalResolution
;
833 UINT32 VerticalResolution
;
835 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
836 return EFI_INVALID_PARAMETER
;
839 if (Width
== 0 || Height
== 0) {
840 return EFI_INVALID_PARAMETER
;
844 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
847 HorizontalResolution
= Private
->UgaHorizontalResolution
;
848 VerticalResolution
= Private
->UgaVerticalResolution
;
851 // We need to fill the Virtual Screen buffer with the blt data.
853 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
855 // Video to BltBuffer: Source is Video, destination is BltBuffer
857 if ((SourceY
+ Height
) > VerticalResolution
) {
858 return EFI_INVALID_PARAMETER
;
861 if ((SourceX
+ Width
) > HorizontalResolution
) {
862 return EFI_INVALID_PARAMETER
;
865 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
866 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
868 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
869 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
870 ScreenPtr
+= HorizontalResolution
;
875 // BltBuffer to Video: Source is BltBuffer, destination is Video
877 if (DestinationY
+ Height
> VerticalResolution
) {
878 return EFI_INVALID_PARAMETER
;
881 if (DestinationX
+ Width
> HorizontalResolution
) {
882 return EFI_INVALID_PARAMETER
;
885 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
887 // Copy backwards, only care the Video to Video Blt
889 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
890 SrcY
= SourceY
+ Height
- 1;
894 // Copy forwards, for other cases
896 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
901 while (Height
!= 0) {
902 if (BltOperation
== EfiUgaVideoFill
) {
903 for (Index
= 0; Index
< Width
; Index
++) {
904 ScreenPtr
[Index
] = *BltBuffer
;
907 if (BltOperation
== EfiUgaBltBufferToVideo
) {
908 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
910 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
913 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
917 ScreenPtr
+= HorizontalResolution
;
920 ScreenPtr
-= HorizontalResolution
;
932 ConSpliterUgaDrawBlt (
933 IN EFI_UGA_DRAW_PROTOCOL
*This
,
934 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
935 IN EFI_UGA_BLT_OPERATION BltOperation
,
938 IN UINTN DestinationX
,
939 IN UINTN DestinationY
,
942 IN UINTN Delta OPTIONAL
947 The following table defines actions for BltOperations:
948 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
949 directly to every pixel of the video display rectangle
950 (DestinationX, DestinationY)
951 (DestinationX + Width, DestinationY + Height).
952 Only one pixel will be used from the BltBuffer. Delta is NOT used.
953 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
954 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
955 the BltBuffer rectangle (DestinationX, DestinationY )
956 (DestinationX + Width, DestinationY + Height). If DestinationX or
957 DestinationY is not zero then Delta must be set to the length in bytes
958 of a row in the BltBuffer.
959 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
960 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
961 video display rectangle (DestinationX, DestinationY)
962 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
963 not zero then Delta must be set to the length in bytes of a row in the
965 EfiUgaVideoToVideo - Copy from the video display rectangle
966 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
967 to the video display rectangle (DestinationX, DestinationY)
968 (DestinationX + Width, DestinationY + Height).
969 The BltBuffer and Delta are not used in this mode.
972 This - Protocol instance pointer.
973 BltBuffer - Buffer containing data to blit into video buffer. This
974 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
975 BltOperation - Operation to perform on BlitBuffer and video memory
976 SourceX - X coordinate of source for the BltBuffer.
977 SourceY - Y coordinate of source for the BltBuffer.
978 DestinationX - X coordinate of destination for the BltBuffer.
979 DestinationY - Y coordinate of destination for the BltBuffer.
980 Width - Width of rectangle in BltBuffer in pixels.
981 Height - Hight of rectangle in BltBuffer in pixels.
985 EFI_SUCCESS - The Blt operation completed.
986 EFI_INVALID_PARAMETER - BltOperation is not valid.
987 EFI_DEVICE_ERROR - A hardware error occured writting to the video
993 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
995 EFI_STATUS ReturnStatus
;
996 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
998 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
1001 // Sync up DevNull UGA device
1003 ReturnStatus
= DevNullUgaBlt (
1015 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1016 return ReturnStatus
;
1019 // return the worst status met
1021 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1022 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1023 if (GraphicsOutput
!= NULL
) {
1024 Status
= GraphicsOutput
->Blt (
1026 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1027 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1036 if (EFI_ERROR (Status
)) {
1037 ReturnStatus
= Status
;
1038 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1040 // Only need to read the data into buffer one time
1046 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
1047 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1048 Private
->TextOutList
[Index
].UgaDraw
,
1059 if (EFI_ERROR (Status
)) {
1060 ReturnStatus
= Status
;
1061 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1063 // Only need to read the data into buffer one time
1070 return ReturnStatus
;
1075 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1076 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1077 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1080 if (UgaDraw
!= NULL
) {
1081 return UgaDraw
->Blt (
1084 EfiUgaBltBufferToVideo
,
1089 Private
->UgaHorizontalResolution
,
1090 Private
->UgaVerticalResolution
,
1091 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1094 return GraphicsOutput
->Blt (
1096 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1097 EfiBltBufferToVideo
,
1102 Private
->UgaHorizontalResolution
,
1103 Private
->UgaVerticalResolution
,
1110 DevNullTextOutOutputString (
1111 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1116 Routine Description:
1117 Write a Unicode string to the output device.
1120 Private - Pointer to the console output splitter's private data. It
1121 indicates the calling context.
1122 WString - The NULL-terminated Unicode string to be displayed on the output
1123 device(s). All output devices must also support the Unicode
1124 drawing defined in this file.
1127 EFI_SUCCESS - The string was output to the device.
1128 EFI_DEVICE_ERROR - The device reported an error while attempting to
1130 EFI_UNSUPPORTED - The output device's mode is not currently in a
1132 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1133 characters in the Unicode string could not be
1134 rendered and were skipped.
1139 UINTN SizeAttribute
;
1141 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1148 INT32
*NullAttributes
;
1153 Mode
= &Private
->TextOutMode
;
1154 NullScreen
= Private
->DevNullScreen
;
1155 NullAttributes
= Private
->DevNullAttributes
;
1156 LastRow
= Private
->DevNullRows
- 1;
1157 MaxColumn
= Private
->DevNullColumns
;
1159 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1167 if (*WString
== CHAR_BACKSPACE
) {
1169 // If the cursor is at the left edge of the display, then move the cursor
1172 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1174 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1178 // If the cursor is not at the left edge of the display,
1179 // then move the cursor left one column.
1181 if (Mode
->CursorColumn
> 0) {
1182 Mode
->CursorColumn
--;
1183 if (Mode
->CursorColumn
> 0 &&
1184 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1186 Mode
->CursorColumn
--;
1189 // Insert an extra backspace
1191 InsertChar
= CHAR_BACKSPACE
;
1196 InsertChar
= TempChar
;
1209 } else if (*WString
== CHAR_LINEFEED
) {
1211 // If the cursor is at the bottom of the display,
1212 // then scroll the display one row, and do not update
1213 // the cursor position. Otherwise, move the cursor down one row.
1215 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1217 // Scroll Screen Up One Row
1219 SizeAttribute
= LastRow
* MaxColumn
;
1222 NullAttributes
+ MaxColumn
,
1223 SizeAttribute
* sizeof (INT32
)
1227 // Each row has an ending CHAR_NULL. So one more character each line
1228 // for DevNullScreen than DevNullAttributes
1230 SizeScreen
= SizeAttribute
+ LastRow
;
1233 NullScreen
+ (MaxColumn
+ 1),
1234 SizeScreen
* sizeof (CHAR16
)
1238 // Print Blank Line at last line
1240 Screen
= NullScreen
+ SizeScreen
;
1241 Attribute
= NullAttributes
+ SizeAttribute
;
1243 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1245 *Attribute
= Mode
->Attribute
;
1252 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1254 // Move the cursor to the beginning of the current row.
1256 Mode
->CursorColumn
= 0;
1260 // Print the character at the current cursor position and
1261 // move the cursor right one column. If this moves the cursor
1262 // past the right edge of the display, then the line should wrap to
1263 // the beginning of the next line. This is equivalent to inserting
1264 // a CR and an LF. Note that if the cursor is at the bottom of the
1265 // display, and the line wraps, then the display will be scrolled
1268 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1270 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1271 if (*WString
== CHAR_NULL
) {
1275 if (*WString
== CHAR_BACKSPACE
) {
1279 if (*WString
== CHAR_LINEFEED
) {
1283 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1287 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1288 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1293 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1295 // If a wide char is at the rightmost column, then move the char
1296 // to the beginning of the next row
1298 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1299 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1301 Mode
->CursorColumn
++;
1303 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1304 NullAttributes
[Index
] = Mode
->Attribute
;
1305 if (CurrentWidth
== 1) {
1306 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1308 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1309 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1312 Index
+= CurrentWidth
;
1314 Mode
->CursorColumn
+= CurrentWidth
;
1318 // At the end of line, output carriage return and line feed
1320 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1321 DevNullTextOutOutputString (Private
, mCrLfString
);
1330 DevNullTextOutSetMode (
1331 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1336 Routine Description:
1337 Sets the output device(s) to a specified mode.
1340 Private - Private data structure pointer.
1341 ModeNumber - The mode number to set.
1344 EFI_SUCCESS - The requested text mode was set.
1345 EFI_DEVICE_ERROR - The device had an error and
1346 could not complete the request.
1347 EFI_UNSUPPORTED - The mode number was not valid.
1348 EFI_OUT_OF_RESOURCES - Out of resources.
1355 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1358 // No extra check for ModeNumber here, as it has been checked in
1359 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1361 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1363 Column
= Mode
->Columns
;
1365 if (Row
<= 0 && Column
<= 0) {
1366 return EFI_UNSUPPORTED
;
1369 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1371 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1372 Private
->DevNullColumns
= Column
;
1373 Private
->DevNullRows
= Row
;
1375 if (Private
->DevNullScreen
!= NULL
) {
1376 FreePool (Private
->DevNullScreen
);
1379 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1380 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1381 if (Private
->DevNullScreen
== NULL
) {
1382 return EFI_OUT_OF_RESOURCES
;
1385 if (Private
->DevNullAttributes
!= NULL
) {
1386 FreePool (Private
->DevNullAttributes
);
1389 Size
= Row
* Column
* sizeof (INT32
);
1390 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1391 if (Private
->DevNullAttributes
== NULL
) {
1392 return EFI_OUT_OF_RESOURCES
;
1396 DevNullTextOutClearScreen (Private
);
1402 DevNullTextOutClearScreen (
1403 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1407 Routine Description:
1408 Clears the output device(s) display to the currently selected background
1412 Private - Protocol instance pointer.
1415 EFI_SUCCESS - The operation completed successfully.
1416 EFI_DEVICE_ERROR - The device had an error and
1417 could not complete the request.
1418 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1426 INT32 CurrentAttribute
;
1429 // Clear the DevNull Text Out Buffers.
1430 // The screen is filled with spaces.
1431 // The attributes are all synced with the current Simple Text Out Attribute
1433 Screen
= Private
->DevNullScreen
;
1434 Attributes
= Private
->DevNullAttributes
;
1435 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1437 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1438 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1440 *Attributes
= CurrentAttribute
;
1443 // Each line of the screen has a NULL on the end so we must skip over it
1448 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1450 return DevNullTextOutEnableCursor (Private
, TRUE
);
1454 DevNullTextOutSetCursorPosition (
1455 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1461 Routine Description:
1462 Sets the current coordinates of the cursor position
1465 Private - Protocol instance pointer.
1466 Column, Row - the position to set the cursor to. Must be greater than or
1467 equal to zero and less than the number of columns and rows
1471 EFI_SUCCESS - The operation completed successfully.
1472 EFI_DEVICE_ERROR - The device had an error and
1473 could not complete the request.
1474 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1475 cursor position is invalid for the current mode.
1480 // No need to do extra check here as whether (Column, Row) is valid has
1481 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1482 // always be supported.
1484 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1485 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1491 DevNullTextOutEnableCursor (
1492 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1496 Routine Description:
1498 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1499 In this driver, the cursor cannot be hidden.
1503 Private - Indicates the calling context.
1505 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1506 is set to be invisible.
1510 EFI_SUCCESS - The request is valid.
1515 Private
->TextOutMode
.CursorVisible
= Visible
;
1522 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1525 Routine Description:
1526 Take the DevNull TextOut device and update the Simple Text Out on every
1530 Private - Indicates the calling context.
1533 EFI_SUCCESS - The request is valid.
1534 other - Return status of TextOut->OutputString ()
1539 EFI_STATUS ReturnStatus
;
1544 UINTN CurrentColumn
;
1547 INT32 StartAttribute
;
1548 BOOLEAN StartCursorState
;
1553 CHAR16
*ScreenStart
;
1554 INT32 CurrentAttribute
;
1556 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1559 // Save the devices Attributes, Cursor enable state and location
1561 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1562 StartRow
= Private
->TextOutMode
.CursorRow
;
1563 StartAttribute
= Private
->TextOutMode
.Attribute
;
1564 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1566 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1568 Sto
= Private
->TextOutList
[List
].TextOut
;
1571 // Skip non GOP/UGA devices
1573 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1574 Sto
->EnableCursor (Sto
, FALSE
);
1575 Sto
->ClearScreen (Sto
);
1579 ReturnStatus
= EFI_SUCCESS
;
1580 Screen
= Private
->DevNullScreen
;
1581 Attributes
= Private
->DevNullAttributes
;
1582 MaxColumn
= Private
->DevNullColumns
;
1584 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1585 if (Buffer
== NULL
) {
1586 return ReturnStatus
;
1589 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1591 if (Row
== (Private
->DevNullRows
- 1)) {
1593 // Don't ever sync the last character as it will scroll the screen
1595 Screen
[MaxColumn
- 1] = 0x00;
1599 while (Column
< MaxColumn
) {
1600 if (Screen
[Column
]) {
1601 CurrentAttribute
= Attributes
[Column
];
1602 CurrentColumn
= Column
;
1603 ScreenStart
= &Screen
[Column
];
1606 // the line end is alway 0x0. So Column should be less than MaxColumn
1607 // It should be still in the same row
1609 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1611 if (Attributes
[Column
] != CurrentAttribute
) {
1618 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1626 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1628 Sto
= Private
->TextOutList
[List
].TextOut
;
1631 // Skip non GOP/UGA devices
1633 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1634 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1635 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1636 Status
= Sto
->OutputString (Sto
, Buffer
);
1637 if (EFI_ERROR (Status
)) {
1638 ReturnStatus
= Status
;
1649 // Restore the devices Attributes, Cursor enable state and location
1651 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1652 Sto
= Private
->TextOutList
[List
].TextOut
;
1655 // Skip non GOP/UGA devices
1657 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1658 Sto
->SetAttribute (Sto
, StartAttribute
);
1659 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1660 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1661 if (EFI_ERROR (Status
)) {
1662 ReturnStatus
= Status
;
1669 return ReturnStatus
;