3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Support for ConsoleControl protocol. Support for UGA Draw spliter.
19 Support for DevNull Console Out. This console uses memory buffers
20 to represnt the console. It allows a console to start very early and
21 when a new console is added it is synced up with the current console
26 #include "ConSplitter.h"
28 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
32 ConSpliterConsoleControlGetMode (
33 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
34 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE
*Mode
,
35 OUT BOOLEAN
*GopExists
,
36 OUT BOOLEAN
*StdInLocked
41 Return the current video mode information. Also returns info about existence
42 of UGA Draw devices in system, and if the Std In device is locked. All the
43 arguments are optional and only returned if a non NULL pointer is passed in.
46 This - Protocol instance pointer.
47 Mode - Are we in text of grahics mode.
48 UgaExists - TRUE if UGA Spliter has found a UGA device
49 StdInLocked - TRUE if StdIn device is keyboard locked
52 EFI_SUCCESS - Mode information returned.
53 EFI_INVALID_PARAMETER - Invalid parameters.
57 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
60 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
63 return EFI_INVALID_PARAMETER
;
66 *Mode
= Private
->ConsoleOutputMode
;
68 if (GopExists
!= NULL
) {
70 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
71 if ((Private
->TextOutList
[Index
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[Index
].UgaDraw
!= NULL
)) {
78 if (StdInLocked
!= NULL
) {
79 *StdInLocked
= ConSpliterConssoleControlStdInLocked ();
87 ConSpliterConsoleControlSetMode (
88 IN EFI_CONSOLE_CONTROL_PROTOCOL
*This
,
89 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
94 Set the current mode to either text or graphics. Graphics is
98 This - Protocol instance pointer.
99 Mode - Mode to set the
102 EFI_SUCCESS - Mode information returned.
103 EFI_INVALID_PARAMETER - Invalid parameter.
104 EFI_UNSUPPORTED - Operation unsupported.
108 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
110 TEXT_OUT_AND_GOP_DATA
*TextAndGop
;
113 Private
= CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
115 if (Mode
>= EfiConsoleControlScreenMaxValue
) {
116 return EFI_INVALID_PARAMETER
;
120 TextAndGop
= &Private
->TextOutList
[0];
121 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
122 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
128 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
129 return EFI_UNSUPPORTED
;
132 Private
->ConsoleOutputMode
= Mode
;
134 TextAndGop
= &Private
->TextOutList
[0];
135 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
137 TextAndGop
->TextOutEnabled
= TRUE
;
139 // If we are going into Graphics mode disable ConOut to any UGA device
141 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
142 TextAndGop
->TextOutEnabled
= FALSE
;
143 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
144 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
146 DevNullUgaSync (Private
, TextAndGop
->UgaDraw
);
151 if (Mode
== EfiConsoleControlScreenText
) {
152 DevNullSyncGopStdOut (Private
);
158 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
161 ConSpliterGraphicsOutputQueryMode (
162 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
163 IN UINT32 ModeNumber
,
164 OUT UINTN
*SizeOfInfo
,
165 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
170 Return the current video mode information.
173 This - Protocol instance pointer.
174 ModeNumber - The mode number to return information on.
175 Info - Caller allocated buffer that returns information about ModeNumber.
176 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
179 EFI_SUCCESS - Mode information returned.
180 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
181 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
182 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
183 EFI_INVALID_PARAMETER - One of the input args was NULL.
187 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
189 TEXT_OUT_GOP_MODE
*Mode
;
191 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
192 return EFI_INVALID_PARAMETER
;
196 // retrieve private data
198 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
200 if (Private
->HardwareNeedsStarting
) {
201 return EFI_NOT_STARTED
;
204 Status
= gBS
->AllocatePool (
206 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
209 if (EFI_ERROR (Status
)) {
213 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
215 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
216 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
217 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
218 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
219 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
226 ConSpliterGraphicsOutputSetMode (
227 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
234 Graphics output protocol interface to set video mode
237 This - Protocol instance pointer.
238 ModeNumber - The mode number to be set.
241 EFI_SUCCESS - Graphics mode was changed.
242 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
243 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
248 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
250 EFI_STATUS ReturnStatus
;
251 TEXT_OUT_GOP_MODE
*Mode
;
253 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
256 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
257 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
259 if (ModeNumber
>= This
->Mode
->MaxMode
) {
260 return EFI_UNSUPPORTED
;
263 if (ModeNumber
== This
->Mode
->Mode
) {
267 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
270 // GopDevNullSetMode ()
272 ReturnStatus
= EFI_SUCCESS
;
275 // Free the old version
277 if (Private
->GraphicsOutputBlt
!= NULL
) {
278 gBS
->FreePool (Private
->GraphicsOutputBlt
);
282 // Allocate the virtual Blt buffer
284 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
285 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
286 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
288 if (Private
->GraphicsOutputBlt
== NULL
) {
289 return EFI_OUT_OF_RESOURCES
;
292 if (!Private
->HardwareNeedsStarting
) {
293 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
294 return EFI_UNSUPPORTED
;
298 // return the worst status met
300 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
301 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
302 if (GraphicsOutput
!= NULL
) {
304 // Find corresponding ModeNumber of this GraphicsOutput instance
306 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
307 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
308 if (EFI_ERROR (Status
)) {
311 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
312 gBS
->FreePool (Info
);
315 gBS
->FreePool (Info
);
318 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
319 if (EFI_ERROR (Status
)) {
320 ReturnStatus
= Status
;
324 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
325 if (UgaDraw
!= NULL
) {
326 Status
= UgaDraw
->SetMode (
328 Mode
->HorizontalResolution
,
329 Mode
->VerticalResolution
,
333 if (EFI_ERROR (Status
)) {
334 ReturnStatus
= Status
;
339 This
->Mode
->Mode
= ModeNumber
;
341 Info
= This
->Mode
->Info
;
342 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
343 Info
->VerticalResolution
= Mode
->VerticalResolution
;
344 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
347 // Information is not enough here, so the following items remain unchanged:
348 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
349 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
350 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
353 Private
->HardwareNeedsStarting
= FALSE
;
359 DevNullGraphicsOutputBlt (
360 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
361 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
362 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
365 IN UINTN DestinationX
,
366 IN UINTN DestinationY
,
369 IN UINTN Delta OPTIONAL
374 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
375 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
376 UINTN HorizontalResolution
;
377 UINTN VerticalResolution
;
379 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
380 return EFI_INVALID_PARAMETER
;
383 if (Width
== 0 || Height
== 0) {
384 return EFI_INVALID_PARAMETER
;
388 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
391 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
392 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
395 // We need to fill the Virtual Screen buffer with the blt data.
397 if (BltOperation
== EfiBltVideoToBltBuffer
) {
399 // Video to BltBuffer: Source is Video, destination is BltBuffer
401 if ((SourceY
+ Height
) > VerticalResolution
) {
402 return EFI_INVALID_PARAMETER
;
405 if ((SourceX
+ Width
) > HorizontalResolution
) {
406 return EFI_INVALID_PARAMETER
;
409 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
410 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
412 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
413 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
414 ScreenPtr
+= HorizontalResolution
;
419 // BltBuffer to Video: Source is BltBuffer, destination is Video
421 if (DestinationY
+ Height
> VerticalResolution
) {
422 return EFI_INVALID_PARAMETER
;
425 if (DestinationX
+ Width
> HorizontalResolution
) {
426 return EFI_INVALID_PARAMETER
;
429 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
432 if (BltOperation
== EfiBltVideoFill
) {
433 for (Index
= 0; Index
< Width
; Index
++) {
434 ScreenPtr
[Index
] = *BltBuffer
;
437 if (BltOperation
== EfiBltBufferToVideo
) {
438 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
440 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
443 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
446 ScreenPtr
+= HorizontalResolution
;
457 ConSpliterGraphicsOutputBlt (
458 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
459 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
460 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
463 IN UINTN DestinationX
,
464 IN UINTN DestinationY
,
467 IN UINTN Delta OPTIONAL
472 The following table defines actions for BltOperations:
473 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
474 directly to every pixel of the video display rectangle
475 (DestinationX, DestinationY)
476 (DestinationX + Width, DestinationY + Height).
477 Only one pixel will be used from the BltBuffer. Delta is NOT used.
478 EfiBltVideoToBltBuffer - Read data from the video display rectangle
479 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
480 the BltBuffer rectangle (DestinationX, DestinationY )
481 (DestinationX + Width, DestinationY + Height). If DestinationX or
482 DestinationY is not zero then Delta must be set to the length in bytes
483 of a row in the BltBuffer.
484 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
485 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
486 video display rectangle (DestinationX, DestinationY)
487 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
488 not zero then Delta must be set to the length in bytes of a row in the
490 EfiBltVideoToVideo - Copy from the video display rectangle
491 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
492 to the video display rectangle (DestinationX, DestinationY)
493 (DestinationX + Width, DestinationY + Height).
494 The BltBuffer and Delta are not used in this mode.
497 This - Protocol instance pointer.
498 BltBuffer - Buffer containing data to blit into video buffer. This
499 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
500 BltOperation - Operation to perform on BlitBuffer and video memory
501 SourceX - X coordinate of source for the BltBuffer.
502 SourceY - Y coordinate of source for the BltBuffer.
503 DestinationX - X coordinate of destination for the BltBuffer.
504 DestinationY - Y coordinate of destination for the BltBuffer.
505 Width - Width of rectangle in BltBuffer in pixels.
506 Height - Hight of rectangle in BltBuffer in pixels.
510 EFI_SUCCESS - The Blt operation completed.
511 EFI_INVALID_PARAMETER - BltOperation is not valid.
512 EFI_DEVICE_ERROR - A hardware error occured writting to the video
518 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
520 EFI_STATUS ReturnStatus
;
521 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
522 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
524 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
527 // Sync up DevNull GOP device
529 ReturnStatus
= DevNullGraphicsOutputBlt (
542 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
546 // return the worst status met
548 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
549 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
550 if (GraphicsOutput
!= NULL
) {
551 Status
= GraphicsOutput
->Blt (
563 if (EFI_ERROR (Status
)) {
564 ReturnStatus
= Status
;
565 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
567 // Only need to read the data into buffer one time
573 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
574 if (UgaDraw
!= NULL
) {
575 Status
= UgaDraw
->Blt (
577 (EFI_UGA_PIXEL
*) BltBuffer
,
587 if (EFI_ERROR (Status
)) {
588 ReturnStatus
= Status
;
589 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
591 // Only need to read the data into buffer one time
603 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
604 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
605 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
608 if (GraphicsOutput
!= NULL
) {
609 return GraphicsOutput
->Blt (
611 Private
->GraphicsOutputBlt
,
617 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
618 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
622 return UgaDraw
->Blt (
624 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
625 EfiUgaBltBufferToVideo
,
630 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
631 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
641 ConSpliterUgaDrawGetMode (
642 IN EFI_UGA_DRAW_PROTOCOL
*This
,
643 OUT UINT32
*HorizontalResolution
,
644 OUT UINT32
*VerticalResolution
,
645 OUT UINT32
*ColorDepth
,
646 OUT UINT32
*RefreshRate
651 Return the current video mode information.
654 This - Protocol instance pointer.
655 HorizontalResolution - Current video horizontal resolution in pixels
656 VerticalResolution - Current video vertical resolution in pixels
657 ColorDepth - Current video color depth in bits per pixel
658 RefreshRate - Current video refresh rate in Hz.
661 EFI_SUCCESS - Mode information returned.
662 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
663 EFI_INVALID_PARAMETER - One of the input args was NULL.
667 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
669 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
670 return EFI_INVALID_PARAMETER
;
673 // retrieve private data
675 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
677 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
678 *VerticalResolution
= Private
->UgaVerticalResolution
;
679 *ColorDepth
= Private
->UgaColorDepth
;
680 *RefreshRate
= Private
->UgaRefreshRate
;
687 ConSpliterUgaDrawSetMode (
688 IN EFI_UGA_DRAW_PROTOCOL
*This
,
689 IN UINT32 HorizontalResolution
,
690 IN UINT32 VerticalResolution
,
691 IN UINT32 ColorDepth
,
692 IN UINT32 RefreshRate
697 Return the current video mode information.
700 This - Protocol instance pointer.
701 HorizontalResolution - Current video horizontal resolution in pixels
702 VerticalResolution - Current video vertical resolution in pixels
703 ColorDepth - Current video color depth in bits per pixel
704 RefreshRate - Current video refresh rate in Hz.
707 EFI_SUCCESS - Mode information returned.
708 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
709 EFI_OUT_OF_RESOURCES - Out of resources.
714 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
716 EFI_STATUS ReturnStatus
;
719 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
722 // UgaDevNullSetMode ()
724 ReturnStatus
= EFI_SUCCESS
;
727 // Free the old version
729 gBS
->FreePool (Private
->UgaBlt
);
732 // Allocate the virtual Blt buffer
734 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
735 Private
->UgaBlt
= AllocateZeroPool (Size
);
736 if (Private
->UgaBlt
== NULL
) {
737 return EFI_OUT_OF_RESOURCES
;
741 // Update the Mode data
743 Private
->UgaHorizontalResolution
= HorizontalResolution
;
744 Private
->UgaVerticalResolution
= VerticalResolution
;
745 Private
->UgaColorDepth
= ColorDepth
;
746 Private
->UgaRefreshRate
= RefreshRate
;
748 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
752 // return the worst status met
754 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
755 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
756 Status
= Private
->TextOutList
[Index
].UgaDraw
->SetMode (
757 Private
->TextOutList
[Index
].UgaDraw
,
758 HorizontalResolution
,
763 if (EFI_ERROR (Status
)) {
764 ReturnStatus
= Status
;
774 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
775 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
776 IN EFI_UGA_BLT_OPERATION BltOperation
,
779 IN UINTN DestinationX
,
780 IN UINTN DestinationY
,
783 IN UINTN Delta OPTIONAL
788 EFI_UGA_PIXEL
*BltPtr
;
789 EFI_UGA_PIXEL
*ScreenPtr
;
790 UINT32 HorizontalResolution
;
791 UINT32 VerticalResolution
;
793 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
794 return EFI_INVALID_PARAMETER
;
797 if (Width
== 0 || Height
== 0) {
798 return EFI_INVALID_PARAMETER
;
802 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
805 HorizontalResolution
= Private
->UgaHorizontalResolution
;
806 VerticalResolution
= Private
->UgaVerticalResolution
;
809 // We need to fill the Virtual Screen buffer with the blt data.
811 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
813 // Video to BltBuffer: Source is Video, destination is BltBuffer
815 if ((SourceY
+ Height
) > VerticalResolution
) {
816 return EFI_INVALID_PARAMETER
;
819 if ((SourceX
+ Width
) > HorizontalResolution
) {
820 return EFI_INVALID_PARAMETER
;
823 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
824 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
826 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
827 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
828 ScreenPtr
+= HorizontalResolution
;
833 // BltBuffer to Video: Source is BltBuffer, destination is Video
835 if (DestinationY
+ Height
> VerticalResolution
) {
836 return EFI_INVALID_PARAMETER
;
839 if (DestinationX
+ Width
> HorizontalResolution
) {
840 return EFI_INVALID_PARAMETER
;
843 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
846 if (BltOperation
== EfiUgaVideoFill
) {
847 for (Index
= 0; Index
< Width
; Index
++) {
848 ScreenPtr
[Index
] = *BltBuffer
;
851 if (BltOperation
== EfiUgaBltBufferToVideo
) {
852 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
854 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
857 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
860 ScreenPtr
+= HorizontalResolution
;
871 ConSpliterUgaDrawBlt (
872 IN EFI_UGA_DRAW_PROTOCOL
*This
,
873 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
874 IN EFI_UGA_BLT_OPERATION BltOperation
,
877 IN UINTN DestinationX
,
878 IN UINTN DestinationY
,
881 IN UINTN Delta OPTIONAL
886 The following table defines actions for BltOperations:
887 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
888 directly to every pixel of the video display rectangle
889 (DestinationX, DestinationY)
890 (DestinationX + Width, DestinationY + Height).
891 Only one pixel will be used from the BltBuffer. Delta is NOT used.
892 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
893 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
894 the BltBuffer rectangle (DestinationX, DestinationY )
895 (DestinationX + Width, DestinationY + Height). If DestinationX or
896 DestinationY is not zero then Delta must be set to the length in bytes
897 of a row in the BltBuffer.
898 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
899 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
900 video display rectangle (DestinationX, DestinationY)
901 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
902 not zero then Delta must be set to the length in bytes of a row in the
904 EfiUgaVideoToVideo - Copy from the video display rectangle
905 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
906 to the video display rectangle (DestinationX, DestinationY)
907 (DestinationX + Width, DestinationY + Height).
908 The BltBuffer and Delta are not used in this mode.
911 This - Protocol instance pointer.
912 BltBuffer - Buffer containing data to blit into video buffer. This
913 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
914 BltOperation - Operation to perform on BlitBuffer and video memory
915 SourceX - X coordinate of source for the BltBuffer.
916 SourceY - Y coordinate of source for the BltBuffer.
917 DestinationX - X coordinate of destination for the BltBuffer.
918 DestinationY - Y coordinate of destination for the BltBuffer.
919 Width - Width of rectangle in BltBuffer in pixels.
920 Height - Hight of rectangle in BltBuffer in pixels.
924 EFI_SUCCESS - The Blt operation completed.
925 EFI_INVALID_PARAMETER - BltOperation is not valid.
926 EFI_DEVICE_ERROR - A hardware error occured writting to the video
932 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
934 EFI_STATUS ReturnStatus
;
936 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
939 // Sync up DevNull UGA device
941 ReturnStatus
= DevNullUgaBlt (
953 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
957 // return the worst status met
959 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
960 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
961 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
962 Private
->TextOutList
[Index
].UgaDraw
,
973 if (EFI_ERROR (Status
)) {
974 ReturnStatus
= Status
;
975 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
977 // Only need to read the data into buffer one time
989 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
990 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
993 return UgaDraw
->Blt (
996 EfiUgaBltBufferToVideo
,
1001 Private
->UgaHorizontalResolution
,
1002 Private
->UgaVerticalResolution
,
1003 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1009 DevNullTextOutOutputString (
1010 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1015 Routine Description:
1016 Write a Unicode string to the output device.
1019 Private - Pointer to the console output splitter's private data. It
1020 indicates the calling context.
1021 WString - The NULL-terminated Unicode string to be displayed on the output
1022 device(s). All output devices must also support the Unicode
1023 drawing defined in this file.
1026 EFI_SUCCESS - The string was output to the device.
1027 EFI_DEVICE_ERROR - The device reported an error while attempting to
1029 EFI_UNSUPPORTED - The output device's mode is not currently in a
1031 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1032 characters in the Unicode string could not be
1033 rendered and were skipped.
1038 UINTN SizeAttribute
;
1040 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1047 INT32
*NullAttributes
;
1052 Mode
= &Private
->TextOutMode
;
1053 NullScreen
= Private
->DevNullScreen
;
1054 NullAttributes
= Private
->DevNullAttributes
;
1055 LastRow
= Private
->DevNullRows
- 1;
1056 MaxColumn
= Private
->DevNullColumns
;
1058 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1066 if (*WString
== CHAR_BACKSPACE
) {
1068 // If the cursor is at the left edge of the display, then move the cursor
1071 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1073 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1077 // If the cursor is not at the left edge of the display,
1078 // then move the cursor left one column.
1080 if (Mode
->CursorColumn
> 0) {
1081 Mode
->CursorColumn
--;
1082 if (Mode
->CursorColumn
> 0 &&
1083 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1085 Mode
->CursorColumn
--;
1088 // Insert an extra backspace
1090 InsertChar
= CHAR_BACKSPACE
;
1095 InsertChar
= TempChar
;
1108 } else if (*WString
== CHAR_LINEFEED
) {
1110 // If the cursor is at the bottom of the display,
1111 // then scroll the display one row, and do not update
1112 // the cursor position. Otherwise, move the cursor down one row.
1114 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1116 // Scroll Screen Up One Row
1118 SizeAttribute
= LastRow
* MaxColumn
;
1121 NullAttributes
+ MaxColumn
,
1122 SizeAttribute
* sizeof (INT32
)
1126 // Each row has an ending CHAR_NULL. So one more character each line
1127 // for DevNullScreen than DevNullAttributes
1129 SizeScreen
= SizeAttribute
+ LastRow
;
1132 NullScreen
+ (MaxColumn
+ 1),
1133 SizeScreen
* sizeof (CHAR16
)
1137 // Print Blank Line at last line
1139 Screen
= NullScreen
+ SizeScreen
;
1140 Attribute
= NullAttributes
+ SizeAttribute
;
1142 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1144 *Attribute
= Mode
->Attribute
;
1151 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1153 // Move the cursor to the beginning of the current row.
1155 Mode
->CursorColumn
= 0;
1159 // Print the character at the current cursor position and
1160 // move the cursor right one column. If this moves the cursor
1161 // past the right edge of the display, then the line should wrap to
1162 // the beginning of the next line. This is equivalent to inserting
1163 // a CR and an LF. Note that if the cursor is at the bottom of the
1164 // display, and the line wraps, then the display will be scrolled
1167 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1169 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1170 if (*WString
== CHAR_NULL
) {
1174 if (*WString
== CHAR_BACKSPACE
) {
1178 if (*WString
== CHAR_LINEFEED
) {
1182 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1186 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
1187 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
1192 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1194 // If a wide char is at the rightmost column, then move the char
1195 // to the beginning of the next row
1197 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1198 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1200 Mode
->CursorColumn
++;
1202 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1203 NullAttributes
[Index
] = Mode
->Attribute
;
1204 if (CurrentWidth
== 1) {
1205 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1207 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1208 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1211 Index
+= CurrentWidth
;
1213 Mode
->CursorColumn
+= CurrentWidth
;
1217 // At the end of line, output carriage return and line feed
1219 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1220 DevNullTextOutOutputString (Private
, mCrLfString
);
1229 DevNullTextOutSetMode (
1230 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1235 Routine Description:
1236 Sets the output device(s) to a specified mode.
1239 Private - Private data structure pointer.
1240 ModeNumber - The mode number to set.
1243 EFI_SUCCESS - The requested text mode was set.
1244 EFI_DEVICE_ERROR - The device had an error and
1245 could not complete the request.
1246 EFI_UNSUPPORTED - The mode number was not valid.
1247 EFI_OUT_OF_RESOURCES - Out of resources.
1254 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1257 // No extra check for ModeNumber here, as it has been checked in
1258 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1260 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1262 Column
= Mode
->Columns
;
1264 if (Row
<= 0 && Column
<= 0) {
1265 return EFI_UNSUPPORTED
;
1268 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1270 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1271 Private
->DevNullColumns
= Column
;
1272 Private
->DevNullRows
= Row
;
1274 gBS
->FreePool (Private
->DevNullScreen
);
1276 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1277 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1278 if (Private
->DevNullScreen
== NULL
) {
1279 return EFI_OUT_OF_RESOURCES
;
1282 gBS
->FreePool (Private
->DevNullAttributes
);
1284 Size
= Row
* Column
* sizeof (INT32
);
1285 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1286 if (Private
->DevNullAttributes
== NULL
) {
1287 return EFI_OUT_OF_RESOURCES
;
1291 DevNullTextOutClearScreen (Private
);
1297 DevNullTextOutClearScreen (
1298 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1302 Routine Description:
1303 Clears the output device(s) display to the currently selected background
1307 Private - Protocol instance pointer.
1310 EFI_SUCCESS - The operation completed successfully.
1311 EFI_DEVICE_ERROR - The device had an error and
1312 could not complete the request.
1313 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1321 INT32 CurrentAttribute
;
1324 // Clear the DevNull Text Out Buffers.
1325 // The screen is filled with spaces.
1326 // The attributes are all synced with the current Simple Text Out Attribute
1328 Screen
= Private
->DevNullScreen
;
1329 Attributes
= Private
->DevNullAttributes
;
1330 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1332 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1333 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1335 *Attributes
= CurrentAttribute
;
1338 // Each line of the screen has a NULL on the end so we must skip over it
1343 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1345 return DevNullTextOutEnableCursor (Private
, TRUE
);
1349 DevNullTextOutSetCursorPosition (
1350 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1356 Routine Description:
1357 Sets the current coordinates of the cursor position
1360 Private - Protocol instance pointer.
1361 Column, Row - the position to set the cursor to. Must be greater than or
1362 equal to zero and less than the number of columns and rows
1366 EFI_SUCCESS - The operation completed successfully.
1367 EFI_DEVICE_ERROR - The device had an error and
1368 could not complete the request.
1369 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1370 cursor position is invalid for the current mode.
1375 // No need to do extra check here as whether (Column, Row) is valid has
1376 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1377 // always be supported.
1379 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1380 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1386 DevNullTextOutEnableCursor (
1387 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1391 Routine Description:
1393 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1394 In this driver, the cursor cannot be hidden.
1398 Private - Indicates the calling context.
1400 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1401 is set to be invisible.
1405 EFI_SUCCESS - The request is valid.
1410 Private
->TextOutMode
.CursorVisible
= Visible
;
1416 DevNullSyncGopStdOut (
1417 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1420 Routine Description:
1421 Take the DevNull TextOut device and update the Simple Text Out on every
1425 Private - Indicates the calling context.
1428 EFI_SUCCESS - The request is valid.
1429 other - Return status of TextOut->OutputString ()
1434 EFI_STATUS ReturnStatus
;
1439 UINTN CurrentColumn
;
1442 INT32 StartAttribute
;
1443 BOOLEAN StartCursorState
;
1448 CHAR16
*ScreenStart
;
1449 INT32 CurrentAttribute
;
1451 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
1454 // Save the devices Attributes, Cursor enable state and location
1456 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1457 StartRow
= Private
->TextOutMode
.CursorRow
;
1458 StartAttribute
= Private
->TextOutMode
.Attribute
;
1459 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1461 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1463 Sto
= Private
->TextOutList
[List
].TextOut
;
1466 // Skip non GOP/UGA devices
1468 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1469 Sto
->EnableCursor (Sto
, FALSE
);
1470 Sto
->ClearScreen (Sto
);
1474 ReturnStatus
= EFI_SUCCESS
;
1475 Screen
= Private
->DevNullScreen
;
1476 Attributes
= Private
->DevNullAttributes
;
1477 MaxColumn
= Private
->DevNullColumns
;
1479 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1481 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1483 if (Row
== (Private
->DevNullRows
- 1)) {
1485 // Don't ever sync the last character as it will scroll the screen
1487 Screen
[MaxColumn
- 1] = 0x00;
1491 while (Column
< MaxColumn
) {
1492 if (Screen
[Column
]) {
1493 CurrentAttribute
= Attributes
[Column
];
1494 CurrentColumn
= Column
;
1495 ScreenStart
= &Screen
[Column
];
1498 // the line end is alway 0x0. So Column should be less than MaxColumn
1499 // It should be still in the same row
1501 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1503 if (Attributes
[Column
] != CurrentAttribute
) {
1510 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1518 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1520 Sto
= Private
->TextOutList
[List
].TextOut
;
1523 // Skip non GOP/UGA devices
1525 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1526 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1527 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1528 Status
= Sto
->OutputString (Sto
, Buffer
);
1529 if (EFI_ERROR (Status
)) {
1530 ReturnStatus
= Status
;
1541 // Restore the devices Attributes, Cursor enable state and location
1543 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1544 Sto
= Private
->TextOutList
[List
].TextOut
;
1547 // Skip non GOP/UGA devices
1549 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1550 Sto
->SetAttribute (Sto
, StartAttribute
);
1551 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1552 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1553 if (EFI_ERROR (Status
)) {
1554 ReturnStatus
= Status
;
1559 gBS
->FreePool (Buffer
);
1561 return ReturnStatus
;