2 Support for ConsoleControl protocol. Support for Graphics output spliter.
3 Support for DevNull Console Out. This console uses memory buffers
4 to represnt the console. It allows a console to start very early and
5 when a new console is added it is synced up with the current console.
7 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "ConSplitter.h"
23 STATIC CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
27 Return the current video mode information. Also returns info about existence
28 of Graphics Output devices or UGA Draw devices in system, and if the Std In device is locked. All the
29 arguments are optional and only returned if a non NULL pointer is passed in.
31 @param This Protocol instance pointer.
32 @param Mode Are we in text of grahics mode.
33 @param GopExists TRUE if GOP Spliter has found a GOP/UGA device
34 @param StdInLocked TRUE if StdIn device is keyboard locked
36 @retval EFI_SUCCESS Mode information returned.
37 @retval EFI_INVALID_PARAMETER Invalid parameters.
42 ConSpliterConsoleControlGetMode (
43 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
44 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE
*Mode
,
45 OUT BOOLEAN
*GopExists
,
46 OUT BOOLEAN
*StdInLocked
49 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
52 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
55 return EFI_INVALID_PARAMETER
;
58 *Mode
= Private
->ConsoleOutputMode
;
60 if (GopExists
!= NULL
) {
62 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
63 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
70 if (StdInLocked
!= NULL
) {
71 *StdInLocked
= ConSpliterConssoleControlStdInLocked ();
79 Set the current mode to either text or graphics. Graphics is
82 @param This Protocol instance pointer.
83 @param Mode Mode to set the
85 @retval EFI_SUCCESS Mode information returned.
86 @retval EFI_INVALID_PARAMETER Invalid parameter.
87 @retval EFI_UNSUPPORTED Operation unsupported.
92 ConSpliterConsoleControlSetMode (
93 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
94 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
97 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
99 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
102 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
104 if (Mode
>= EfiConsoleControlScreenMaxValue
) {
105 return EFI_INVALID_PARAMETER
;
109 // Judge current mode with wanted mode at first.
111 if (Private
->ConsoleOutputMode
== Mode
) {
116 TextAndGop
= &Private
->TextOutList
[0];
117 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
118 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
124 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
125 return EFI_UNSUPPORTED
;
128 Private
->ConsoleOutputMode
= Mode
;
130 TextAndGop
= &Private
->TextOutList
[0];
131 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
133 TextAndGop
->TextOutEnabled
= TRUE
;
135 // If we are going into Graphics mode disable ConOut to any UGA device
137 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
138 TextAndGop
->TextOutEnabled
= FALSE
;
139 if (FeaturePcdGet (PcdConOutGopSupport
)) {
140 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
141 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
142 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
146 if (Mode
== EfiConsoleControlScreenText
) {
147 DevNullSyncStdOut (Private
);
154 Return the current video mode information.
156 @param This Protocol instance pointer.
157 @param ModeNumber The mode number to return information on.
158 @param SizeOfInfo A pointer to the size, in bytes, of the Info
160 @param Info Caller allocated buffer that returns information
163 @retval EFI_SUCCESS Mode information returned.
164 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
165 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
167 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
168 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
173 ConSpliterGraphicsOutputQueryMode (
174 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
175 IN UINT32 ModeNumber
,
176 OUT UINTN
*SizeOfInfo
,
177 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
180 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
182 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
183 return EFI_INVALID_PARAMETER
;
187 // retrieve private data
189 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
191 if (Private
->HardwareNeedsStarting
) {
192 return EFI_NOT_STARTED
;
195 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
198 return EFI_OUT_OF_RESOURCES
;
201 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
203 CopyMem (*Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], *SizeOfInfo
);
210 Graphics output protocol interface to set video mode
212 @param This Protocol instance pointer.
213 @param ModeNumber The mode number to be set.
215 @retval EFI_SUCCESS Graphics mode was changed.
216 @retval EFI_DEVICE_ERROR The device had an error and could not complete
218 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
223 ConSpliterGraphicsOutputSetMode (
224 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
229 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
231 EFI_STATUS ReturnStatus
;
232 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
234 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
237 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
238 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
240 if (ModeNumber
>= This
->Mode
->MaxMode
) {
241 return EFI_UNSUPPORTED
;
244 if (ModeNumber
== This
->Mode
->Mode
) {
248 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
251 // GopDevNullSetMode ()
253 ReturnStatus
= EFI_SUCCESS
;
256 // Free the old version
258 if (Private
->GraphicsOutputBlt
!= NULL
) {
259 FreePool (Private
->GraphicsOutputBlt
);
263 // Allocate the virtual Blt buffer
265 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
266 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
267 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
269 if (Private
->GraphicsOutputBlt
== NULL
) {
270 return EFI_OUT_OF_RESOURCES
;
274 // return the worst status met
276 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
277 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
278 if (GraphicsOutput
!= NULL
) {
280 // Find corresponding ModeNumber of this GraphicsOutput instance
282 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
283 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
284 if (EFI_ERROR (Status
)) {
287 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
294 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
295 if (EFI_ERROR (Status
)) {
296 ReturnStatus
= Status
;
300 if (EFI_ERROR (ReturnStatus
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
301 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
302 if (UgaDraw
!= NULL
) {
303 Status
= UgaDraw
->SetMode (
305 Mode
->HorizontalResolution
,
306 Mode
->VerticalResolution
,
310 if (EFI_ERROR (Status
)) {
311 ReturnStatus
= Status
;
317 This
->Mode
->Mode
= ModeNumber
;
319 CopyMem (This
->Mode
->Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], This
->Mode
->SizeOfInfo
);
322 // Information is not enough here, so the following items remain unchanged:
323 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
324 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
325 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
328 Private
->HardwareNeedsStarting
= FALSE
;
334 DevNullGraphicsOutputBlt (
335 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
336 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
337 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
340 IN UINTN DestinationX
,
341 IN UINTN DestinationY
,
344 IN UINTN Delta OPTIONAL
350 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
351 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
352 UINTN HorizontalResolution
;
353 UINTN VerticalResolution
;
355 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
356 return EFI_INVALID_PARAMETER
;
359 if (Width
== 0 || Height
== 0) {
360 return EFI_INVALID_PARAMETER
;
364 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
367 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
368 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
371 // We need to fill the Virtual Screen buffer with the blt data.
373 if (BltOperation
== EfiBltVideoToBltBuffer
) {
375 // Video to BltBuffer: Source is Video, destination is BltBuffer
377 if ((SourceY
+ Height
) > VerticalResolution
) {
378 return EFI_INVALID_PARAMETER
;
381 if ((SourceX
+ Width
) > HorizontalResolution
) {
382 return EFI_INVALID_PARAMETER
;
385 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
386 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
388 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
389 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
390 ScreenPtr
+= HorizontalResolution
;
395 // BltBuffer to Video: Source is BltBuffer, destination is Video
397 if (DestinationY
+ Height
> VerticalResolution
) {
398 return EFI_INVALID_PARAMETER
;
401 if (DestinationX
+ Width
> HorizontalResolution
) {
402 return EFI_INVALID_PARAMETER
;
405 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
407 // Copy backwards, only care the Video to Video Blt
409 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
410 SrcY
= SourceY
+ Height
- 1;
414 // Copy forwards, for other cases
416 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
421 while (Height
!= 0) {
422 if (BltOperation
== EfiBltVideoFill
) {
423 for (Index
= 0; Index
< Width
; Index
++) {
424 ScreenPtr
[Index
] = *BltBuffer
;
427 if (BltOperation
== EfiBltBufferToVideo
) {
428 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
430 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
433 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
437 ScreenPtr
+= HorizontalResolution
;
440 ScreenPtr
-= HorizontalResolution
;
452 The following table defines actions for BltOperations.
454 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
455 directly to every pixel of the video display rectangle
456 (DestinationX, DestinationY)
457 (DestinationX + Width, DestinationY + Height).
458 Only one pixel will be used from the BltBuffer. Delta is NOT used.
459 EfiBltVideoToBltBuffer - Read data from the video display rectangle
460 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
461 the BltBuffer rectangle (DestinationX, DestinationY )
462 (DestinationX + Width, DestinationY + Height). If DestinationX or
463 DestinationY is not zero then Delta must be set to the length in bytes
464 of a row in the BltBuffer.
465 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
466 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
467 video display rectangle (DestinationX, DestinationY)
468 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
469 not zero then Delta must be set to the length in bytes of a row in the
471 EfiBltVideoToVideo - Copy from the video display rectangle
472 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
473 to the video display rectangle (DestinationX, DestinationY)
474 (DestinationX + Width, DestinationY + Height).
475 The BltBuffer and Delta are not used in this mode.
477 @param This Protocol instance pointer.
478 @param BltBuffer Buffer containing data to blit into video buffer.
479 This buffer has a size of
480 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
481 @param BltOperation Operation to perform on BlitBuffer and video
483 @param SourceX X coordinate of source for the BltBuffer.
484 @param SourceY Y coordinate of source for the BltBuffer.
485 @param DestinationX X coordinate of destination for the BltBuffer.
486 @param DestinationY Y coordinate of destination for the BltBuffer.
487 @param Width Width of rectangle in BltBuffer in pixels.
488 @param Height Hight of rectangle in BltBuffer in pixels.
489 @param Delta (not used here).
491 @retval EFI_SUCCESS The Blt operation completed.
492 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
493 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
499 ConSpliterGraphicsOutputBlt (
500 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
501 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
502 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
505 IN UINTN DestinationX
,
506 IN UINTN DestinationY
,
509 IN UINTN Delta OPTIONAL
513 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
515 EFI_STATUS ReturnStatus
;
516 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
517 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
519 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
522 // Sync up DevNull GOP device
524 ReturnStatus
= DevNullGraphicsOutputBlt (
537 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
541 // return the worst status met
543 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
544 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
545 if (GraphicsOutput
!= NULL
) {
546 Status
= GraphicsOutput
->Blt (
558 if (EFI_ERROR (Status
)) {
559 ReturnStatus
= Status
;
560 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
562 // Only need to read the data into buffer one time
568 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
569 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
570 Status
= UgaDraw
->Blt (
572 (EFI_UGA_PIXEL
*) BltBuffer
,
573 (EFI_UGA_BLT_OPERATION
) BltOperation
,
582 if (EFI_ERROR (Status
)) {
583 ReturnStatus
= Status
;
584 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
586 // Only need to read the data into buffer one time
598 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
599 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
600 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
603 if (GraphicsOutput
!= NULL
) {
604 return GraphicsOutput
->Blt (
606 Private
->GraphicsOutputBlt
,
612 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
613 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
616 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
617 return UgaDraw
->Blt (
619 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
620 EfiUgaBltBufferToVideo
,
625 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
626 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
630 return EFI_UNSUPPORTED
;
636 Return the current video mode information.
638 @param This Protocol instance pointer.
639 @param HorizontalResolution Current video horizontal resolution in pixels
640 @param VerticalResolution Current video vertical resolution in pixels
641 @param ColorDepth Current video color depth in bits per pixel
642 @param RefreshRate Current video refresh rate in Hz.
644 @retval EFI_SUCCESS Mode information returned.
645 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
646 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
651 ConSpliterUgaDrawGetMode (
652 IN EFI_UGA_DRAW_PROTOCOL
*This
,
653 OUT UINT32
*HorizontalResolution
,
654 OUT UINT32
*VerticalResolution
,
655 OUT UINT32
*ColorDepth
,
656 OUT UINT32
*RefreshRate
659 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
661 if ((HorizontalResolution
== NULL
) ||
662 (VerticalResolution
== NULL
) ||
663 (RefreshRate
== NULL
) ||
664 (ColorDepth
== NULL
)) {
665 return EFI_INVALID_PARAMETER
;
668 // retrieve private data
670 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
672 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
673 *VerticalResolution
= Private
->UgaVerticalResolution
;
674 *ColorDepth
= Private
->UgaColorDepth
;
675 *RefreshRate
= Private
->UgaRefreshRate
;
682 Return the current video mode information.
684 @param This Protocol instance pointer.
685 @param HorizontalResolution Current video horizontal resolution in pixels
686 @param VerticalResolution Current video vertical resolution in pixels
687 @param ColorDepth Current video color depth in bits per pixel
688 @param RefreshRate Current video refresh rate in Hz.
690 @retval EFI_SUCCESS Mode information returned.
691 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
692 @retval EFI_OUT_OF_RESOURCES Out of resources.
697 ConSpliterUgaDrawSetMode (
698 IN EFI_UGA_DRAW_PROTOCOL
*This
,
699 IN UINT32 HorizontalResolution
,
700 IN UINT32 VerticalResolution
,
701 IN UINT32 ColorDepth
,
702 IN UINT32 RefreshRate
706 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
708 EFI_STATUS ReturnStatus
;
710 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
713 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
714 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
716 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
719 // UgaDevNullSetMode ()
721 ReturnStatus
= EFI_SUCCESS
;
724 // Free the old version
726 if (Private
->UgaBlt
!= NULL
) {
727 FreePool (Private
->UgaBlt
);
731 // Allocate the virtual Blt buffer
733 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
734 Private
->UgaBlt
= AllocateZeroPool (Size
);
735 if (Private
->UgaBlt
== NULL
) {
736 return EFI_OUT_OF_RESOURCES
;
740 // Update the Mode data
742 Private
->UgaHorizontalResolution
= HorizontalResolution
;
743 Private
->UgaVerticalResolution
= VerticalResolution
;
744 Private
->UgaColorDepth
= ColorDepth
;
745 Private
->UgaRefreshRate
= RefreshRate
;
747 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
751 // return the worst status met
753 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
755 ReturnStatus
= EFI_UNSUPPORTED
;
757 if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
758 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
759 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
760 Status
= UgaDraw
->SetMode (
762 HorizontalResolution
,
767 if (EFI_ERROR (Status
)) {
768 ReturnStatus
= Status
;
773 if (EFI_ERROR (ReturnStatus
)) {
774 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
775 if (GraphicsOutput
!= NULL
) {
777 // Find corresponding ModeNumber of this GraphicsOutput instance
779 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
780 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
781 if (EFI_ERROR (Status
)) {
784 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
791 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
792 if (EFI_ERROR (Status
)) {
793 ReturnStatus
= Status
;
804 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
805 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
806 IN EFI_UGA_BLT_OPERATION BltOperation
,
809 IN UINTN DestinationX
,
810 IN UINTN DestinationY
,
813 IN UINTN Delta OPTIONAL
819 EFI_UGA_PIXEL
*BltPtr
;
820 EFI_UGA_PIXEL
*ScreenPtr
;
821 UINT32 HorizontalResolution
;
822 UINT32 VerticalResolution
;
824 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
825 return EFI_INVALID_PARAMETER
;
828 if (Width
== 0 || Height
== 0) {
829 return EFI_INVALID_PARAMETER
;
833 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
836 HorizontalResolution
= Private
->UgaHorizontalResolution
;
837 VerticalResolution
= Private
->UgaVerticalResolution
;
840 // We need to fill the Virtual Screen buffer with the blt data.
842 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
844 // Video to BltBuffer: Source is Video, destination is BltBuffer
846 if ((SourceY
+ Height
) > VerticalResolution
) {
847 return EFI_INVALID_PARAMETER
;
850 if ((SourceX
+ Width
) > HorizontalResolution
) {
851 return EFI_INVALID_PARAMETER
;
854 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
855 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
857 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
858 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
859 ScreenPtr
+= HorizontalResolution
;
864 // BltBuffer to Video: Source is BltBuffer, destination is Video
866 if (DestinationY
+ Height
> VerticalResolution
) {
867 return EFI_INVALID_PARAMETER
;
870 if (DestinationX
+ Width
> HorizontalResolution
) {
871 return EFI_INVALID_PARAMETER
;
874 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
876 // Copy backwards, only care the Video to Video Blt
878 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
879 SrcY
= SourceY
+ Height
- 1;
883 // Copy forwards, for other cases
885 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
890 while (Height
!= 0) {
891 if (BltOperation
== EfiUgaVideoFill
) {
892 for (Index
= 0; Index
< Width
; Index
++) {
893 ScreenPtr
[Index
] = *BltBuffer
;
896 if (BltOperation
== EfiUgaBltBufferToVideo
) {
897 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
899 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
902 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
906 ScreenPtr
+= HorizontalResolution
;
909 ScreenPtr
-= HorizontalResolution
;
921 The following table defines actions for BltOperations.
923 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
924 directly to every pixel of the video display rectangle
925 (DestinationX, DestinationY)
926 (DestinationX + Width, DestinationY + Height).
927 Only one pixel will be used from the BltBuffer. Delta is NOT used.
928 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
929 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
930 the BltBuffer rectangle (DestinationX, DestinationY )
931 (DestinationX + Width, DestinationY + Height). If DestinationX or
932 DestinationY is not zero then Delta must be set to the length in bytes
933 of a row in the BltBuffer.
934 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
935 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
936 video display rectangle (DestinationX, DestinationY)
937 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
938 not zero then Delta must be set to the length in bytes of a row in the
940 EfiUgaVideoToVideo - Copy from the video display rectangle
941 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
942 to the video display rectangle (DestinationX, DestinationY)
943 (DestinationX + Width, DestinationY + Height).
944 The BltBuffer and Delta are not used in this mode.
946 @param This Protocol instance pointer.
947 @param BltBuffer Buffer containing data to blit into video buffer.
948 This buffer has a size of
949 Width*Height*sizeof(EFI_UGA_PIXEL)
950 @param BltOperation Operation to perform on BlitBuffer and video
952 @param SourceX X coordinate of source for the BltBuffer.
953 @param SourceY Y coordinate of source for the BltBuffer.
954 @param DestinationX X coordinate of destination for the BltBuffer.
955 @param DestinationY Y coordinate of destination for the BltBuffer.
956 @param Width Width of rectangle in BltBuffer in pixels.
957 @param Height Hight of rectangle in BltBuffer in pixels.
958 @param Delta (not used here)
960 @retval EFI_SUCCESS The Blt operation completed.
961 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
962 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
968 ConSpliterUgaDrawBlt (
969 IN EFI_UGA_DRAW_PROTOCOL
*This
,
970 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
971 IN EFI_UGA_BLT_OPERATION BltOperation
,
974 IN UINTN DestinationX
,
975 IN UINTN DestinationY
,
978 IN UINTN Delta OPTIONAL
982 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
984 EFI_STATUS ReturnStatus
;
985 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
987 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
990 // Sync up DevNull UGA device
992 ReturnStatus
= DevNullUgaBlt (
1004 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1005 return ReturnStatus
;
1008 // return the worst status met
1010 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1011 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1012 if (GraphicsOutput
!= NULL
) {
1013 Status
= GraphicsOutput
->Blt (
1015 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1016 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1025 if (EFI_ERROR (Status
)) {
1026 ReturnStatus
= Status
;
1027 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1029 // Only need to read the data into buffer one time
1035 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1036 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1037 Private
->TextOutList
[Index
].UgaDraw
,
1048 if (EFI_ERROR (Status
)) {
1049 ReturnStatus
= Status
;
1050 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1052 // Only need to read the data into buffer one time
1059 return ReturnStatus
;
1064 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1065 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1066 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1069 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1070 return UgaDraw
->Blt (
1073 EfiUgaBltBufferToVideo
,
1078 Private
->UgaHorizontalResolution
,
1079 Private
->UgaVerticalResolution
,
1080 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1082 } else if (GraphicsOutput
!= NULL
) {
1083 return GraphicsOutput
->Blt (
1085 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1086 EfiBltBufferToVideo
,
1091 Private
->UgaHorizontalResolution
,
1092 Private
->UgaVerticalResolution
,
1096 return EFI_UNSUPPORTED
;
1102 Write a Unicode string to the output device.
1104 @param Private Pointer to the console output splitter's private
1105 data. It indicates the calling context.
1106 @param WString The NULL-terminated Unicode string to be
1107 displayed on the output device(s). All output
1108 devices must also support the Unicode drawing
1109 defined in this file.
1111 @retval EFI_SUCCESS The string was output to the device.
1112 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
1114 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
1116 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
1117 characters in the Unicode string could not be
1118 rendered and were skipped.
1122 DevNullTextOutOutputString (
1123 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1128 UINTN SizeAttribute
;
1130 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1137 INT32
*NullAttributes
;
1142 Mode
= &Private
->TextOutMode
;
1143 NullScreen
= Private
->DevNullScreen
;
1144 NullAttributes
= Private
->DevNullAttributes
;
1145 LastRow
= Private
->DevNullRows
- 1;
1146 MaxColumn
= Private
->DevNullColumns
;
1148 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1154 while (*WString
!= L
'\0') {
1156 if (*WString
== CHAR_BACKSPACE
) {
1158 // If the cursor is at the left edge of the display, then move the cursor
1161 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1163 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1167 // If the cursor is not at the left edge of the display,
1168 // then move the cursor left one column.
1170 if (Mode
->CursorColumn
> 0) {
1171 Mode
->CursorColumn
--;
1172 if (Mode
->CursorColumn
> 0 &&
1173 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1175 Mode
->CursorColumn
--;
1178 // Insert an extra backspace
1180 InsertChar
= CHAR_BACKSPACE
;
1182 while (*PStr
!= L
'\0') {
1185 InsertChar
= TempChar
;
1198 } else if (*WString
== CHAR_LINEFEED
) {
1200 // If the cursor is at the bottom of the display,
1201 // then scroll the display one row, and do not update
1202 // the cursor position. Otherwise, move the cursor down one row.
1204 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1206 // Scroll Screen Up One Row
1208 SizeAttribute
= LastRow
* MaxColumn
;
1211 NullAttributes
+ MaxColumn
,
1212 SizeAttribute
* sizeof (INT32
)
1216 // Each row has an ending CHAR_NULL. So one more character each line
1217 // for DevNullScreen than DevNullAttributes
1219 SizeScreen
= SizeAttribute
+ LastRow
;
1222 NullScreen
+ (MaxColumn
+ 1),
1223 SizeScreen
* sizeof (CHAR16
)
1227 // Print Blank Line at last line
1229 Screen
= NullScreen
+ SizeScreen
;
1230 Attribute
= NullAttributes
+ SizeAttribute
;
1232 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1234 *Attribute
= Mode
->Attribute
;
1241 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1243 // Move the cursor to the beginning of the current row.
1245 Mode
->CursorColumn
= 0;
1249 // Print the character at the current cursor position and
1250 // move the cursor right one column. If this moves the cursor
1251 // past the right edge of the display, then the line should wrap to
1252 // the beginning of the next line. This is equivalent to inserting
1253 // a CR and an LF. Note that if the cursor is at the bottom of the
1254 // display, and the line wraps, then the display will be scrolled
1257 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1259 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1260 if (*WString
== CHAR_NULL
) {
1264 if (*WString
== CHAR_BACKSPACE
) {
1268 if (*WString
== CHAR_LINEFEED
) {
1272 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1276 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1277 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1282 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1284 // If a wide char is at the rightmost column, then move the char
1285 // to the beginning of the next row
1287 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1288 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1290 Mode
->CursorColumn
++;
1292 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1293 NullAttributes
[Index
] = Mode
->Attribute
;
1294 if (CurrentWidth
== 1) {
1295 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1297 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1298 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1301 Index
+= CurrentWidth
;
1303 Mode
->CursorColumn
+= CurrentWidth
;
1307 // At the end of line, output carriage return and line feed
1309 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1310 DevNullTextOutOutputString (Private
, mCrLfString
);
1320 Sets the output device(s) to a specified mode.
1322 @param Private Private data structure pointer.
1323 @param ModeNumber The mode number to set.
1325 @retval EFI_SUCCESS The requested text mode was set.
1326 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1328 @retval EFI_UNSUPPORTED The mode number was not valid.
1329 @retval EFI_OUT_OF_RESOURCES Out of resources.
1333 DevNullTextOutSetMode (
1334 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1342 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1345 // No extra check for ModeNumber here, as it has been checked in
1346 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1347 // Row and Column should be fetched from intersection map.
1349 if (Private
->TextOutModeMap
!= NULL
) {
1350 CurrentMode
= *(Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
);
1352 CurrentMode
= (INT32
)(ModeNumber
);
1354 Mode
= &(Private
->TextOutQueryData
[CurrentMode
]);
1356 Column
= Mode
->Columns
;
1358 if (Row
<= 0 && Column
<= 0) {
1359 return EFI_UNSUPPORTED
;
1362 if (Private
->TextOutMode
.Mode
!= (INT32
) ModeNumber
) {
1364 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1365 Private
->DevNullColumns
= Column
;
1366 Private
->DevNullRows
= Row
;
1368 if (Private
->DevNullScreen
!= NULL
) {
1369 FreePool (Private
->DevNullScreen
);
1372 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1373 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1374 if (Private
->DevNullScreen
== NULL
) {
1375 return EFI_OUT_OF_RESOURCES
;
1378 if (Private
->DevNullAttributes
!= NULL
) {
1379 FreePool (Private
->DevNullAttributes
);
1382 Size
= Row
* Column
* sizeof (INT32
);
1383 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1384 if (Private
->DevNullAttributes
== NULL
) {
1385 return EFI_OUT_OF_RESOURCES
;
1389 DevNullTextOutClearScreen (Private
);
1396 Clears the output device(s) display to the currently selected background
1399 @param Private Protocol instance pointer.
1401 @retval EFI_SUCCESS The operation completed successfully.
1402 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1404 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1408 DevNullTextOutClearScreen (
1409 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1416 INT32 CurrentAttribute
;
1419 // Clear the DevNull Text Out Buffers.
1420 // The screen is filled with spaces.
1421 // The attributes are all synced with the current Simple Text Out Attribute
1423 Screen
= Private
->DevNullScreen
;
1424 Attributes
= Private
->DevNullAttributes
;
1425 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1427 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1428 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1430 *Attributes
= CurrentAttribute
;
1433 // Each line of the screen has a NULL on the end so we must skip over it
1438 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1440 return DevNullTextOutEnableCursor (Private
, TRUE
);
1445 Sets the current coordinates of the cursor position.
1447 @param Private Protocol instance pointer.
1449 @param Row the position to set the cursor to. Must be
1450 greater than or equal to zero and less than the
1451 number of columns and rows by QueryMode ().
1453 @retval EFI_SUCCESS The operation completed successfully.
1454 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1456 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or
1457 the cursor position is invalid for the current
1462 DevNullTextOutSetCursorPosition (
1463 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1469 // No need to do extra check here as whether (Column, Row) is valid has
1470 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1471 // always be supported.
1473 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1474 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1481 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1482 In this driver, the cursor cannot be hidden.
1484 @param Private Indicates the calling context.
1485 @param Visible If TRUE, the cursor is set to be visible, If
1486 FALSE, the cursor is set to be invisible.
1488 @retval EFI_SUCCESS The request is valid.
1492 DevNullTextOutEnableCursor (
1493 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1497 Private
->TextOutMode
.CursorVisible
= Visible
;
1504 Take the DevNull TextOut device and update the Simple Text Out on every
1507 @param Private Indicates the calling context.
1509 @retval EFI_SUCCESS The request is valid.
1510 @retval other Return status of TextOut->OutputString ()
1515 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1519 EFI_STATUS ReturnStatus
;
1524 UINTN CurrentColumn
;
1527 INT32 StartAttribute
;
1528 BOOLEAN StartCursorState
;
1533 CHAR16
*ScreenStart
;
1534 INT32 CurrentAttribute
;
1536 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1539 // Save the devices Attributes, Cursor enable state and location
1541 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1542 StartRow
= Private
->TextOutMode
.CursorRow
;
1543 StartAttribute
= Private
->TextOutMode
.Attribute
;
1544 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1546 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1548 Sto
= Private
->TextOutList
[List
].TextOut
;
1551 // Skip non GOP/UGA devices
1553 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1554 Sto
->EnableCursor (Sto
, FALSE
);
1555 Sto
->ClearScreen (Sto
);
1559 ReturnStatus
= EFI_SUCCESS
;
1560 Screen
= Private
->DevNullScreen
;
1561 Attributes
= Private
->DevNullAttributes
;
1562 MaxColumn
= Private
->DevNullColumns
;
1564 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1565 if (Buffer
== NULL
) {
1566 return ReturnStatus
;
1569 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1571 if (Row
== (Private
->DevNullRows
- 1)) {
1573 // Don't ever sync the last character as it will scroll the screen
1575 Screen
[MaxColumn
- 1] = 0x00;
1579 while (Column
< MaxColumn
) {
1580 if (Screen
[Column
] > 0) {
1581 CurrentAttribute
= Attributes
[Column
];
1582 CurrentColumn
= Column
;
1583 ScreenStart
= &Screen
[Column
];
1586 // the line end is alway 0x0. So Column should be less than MaxColumn
1587 // It should be still in the same row
1589 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1591 if (Attributes
[Column
] != CurrentAttribute
) {
1598 if ((Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) != 0) {
1606 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1608 Sto
= Private
->TextOutList
[List
].TextOut
;
1611 // Skip non GOP/UGA devices
1613 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1614 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1615 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1616 Status
= Sto
->OutputString (Sto
, Buffer
);
1617 if (EFI_ERROR (Status
)) {
1618 ReturnStatus
= Status
;
1629 // Restore the devices Attributes, Cursor enable state and location
1631 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1632 Sto
= Private
->TextOutList
[List
].TextOut
;
1635 // Skip non GOP/UGA devices
1637 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1638 Sto
->SetAttribute (Sto
, StartAttribute
);
1639 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1640 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1641 if (EFI_ERROR (Status
)) {
1642 ReturnStatus
= Status
;
1649 return ReturnStatus
;