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.
19 #include "ConSplitter.h"
22 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
26 ConSpliterConsoleControlGetMode (
27 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
28 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE
*Mode
,
29 OUT BOOLEAN
*GopExists
,
30 OUT BOOLEAN
*StdInLocked
35 Return the current video mode information. Also returns info about existence
36 of Graphics Output devices or UGA Draw devices in system, and if the Std In device is locked. All the
37 arguments are optional and only returned if a non NULL pointer is passed in.
40 This - Protocol instance pointer.
41 Mode - Are we in text of grahics mode.
42 GopExists - TRUE if GOP Spliter has found a GOP/UGA device
43 StdInLocked - TRUE if StdIn device is keyboard locked
46 EFI_SUCCESS - Mode information returned.
47 EFI_INVALID_PARAMETER - Invalid parameters.
51 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
54 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
57 return EFI_INVALID_PARAMETER
;
60 *Mode
= Private
->ConsoleOutputMode
;
62 if (GopExists
!= NULL
) {
64 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
65 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
72 if (StdInLocked
!= NULL
) {
73 *StdInLocked
= ConSpliterConssoleControlStdInLocked ();
81 ConSpliterConsoleControlSetMode (
82 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
83 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
88 Set the current mode to either text or graphics. Graphics is
92 This - Protocol instance pointer.
93 Mode - Mode to set the
96 EFI_SUCCESS - Mode information returned.
97 EFI_INVALID_PARAMETER - Invalid parameter.
98 EFI_UNSUPPORTED - Operation unsupported.
102 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
104 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
107 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
109 if (Mode
>= EfiConsoleControlScreenMaxValue
) {
110 return EFI_INVALID_PARAMETER
;
114 // Judge current mode with wanted mode at first.
116 if (Private
->ConsoleOutputMode
== Mode
) {
121 TextAndGop
= &Private
->TextOutList
[0];
122 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
123 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
129 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
130 return EFI_UNSUPPORTED
;
133 Private
->ConsoleOutputMode
= Mode
;
135 TextAndGop
= &Private
->TextOutList
[0];
136 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
138 TextAndGop
->TextOutEnabled
= TRUE
;
140 // If we are going into Graphics mode disable ConOut to any UGA device
142 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
143 TextAndGop
->TextOutEnabled
= FALSE
;
144 if (FeaturePcdGet (PcdConOutGopSupport
)) {
145 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
146 } else if (FeaturePcdGet (PcdConOutUgaSupport
)) {
147 DevNullUgaSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
151 if (Mode
== EfiConsoleControlScreenText
) {
152 DevNullSyncStdOut (Private
);
159 ConSpliterGraphicsOutputQueryMode (
160 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
161 IN UINT32 ModeNumber
,
162 OUT UINTN
*SizeOfInfo
,
163 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
168 Return the current video mode information.
171 This - Protocol instance pointer.
172 ModeNumber - The mode number to return information on.
173 Info - Caller allocated buffer that returns information about ModeNumber.
174 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
177 EFI_SUCCESS - Mode information returned.
178 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
179 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
180 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
181 EFI_INVALID_PARAMETER - One of the input args was NULL.
185 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
187 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
188 return EFI_INVALID_PARAMETER
;
192 // retrieve private data
194 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
196 if (Private
->HardwareNeedsStarting
) {
197 return EFI_NOT_STARTED
;
200 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
203 return EFI_OUT_OF_RESOURCES
;
206 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
208 CopyMem (*Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], *SizeOfInfo
);
215 ConSpliterGraphicsOutputSetMode (
216 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
223 Graphics output protocol interface to set video mode
226 This - Protocol instance pointer.
227 ModeNumber - The mode number to be set.
230 EFI_SUCCESS - Graphics mode was changed.
231 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
232 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
237 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
239 EFI_STATUS ReturnStatus
;
240 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Mode
;
242 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
245 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
246 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
248 if (ModeNumber
>= This
->Mode
->MaxMode
) {
249 return EFI_UNSUPPORTED
;
252 if (ModeNumber
== This
->Mode
->Mode
) {
256 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
259 // GopDevNullSetMode ()
261 ReturnStatus
= EFI_SUCCESS
;
264 // Free the old version
266 if (Private
->GraphicsOutputBlt
!= NULL
) {
267 FreePool (Private
->GraphicsOutputBlt
);
271 // Allocate the virtual Blt buffer
273 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
274 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
275 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
277 if (Private
->GraphicsOutputBlt
== NULL
) {
278 return EFI_OUT_OF_RESOURCES
;
282 // return the worst status met
284 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
285 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
286 if (GraphicsOutput
!= NULL
) {
288 // Find corresponding ModeNumber of this GraphicsOutput instance
290 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
291 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
292 if (EFI_ERROR (Status
)) {
295 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
302 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
303 if (EFI_ERROR (Status
)) {
304 ReturnStatus
= Status
;
308 if (EFI_ERROR (ReturnStatus
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
309 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
310 if (UgaDraw
!= NULL
) {
311 Status
= UgaDraw
->SetMode (
313 Mode
->HorizontalResolution
,
314 Mode
->VerticalResolution
,
318 if (EFI_ERROR (Status
)) {
319 ReturnStatus
= Status
;
325 This
->Mode
->Mode
= ModeNumber
;
327 CopyMem (This
->Mode
->Info
, &Private
->GraphicsOutputModeBuffer
[ModeNumber
], This
->Mode
->SizeOfInfo
);
330 // Information is not enough here, so the following items remain unchanged:
331 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
332 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
333 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
336 Private
->HardwareNeedsStarting
= FALSE
;
343 DevNullGraphicsOutputBlt (
344 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
345 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
346 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
349 IN UINTN DestinationX
,
350 IN UINTN DestinationY
,
353 IN UINTN Delta OPTIONAL
359 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
360 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
361 UINTN HorizontalResolution
;
362 UINTN VerticalResolution
;
364 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
365 return EFI_INVALID_PARAMETER
;
368 if (Width
== 0 || Height
== 0) {
369 return EFI_INVALID_PARAMETER
;
373 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
376 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
377 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
380 // We need to fill the Virtual Screen buffer with the blt data.
382 if (BltOperation
== EfiBltVideoToBltBuffer
) {
384 // Video to BltBuffer: Source is Video, destination is BltBuffer
386 if ((SourceY
+ Height
) > VerticalResolution
) {
387 return EFI_INVALID_PARAMETER
;
390 if ((SourceX
+ Width
) > HorizontalResolution
) {
391 return EFI_INVALID_PARAMETER
;
394 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
395 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
397 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
398 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
399 ScreenPtr
+= HorizontalResolution
;
404 // BltBuffer to Video: Source is BltBuffer, destination is Video
406 if (DestinationY
+ Height
> VerticalResolution
) {
407 return EFI_INVALID_PARAMETER
;
410 if (DestinationX
+ Width
> HorizontalResolution
) {
411 return EFI_INVALID_PARAMETER
;
414 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
416 // Copy backwards, only care the Video to Video Blt
418 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
419 SrcY
= SourceY
+ Height
- 1;
423 // Copy forwards, for other cases
425 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
430 while (Height
!= 0) {
431 if (BltOperation
== EfiBltVideoFill
) {
432 for (Index
= 0; Index
< Width
; Index
++) {
433 ScreenPtr
[Index
] = *BltBuffer
;
436 if (BltOperation
== EfiBltBufferToVideo
) {
437 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
439 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
442 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
446 ScreenPtr
+= HorizontalResolution
;
449 ScreenPtr
-= HorizontalResolution
;
461 ConSpliterGraphicsOutputBlt (
462 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
463 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
464 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
467 IN UINTN DestinationX
,
468 IN UINTN DestinationY
,
471 IN UINTN Delta OPTIONAL
476 The following table defines actions for BltOperations:
477 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
478 directly to every pixel of the video display rectangle
479 (DestinationX, DestinationY)
480 (DestinationX + Width, DestinationY + Height).
481 Only one pixel will be used from the BltBuffer. Delta is NOT used.
482 EfiBltVideoToBltBuffer - Read data from the video display rectangle
483 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
484 the BltBuffer rectangle (DestinationX, DestinationY )
485 (DestinationX + Width, DestinationY + Height). If DestinationX or
486 DestinationY is not zero then Delta must be set to the length in bytes
487 of a row in the BltBuffer.
488 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
489 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
490 video display rectangle (DestinationX, DestinationY)
491 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
492 not zero then Delta must be set to the length in bytes of a row in the
494 EfiBltVideoToVideo - Copy from the video display rectangle
495 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
496 to the video display rectangle (DestinationX, DestinationY)
497 (DestinationX + Width, DestinationY + Height).
498 The BltBuffer and Delta are not used in this mode.
501 This - Protocol instance pointer.
502 BltBuffer - Buffer containing data to blit into video buffer. This
503 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
504 BltOperation - Operation to perform on BlitBuffer and video memory
505 SourceX - X coordinate of source for the BltBuffer.
506 SourceY - Y coordinate of source for the BltBuffer.
507 DestinationX - X coordinate of destination for the BltBuffer.
508 DestinationY - Y coordinate of destination for the BltBuffer.
509 Width - Width of rectangle in BltBuffer in pixels.
510 Height - Hight of rectangle in BltBuffer in pixels.
514 EFI_SUCCESS - The Blt operation completed.
515 EFI_INVALID_PARAMETER - BltOperation is not valid.
516 EFI_DEVICE_ERROR - A hardware error occured writting to the video
522 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
524 EFI_STATUS ReturnStatus
;
525 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
526 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
528 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
531 // Sync up DevNull GOP device
533 ReturnStatus
= DevNullGraphicsOutputBlt (
546 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
550 // return the worst status met
552 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
553 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
554 if (GraphicsOutput
!= NULL
) {
555 Status
= GraphicsOutput
->Blt (
567 if (EFI_ERROR (Status
)) {
568 ReturnStatus
= Status
;
569 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
571 // Only need to read the data into buffer one time
577 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
578 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
579 Status
= UgaDraw
->Blt (
581 (EFI_UGA_PIXEL
*) BltBuffer
,
582 (EFI_UGA_BLT_OPERATION
) BltOperation
,
591 if (EFI_ERROR (Status
)) {
592 ReturnStatus
= Status
;
593 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
595 // Only need to read the data into buffer one time
607 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
608 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
609 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
612 if (GraphicsOutput
!= NULL
) {
613 return GraphicsOutput
->Blt (
615 Private
->GraphicsOutputBlt
,
621 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
622 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
625 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
626 return UgaDraw
->Blt (
628 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
629 EfiUgaBltBufferToVideo
,
634 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
635 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
639 return EFI_UNSUPPORTED
;
645 ConSpliterUgaDrawGetMode (
646 IN EFI_UGA_DRAW_PROTOCOL
*This
,
647 OUT UINT32
*HorizontalResolution
,
648 OUT UINT32
*VerticalResolution
,
649 OUT UINT32
*ColorDepth
,
650 OUT UINT32
*RefreshRate
655 Return the current video mode information.
658 This - Protocol instance pointer.
659 HorizontalResolution - Current video horizontal resolution in pixels
660 VerticalResolution - Current video vertical resolution in pixels
661 ColorDepth - Current video color depth in bits per pixel
662 RefreshRate - Current video refresh rate in Hz.
665 EFI_SUCCESS - Mode information returned.
666 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
667 EFI_INVALID_PARAMETER - One of the input args was NULL.
671 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
673 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
674 return EFI_INVALID_PARAMETER
;
677 // retrieve private data
679 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
681 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
682 *VerticalResolution
= Private
->UgaVerticalResolution
;
683 *ColorDepth
= Private
->UgaColorDepth
;
684 *RefreshRate
= Private
->UgaRefreshRate
;
691 ConSpliterUgaDrawSetMode (
692 IN EFI_UGA_DRAW_PROTOCOL
*This
,
693 IN UINT32 HorizontalResolution
,
694 IN UINT32 VerticalResolution
,
695 IN UINT32 ColorDepth
,
696 IN UINT32 RefreshRate
701 Return the current video mode information.
704 This - Protocol instance pointer.
705 HorizontalResolution - Current video horizontal resolution in pixels
706 VerticalResolution - Current video vertical resolution in pixels
707 ColorDepth - Current video color depth in bits per pixel
708 RefreshRate - Current video refresh rate in Hz.
711 EFI_SUCCESS - Mode information returned.
712 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
713 EFI_OUT_OF_RESOURCES - Out of resources.
718 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
720 EFI_STATUS ReturnStatus
;
722 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
725 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
726 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
728 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
731 // UgaDevNullSetMode ()
733 ReturnStatus
= EFI_SUCCESS
;
736 // Free the old version
738 if (Private
->UgaBlt
!= NULL
) {
739 FreePool (Private
->UgaBlt
);
743 // Allocate the virtual Blt buffer
745 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
746 Private
->UgaBlt
= AllocateZeroPool (Size
);
747 if (Private
->UgaBlt
== NULL
) {
748 return EFI_OUT_OF_RESOURCES
;
752 // Update the Mode data
754 Private
->UgaHorizontalResolution
= HorizontalResolution
;
755 Private
->UgaVerticalResolution
= VerticalResolution
;
756 Private
->UgaColorDepth
= ColorDepth
;
757 Private
->UgaRefreshRate
= RefreshRate
;
759 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
763 // return the worst status met
765 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
767 ReturnStatus
= EFI_UNSUPPORTED
;
769 if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
770 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
771 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
772 Status
= UgaDraw
->SetMode (
774 HorizontalResolution
,
779 if (EFI_ERROR (Status
)) {
780 ReturnStatus
= Status
;
785 if (EFI_ERROR (ReturnStatus
)) {
786 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
787 if (GraphicsOutput
!= NULL
) {
789 // Find corresponding ModeNumber of this GraphicsOutput instance
791 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
792 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
793 if (EFI_ERROR (Status
)) {
796 if ((Info
->HorizontalResolution
== HorizontalResolution
) && (Info
->VerticalResolution
== VerticalResolution
)) {
803 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
804 if (EFI_ERROR (Status
)) {
805 ReturnStatus
= Status
;
816 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
817 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
818 IN EFI_UGA_BLT_OPERATION BltOperation
,
821 IN UINTN DestinationX
,
822 IN UINTN DestinationY
,
825 IN UINTN Delta OPTIONAL
831 EFI_UGA_PIXEL
*BltPtr
;
832 EFI_UGA_PIXEL
*ScreenPtr
;
833 UINT32 HorizontalResolution
;
834 UINT32 VerticalResolution
;
836 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
837 return EFI_INVALID_PARAMETER
;
840 if (Width
== 0 || Height
== 0) {
841 return EFI_INVALID_PARAMETER
;
845 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
848 HorizontalResolution
= Private
->UgaHorizontalResolution
;
849 VerticalResolution
= Private
->UgaVerticalResolution
;
852 // We need to fill the Virtual Screen buffer with the blt data.
854 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
856 // Video to BltBuffer: Source is Video, destination is BltBuffer
858 if ((SourceY
+ Height
) > VerticalResolution
) {
859 return EFI_INVALID_PARAMETER
;
862 if ((SourceX
+ Width
) > HorizontalResolution
) {
863 return EFI_INVALID_PARAMETER
;
866 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
867 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
869 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
870 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
871 ScreenPtr
+= HorizontalResolution
;
876 // BltBuffer to Video: Source is BltBuffer, destination is Video
878 if (DestinationY
+ Height
> VerticalResolution
) {
879 return EFI_INVALID_PARAMETER
;
882 if (DestinationX
+ Width
> HorizontalResolution
) {
883 return EFI_INVALID_PARAMETER
;
886 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
888 // Copy backwards, only care the Video to Video Blt
890 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
891 SrcY
= SourceY
+ Height
- 1;
895 // Copy forwards, for other cases
897 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
902 while (Height
!= 0) {
903 if (BltOperation
== EfiUgaVideoFill
) {
904 for (Index
= 0; Index
< Width
; Index
++) {
905 ScreenPtr
[Index
] = *BltBuffer
;
908 if (BltOperation
== EfiUgaBltBufferToVideo
) {
909 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
911 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
914 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
918 ScreenPtr
+= HorizontalResolution
;
921 ScreenPtr
-= HorizontalResolution
;
933 ConSpliterUgaDrawBlt (
934 IN EFI_UGA_DRAW_PROTOCOL
*This
,
935 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
936 IN EFI_UGA_BLT_OPERATION BltOperation
,
939 IN UINTN DestinationX
,
940 IN UINTN DestinationY
,
943 IN UINTN Delta OPTIONAL
948 The following table defines actions for BltOperations:
949 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
950 directly to every pixel of the video display rectangle
951 (DestinationX, DestinationY)
952 (DestinationX + Width, DestinationY + Height).
953 Only one pixel will be used from the BltBuffer. Delta is NOT used.
954 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
955 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
956 the BltBuffer rectangle (DestinationX, DestinationY )
957 (DestinationX + Width, DestinationY + Height). If DestinationX or
958 DestinationY is not zero then Delta must be set to the length in bytes
959 of a row in the BltBuffer.
960 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
961 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
962 video display rectangle (DestinationX, DestinationY)
963 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
964 not zero then Delta must be set to the length in bytes of a row in the
966 EfiUgaVideoToVideo - Copy from the video display rectangle
967 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
968 to the video display rectangle (DestinationX, DestinationY)
969 (DestinationX + Width, DestinationY + Height).
970 The BltBuffer and Delta are not used in this mode.
973 This - Protocol instance pointer.
974 BltBuffer - Buffer containing data to blit into video buffer. This
975 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
976 BltOperation - Operation to perform on BlitBuffer and video memory
977 SourceX - X coordinate of source for the BltBuffer.
978 SourceY - Y coordinate of source for the BltBuffer.
979 DestinationX - X coordinate of destination for the BltBuffer.
980 DestinationY - Y coordinate of destination for the BltBuffer.
981 Width - Width of rectangle in BltBuffer in pixels.
982 Height - Hight of rectangle in BltBuffer in pixels.
986 EFI_SUCCESS - The Blt operation completed.
987 EFI_INVALID_PARAMETER - BltOperation is not valid.
988 EFI_DEVICE_ERROR - A hardware error occured writting to the video
994 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
996 EFI_STATUS ReturnStatus
;
997 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
999 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
1002 // Sync up DevNull UGA device
1004 ReturnStatus
= DevNullUgaBlt (
1016 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1017 return ReturnStatus
;
1020 // return the worst status met
1022 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1023 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
1024 if (GraphicsOutput
!= NULL
) {
1025 Status
= GraphicsOutput
->Blt (
1027 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltBuffer
,
1028 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION
) BltOperation
,
1037 if (EFI_ERROR (Status
)) {
1038 ReturnStatus
= Status
;
1039 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
1041 // Only need to read the data into buffer one time
1047 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1048 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1049 Private
->TextOutList
[Index
].UgaDraw
,
1060 if (EFI_ERROR (Status
)) {
1061 ReturnStatus
= Status
;
1062 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1064 // Only need to read the data into buffer one time
1071 return ReturnStatus
;
1076 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1077 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
1078 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1081 if (UgaDraw
!= NULL
&& FeaturePcdGet (PcdUgaConsumeSupport
)) {
1082 return UgaDraw
->Blt (
1085 EfiUgaBltBufferToVideo
,
1090 Private
->UgaHorizontalResolution
,
1091 Private
->UgaVerticalResolution
,
1092 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1094 } else if (GraphicsOutput
!= NULL
) {
1095 return GraphicsOutput
->Blt (
1097 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) Private
->UgaBlt
,
1098 EfiBltBufferToVideo
,
1103 Private
->UgaHorizontalResolution
,
1104 Private
->UgaVerticalResolution
,
1108 return EFI_UNSUPPORTED
;
1113 DevNullTextOutOutputString (
1114 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1119 Routine Description:
1120 Write a Unicode string to the output device.
1123 Private - Pointer to the console output splitter's private data. It
1124 indicates the calling context.
1125 WString - The NULL-terminated Unicode string to be displayed on the output
1126 device(s). All output devices must also support the Unicode
1127 drawing defined in this file.
1130 EFI_SUCCESS - The string was output to the device.
1131 EFI_DEVICE_ERROR - The device reported an error while attempting to
1133 EFI_UNSUPPORTED - The output device's mode is not currently in a
1135 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1136 characters in the Unicode string could not be
1137 rendered and were skipped.
1142 UINTN SizeAttribute
;
1144 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1151 INT32
*NullAttributes
;
1156 Mode
= &Private
->TextOutMode
;
1157 NullScreen
= Private
->DevNullScreen
;
1158 NullAttributes
= Private
->DevNullAttributes
;
1159 LastRow
= Private
->DevNullRows
- 1;
1160 MaxColumn
= Private
->DevNullColumns
;
1162 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1170 if (*WString
== CHAR_BACKSPACE
) {
1172 // If the cursor is at the left edge of the display, then move the cursor
1175 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1177 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1181 // If the cursor is not at the left edge of the display,
1182 // then move the cursor left one column.
1184 if (Mode
->CursorColumn
> 0) {
1185 Mode
->CursorColumn
--;
1186 if (Mode
->CursorColumn
> 0 &&
1187 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1189 Mode
->CursorColumn
--;
1192 // Insert an extra backspace
1194 InsertChar
= CHAR_BACKSPACE
;
1199 InsertChar
= TempChar
;
1212 } else if (*WString
== CHAR_LINEFEED
) {
1214 // If the cursor is at the bottom of the display,
1215 // then scroll the display one row, and do not update
1216 // the cursor position. Otherwise, move the cursor down one row.
1218 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1220 // Scroll Screen Up One Row
1222 SizeAttribute
= LastRow
* MaxColumn
;
1225 NullAttributes
+ MaxColumn
,
1226 SizeAttribute
* sizeof (INT32
)
1230 // Each row has an ending CHAR_NULL. So one more character each line
1231 // for DevNullScreen than DevNullAttributes
1233 SizeScreen
= SizeAttribute
+ LastRow
;
1236 NullScreen
+ (MaxColumn
+ 1),
1237 SizeScreen
* sizeof (CHAR16
)
1241 // Print Blank Line at last line
1243 Screen
= NullScreen
+ SizeScreen
;
1244 Attribute
= NullAttributes
+ SizeAttribute
;
1246 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1248 *Attribute
= Mode
->Attribute
;
1255 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1257 // Move the cursor to the beginning of the current row.
1259 Mode
->CursorColumn
= 0;
1263 // Print the character at the current cursor position and
1264 // move the cursor right one column. If this moves the cursor
1265 // past the right edge of the display, then the line should wrap to
1266 // the beginning of the next line. This is equivalent to inserting
1267 // a CR and an LF. Note that if the cursor is at the bottom of the
1268 // display, and the line wraps, then the display will be scrolled
1271 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1273 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1274 if (*WString
== CHAR_NULL
) {
1278 if (*WString
== CHAR_BACKSPACE
) {
1282 if (*WString
== CHAR_LINEFEED
) {
1286 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1290 if (*WString
== UNICODE_WIDE_CHAR
|| *WString
== UNICODE_NARROW_CHAR
) {
1291 CurrentWidth
= (*WString
== UNICODE_WIDE_CHAR
) ? 2 : 1;
1296 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1298 // If a wide char is at the rightmost column, then move the char
1299 // to the beginning of the next row
1301 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1302 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1304 Mode
->CursorColumn
++;
1306 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1307 NullAttributes
[Index
] = Mode
->Attribute
;
1308 if (CurrentWidth
== 1) {
1309 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1311 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1312 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1315 Index
+= CurrentWidth
;
1317 Mode
->CursorColumn
+= CurrentWidth
;
1321 // At the end of line, output carriage return and line feed
1323 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1324 DevNullTextOutOutputString (Private
, mCrLfString
);
1333 DevNullTextOutSetMode (
1334 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1339 Routine Description:
1340 Sets the output device(s) to a specified mode.
1343 Private - Private data structure pointer.
1344 ModeNumber - The mode number to set.
1347 EFI_SUCCESS - The requested text mode was set.
1348 EFI_DEVICE_ERROR - The device had an error and
1349 could not complete the request.
1350 EFI_UNSUPPORTED - The mode number was not valid.
1351 EFI_OUT_OF_RESOURCES - Out of resources.
1359 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1362 // No extra check for ModeNumber here, as it has been checked in
1363 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1364 // Row and Column should be fetched from intersection map.
1366 if (Private
->TextOutModeMap
!= NULL
) {
1367 CurrentMode
= *(Private
->TextOutModeMap
+ Private
->TextOutListCount
* ModeNumber
);
1369 CurrentMode
= (INT32
)(ModeNumber
);
1371 Mode
= &(Private
->TextOutQueryData
[CurrentMode
]);
1373 Column
= Mode
->Columns
;
1375 if (Row
<= 0 && Column
<= 0) {
1376 return EFI_UNSUPPORTED
;
1379 if (Private
->TextOutMode
.Mode
!= (INT32
) ModeNumber
) {
1381 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1382 Private
->DevNullColumns
= Column
;
1383 Private
->DevNullRows
= Row
;
1385 if (Private
->DevNullScreen
!= NULL
) {
1386 FreePool (Private
->DevNullScreen
);
1389 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1390 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1391 if (Private
->DevNullScreen
== NULL
) {
1392 return EFI_OUT_OF_RESOURCES
;
1395 if (Private
->DevNullAttributes
!= NULL
) {
1396 FreePool (Private
->DevNullAttributes
);
1399 Size
= Row
* Column
* sizeof (INT32
);
1400 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1401 if (Private
->DevNullAttributes
== NULL
) {
1402 return EFI_OUT_OF_RESOURCES
;
1406 DevNullTextOutClearScreen (Private
);
1412 DevNullTextOutClearScreen (
1413 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1417 Routine Description:
1418 Clears the output device(s) display to the currently selected background
1422 Private - Protocol instance pointer.
1425 EFI_SUCCESS - The operation completed successfully.
1426 EFI_DEVICE_ERROR - The device had an error and
1427 could not complete the request.
1428 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1436 INT32 CurrentAttribute
;
1439 // Clear the DevNull Text Out Buffers.
1440 // The screen is filled with spaces.
1441 // The attributes are all synced with the current Simple Text Out Attribute
1443 Screen
= Private
->DevNullScreen
;
1444 Attributes
= Private
->DevNullAttributes
;
1445 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1447 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1448 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1450 *Attributes
= CurrentAttribute
;
1453 // Each line of the screen has a NULL on the end so we must skip over it
1458 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1460 return DevNullTextOutEnableCursor (Private
, TRUE
);
1464 DevNullTextOutSetCursorPosition (
1465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1471 Routine Description:
1472 Sets the current coordinates of the cursor position
1475 Private - Protocol instance pointer.
1476 Column, Row - the position to set the cursor to. Must be greater than or
1477 equal to zero and less than the number of columns and rows
1481 EFI_SUCCESS - The operation completed successfully.
1482 EFI_DEVICE_ERROR - The device had an error and
1483 could not complete the request.
1484 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1485 cursor position is invalid for the current mode.
1490 // No need to do extra check here as whether (Column, Row) is valid has
1491 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1492 // always be supported.
1494 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1495 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1501 DevNullTextOutEnableCursor (
1502 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1506 Routine Description:
1508 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1509 In this driver, the cursor cannot be hidden.
1513 Private - Indicates the calling context.
1515 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1516 is set to be invisible.
1520 EFI_SUCCESS - The request is valid.
1525 Private
->TextOutMode
.CursorVisible
= Visible
;
1532 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1535 Routine Description:
1536 Take the DevNull TextOut device and update the Simple Text Out on every
1540 Private - Indicates the calling context.
1543 EFI_SUCCESS - The request is valid.
1544 other - Return status of TextOut->OutputString ()
1549 EFI_STATUS ReturnStatus
;
1554 UINTN CurrentColumn
;
1557 INT32 StartAttribute
;
1558 BOOLEAN StartCursorState
;
1563 CHAR16
*ScreenStart
;
1564 INT32 CurrentAttribute
;
1566 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
1569 // Save the devices Attributes, Cursor enable state and location
1571 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1572 StartRow
= Private
->TextOutMode
.CursorRow
;
1573 StartAttribute
= Private
->TextOutMode
.Attribute
;
1574 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1576 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1578 Sto
= Private
->TextOutList
[List
].TextOut
;
1581 // Skip non GOP/UGA devices
1583 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1584 Sto
->EnableCursor (Sto
, FALSE
);
1585 Sto
->ClearScreen (Sto
);
1589 ReturnStatus
= EFI_SUCCESS
;
1590 Screen
= Private
->DevNullScreen
;
1591 Attributes
= Private
->DevNullAttributes
;
1592 MaxColumn
= Private
->DevNullColumns
;
1594 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1595 if (Buffer
== NULL
) {
1596 return ReturnStatus
;
1599 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1601 if (Row
== (Private
->DevNullRows
- 1)) {
1603 // Don't ever sync the last character as it will scroll the screen
1605 Screen
[MaxColumn
- 1] = 0x00;
1609 while (Column
< MaxColumn
) {
1610 if (Screen
[Column
]) {
1611 CurrentAttribute
= Attributes
[Column
];
1612 CurrentColumn
= Column
;
1613 ScreenStart
= &Screen
[Column
];
1616 // the line end is alway 0x0. So Column should be less than MaxColumn
1617 // It should be still in the same row
1619 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1621 if (Attributes
[Column
] != CurrentAttribute
) {
1628 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1636 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1638 Sto
= Private
->TextOutList
[List
].TextOut
;
1641 // Skip non GOP/UGA devices
1643 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1644 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1645 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1646 Status
= Sto
->OutputString (Sto
, Buffer
);
1647 if (EFI_ERROR (Status
)) {
1648 ReturnStatus
= Status
;
1659 // Restore the devices Attributes, Cursor enable state and location
1661 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1662 Sto
= Private
->TextOutList
[List
].TextOut
;
1665 // Skip non GOP/UGA devices
1667 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1668 Sto
->SetAttribute (Sto
, StartAttribute
);
1669 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1670 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1671 if (EFI_ERROR (Status
)) {
1672 ReturnStatus
= Status
;
1679 return ReturnStatus
;