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
;
360 DevNullGraphicsOutputBlt (
361 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
362 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
363 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
366 IN UINTN DestinationX
,
367 IN UINTN DestinationY
,
370 IN UINTN Delta OPTIONAL
375 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
376 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
377 UINTN HorizontalResolution
;
378 UINTN VerticalResolution
;
380 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
381 return EFI_INVALID_PARAMETER
;
384 if (Width
== 0 || Height
== 0) {
385 return EFI_INVALID_PARAMETER
;
389 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
392 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
393 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
396 // We need to fill the Virtual Screen buffer with the blt data.
398 if (BltOperation
== EfiBltVideoToBltBuffer
) {
400 // Video to BltBuffer: Source is Video, destination is BltBuffer
402 if ((SourceY
+ Height
) > VerticalResolution
) {
403 return EFI_INVALID_PARAMETER
;
406 if ((SourceX
+ Width
) > HorizontalResolution
) {
407 return EFI_INVALID_PARAMETER
;
410 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
411 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
413 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
414 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
415 ScreenPtr
+= HorizontalResolution
;
420 // BltBuffer to Video: Source is BltBuffer, destination is Video
422 if (DestinationY
+ Height
> VerticalResolution
) {
423 return EFI_INVALID_PARAMETER
;
426 if (DestinationX
+ Width
> HorizontalResolution
) {
427 return EFI_INVALID_PARAMETER
;
430 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
433 if (BltOperation
== EfiBltVideoFill
) {
434 for (Index
= 0; Index
< Width
; Index
++) {
435 ScreenPtr
[Index
] = *BltBuffer
;
438 if (BltOperation
== EfiBltBufferToVideo
) {
439 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
441 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
444 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
447 ScreenPtr
+= HorizontalResolution
;
458 ConSpliterGraphicsOutputBlt (
459 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
460 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
461 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
464 IN UINTN DestinationX
,
465 IN UINTN DestinationY
,
468 IN UINTN Delta OPTIONAL
473 The following table defines actions for BltOperations:
474 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
475 directly to every pixel of the video display rectangle
476 (DestinationX, DestinationY)
477 (DestinationX + Width, DestinationY + Height).
478 Only one pixel will be used from the BltBuffer. Delta is NOT used.
479 EfiBltVideoToBltBuffer - Read data from the video display rectangle
480 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
481 the BltBuffer rectangle (DestinationX, DestinationY )
482 (DestinationX + Width, DestinationY + Height). If DestinationX or
483 DestinationY is not zero then Delta must be set to the length in bytes
484 of a row in the BltBuffer.
485 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
486 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
487 video display rectangle (DestinationX, DestinationY)
488 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
489 not zero then Delta must be set to the length in bytes of a row in the
491 EfiBltVideoToVideo - Copy from the video display rectangle
492 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
493 to the video display rectangle (DestinationX, DestinationY)
494 (DestinationX + Width, DestinationY + Height).
495 The BltBuffer and Delta are not used in this mode.
498 This - Protocol instance pointer.
499 BltBuffer - Buffer containing data to blit into video buffer. This
500 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
501 BltOperation - Operation to perform on BlitBuffer and video memory
502 SourceX - X coordinate of source for the BltBuffer.
503 SourceY - Y coordinate of source for the BltBuffer.
504 DestinationX - X coordinate of destination for the BltBuffer.
505 DestinationY - Y coordinate of destination for the BltBuffer.
506 Width - Width of rectangle in BltBuffer in pixels.
507 Height - Hight of rectangle in BltBuffer in pixels.
511 EFI_SUCCESS - The Blt operation completed.
512 EFI_INVALID_PARAMETER - BltOperation is not valid.
513 EFI_DEVICE_ERROR - A hardware error occured writting to the video
519 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
521 EFI_STATUS ReturnStatus
;
522 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
523 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
525 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
528 // Sync up DevNull GOP device
530 ReturnStatus
= DevNullGraphicsOutputBlt (
543 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
547 // return the worst status met
549 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
550 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
551 if (GraphicsOutput
!= NULL
) {
552 Status
= GraphicsOutput
->Blt (
564 if (EFI_ERROR (Status
)) {
565 ReturnStatus
= Status
;
566 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
568 // Only need to read the data into buffer one time
574 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
575 if (UgaDraw
!= NULL
) {
576 Status
= UgaDraw
->Blt (
578 (EFI_UGA_PIXEL
*) BltBuffer
,
579 (EFI_UGA_BLT_OPERATION
) BltOperation
,
588 if (EFI_ERROR (Status
)) {
589 ReturnStatus
= Status
;
590 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
592 // Only need to read the data into buffer one time
604 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
605 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
606 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
609 if (GraphicsOutput
!= NULL
) {
610 return GraphicsOutput
->Blt (
612 Private
->GraphicsOutputBlt
,
618 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
619 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
623 return UgaDraw
->Blt (
625 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
626 EfiUgaBltBufferToVideo
,
631 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
632 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
642 ConSpliterUgaDrawGetMode (
643 IN EFI_UGA_DRAW_PROTOCOL
*This
,
644 OUT UINT32
*HorizontalResolution
,
645 OUT UINT32
*VerticalResolution
,
646 OUT UINT32
*ColorDepth
,
647 OUT UINT32
*RefreshRate
652 Return the current video mode information.
655 This - Protocol instance pointer.
656 HorizontalResolution - Current video horizontal resolution in pixels
657 VerticalResolution - Current video vertical resolution in pixels
658 ColorDepth - Current video color depth in bits per pixel
659 RefreshRate - Current video refresh rate in Hz.
662 EFI_SUCCESS - Mode information returned.
663 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
664 EFI_INVALID_PARAMETER - One of the input args was NULL.
668 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
670 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
671 return EFI_INVALID_PARAMETER
;
674 // retrieve private data
676 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
678 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
679 *VerticalResolution
= Private
->UgaVerticalResolution
;
680 *ColorDepth
= Private
->UgaColorDepth
;
681 *RefreshRate
= Private
->UgaRefreshRate
;
688 ConSpliterUgaDrawSetMode (
689 IN EFI_UGA_DRAW_PROTOCOL
*This
,
690 IN UINT32 HorizontalResolution
,
691 IN UINT32 VerticalResolution
,
692 IN UINT32 ColorDepth
,
693 IN UINT32 RefreshRate
698 Return the current video mode information.
701 This - Protocol instance pointer.
702 HorizontalResolution - Current video horizontal resolution in pixels
703 VerticalResolution - Current video vertical resolution in pixels
704 ColorDepth - Current video color depth in bits per pixel
705 RefreshRate - Current video refresh rate in Hz.
708 EFI_SUCCESS - Mode information returned.
709 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
710 EFI_OUT_OF_RESOURCES - Out of resources.
715 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
717 EFI_STATUS ReturnStatus
;
720 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
723 // UgaDevNullSetMode ()
725 ReturnStatus
= EFI_SUCCESS
;
728 // Free the old version
730 gBS
->FreePool (Private
->UgaBlt
);
733 // Allocate the virtual Blt buffer
735 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
736 Private
->UgaBlt
= AllocateZeroPool (Size
);
737 if (Private
->UgaBlt
== NULL
) {
738 return EFI_OUT_OF_RESOURCES
;
742 // Update the Mode data
744 Private
->UgaHorizontalResolution
= HorizontalResolution
;
745 Private
->UgaVerticalResolution
= VerticalResolution
;
746 Private
->UgaColorDepth
= ColorDepth
;
747 Private
->UgaRefreshRate
= RefreshRate
;
749 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
753 // return the worst status met
755 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
756 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
757 Status
= Private
->TextOutList
[Index
].UgaDraw
->SetMode (
758 Private
->TextOutList
[Index
].UgaDraw
,
759 HorizontalResolution
,
764 if (EFI_ERROR (Status
)) {
765 ReturnStatus
= Status
;
775 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
776 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
777 IN EFI_UGA_BLT_OPERATION BltOperation
,
780 IN UINTN DestinationX
,
781 IN UINTN DestinationY
,
784 IN UINTN Delta OPTIONAL
789 EFI_UGA_PIXEL
*BltPtr
;
790 EFI_UGA_PIXEL
*ScreenPtr
;
791 UINT32 HorizontalResolution
;
792 UINT32 VerticalResolution
;
794 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
795 return EFI_INVALID_PARAMETER
;
798 if (Width
== 0 || Height
== 0) {
799 return EFI_INVALID_PARAMETER
;
803 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
806 HorizontalResolution
= Private
->UgaHorizontalResolution
;
807 VerticalResolution
= Private
->UgaVerticalResolution
;
810 // We need to fill the Virtual Screen buffer with the blt data.
812 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
814 // Video to BltBuffer: Source is Video, destination is BltBuffer
816 if ((SourceY
+ Height
) > VerticalResolution
) {
817 return EFI_INVALID_PARAMETER
;
820 if ((SourceX
+ Width
) > HorizontalResolution
) {
821 return EFI_INVALID_PARAMETER
;
824 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
825 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
827 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
828 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
829 ScreenPtr
+= HorizontalResolution
;
834 // BltBuffer to Video: Source is BltBuffer, destination is Video
836 if (DestinationY
+ Height
> VerticalResolution
) {
837 return EFI_INVALID_PARAMETER
;
840 if (DestinationX
+ Width
> HorizontalResolution
) {
841 return EFI_INVALID_PARAMETER
;
844 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
847 if (BltOperation
== EfiUgaVideoFill
) {
848 for (Index
= 0; Index
< Width
; Index
++) {
849 ScreenPtr
[Index
] = *BltBuffer
;
852 if (BltOperation
== EfiUgaBltBufferToVideo
) {
853 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
855 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
858 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
861 ScreenPtr
+= HorizontalResolution
;
872 ConSpliterUgaDrawBlt (
873 IN EFI_UGA_DRAW_PROTOCOL
*This
,
874 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
875 IN EFI_UGA_BLT_OPERATION BltOperation
,
878 IN UINTN DestinationX
,
879 IN UINTN DestinationY
,
882 IN UINTN Delta OPTIONAL
887 The following table defines actions for BltOperations:
888 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
889 directly to every pixel of the video display rectangle
890 (DestinationX, DestinationY)
891 (DestinationX + Width, DestinationY + Height).
892 Only one pixel will be used from the BltBuffer. Delta is NOT used.
893 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
894 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
895 the BltBuffer rectangle (DestinationX, DestinationY )
896 (DestinationX + Width, DestinationY + Height). If DestinationX or
897 DestinationY is not zero then Delta must be set to the length in bytes
898 of a row in the BltBuffer.
899 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
900 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
901 video display rectangle (DestinationX, DestinationY)
902 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
903 not zero then Delta must be set to the length in bytes of a row in the
905 EfiUgaVideoToVideo - Copy from the video display rectangle
906 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
907 to the video display rectangle (DestinationX, DestinationY)
908 (DestinationX + Width, DestinationY + Height).
909 The BltBuffer and Delta are not used in this mode.
912 This - Protocol instance pointer.
913 BltBuffer - Buffer containing data to blit into video buffer. This
914 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
915 BltOperation - Operation to perform on BlitBuffer and video memory
916 SourceX - X coordinate of source for the BltBuffer.
917 SourceY - Y coordinate of source for the BltBuffer.
918 DestinationX - X coordinate of destination for the BltBuffer.
919 DestinationY - Y coordinate of destination for the BltBuffer.
920 Width - Width of rectangle in BltBuffer in pixels.
921 Height - Hight of rectangle in BltBuffer in pixels.
925 EFI_SUCCESS - The Blt operation completed.
926 EFI_INVALID_PARAMETER - BltOperation is not valid.
927 EFI_DEVICE_ERROR - A hardware error occured writting to the video
933 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
935 EFI_STATUS ReturnStatus
;
937 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
940 // Sync up DevNull UGA device
942 ReturnStatus
= DevNullUgaBlt (
954 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
958 // return the worst status met
960 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
961 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
962 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
963 Private
->TextOutList
[Index
].UgaDraw
,
974 if (EFI_ERROR (Status
)) {
975 ReturnStatus
= Status
;
976 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
978 // Only need to read the data into buffer one time
990 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
991 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
994 return UgaDraw
->Blt (
997 EfiUgaBltBufferToVideo
,
1002 Private
->UgaHorizontalResolution
,
1003 Private
->UgaVerticalResolution
,
1004 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1010 DevNullTextOutOutputString (
1011 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1016 Routine Description:
1017 Write a Unicode string to the output device.
1020 Private - Pointer to the console output splitter's private data. It
1021 indicates the calling context.
1022 WString - The NULL-terminated Unicode string to be displayed on the output
1023 device(s). All output devices must also support the Unicode
1024 drawing defined in this file.
1027 EFI_SUCCESS - The string was output to the device.
1028 EFI_DEVICE_ERROR - The device reported an error while attempting to
1030 EFI_UNSUPPORTED - The output device's mode is not currently in a
1032 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1033 characters in the Unicode string could not be
1034 rendered and were skipped.
1039 UINTN SizeAttribute
;
1041 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1048 INT32
*NullAttributes
;
1053 Mode
= &Private
->TextOutMode
;
1054 NullScreen
= Private
->DevNullScreen
;
1055 NullAttributes
= Private
->DevNullAttributes
;
1056 LastRow
= Private
->DevNullRows
- 1;
1057 MaxColumn
= Private
->DevNullColumns
;
1059 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1067 if (*WString
== CHAR_BACKSPACE
) {
1069 // If the cursor is at the left edge of the display, then move the cursor
1072 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1074 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1078 // If the cursor is not at the left edge of the display,
1079 // then move the cursor left one column.
1081 if (Mode
->CursorColumn
> 0) {
1082 Mode
->CursorColumn
--;
1083 if (Mode
->CursorColumn
> 0 &&
1084 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1086 Mode
->CursorColumn
--;
1089 // Insert an extra backspace
1091 InsertChar
= CHAR_BACKSPACE
;
1096 InsertChar
= TempChar
;
1109 } else if (*WString
== CHAR_LINEFEED
) {
1111 // If the cursor is at the bottom of the display,
1112 // then scroll the display one row, and do not update
1113 // the cursor position. Otherwise, move the cursor down one row.
1115 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1117 // Scroll Screen Up One Row
1119 SizeAttribute
= LastRow
* MaxColumn
;
1122 NullAttributes
+ MaxColumn
,
1123 SizeAttribute
* sizeof (INT32
)
1127 // Each row has an ending CHAR_NULL. So one more character each line
1128 // for DevNullScreen than DevNullAttributes
1130 SizeScreen
= SizeAttribute
+ LastRow
;
1133 NullScreen
+ (MaxColumn
+ 1),
1134 SizeScreen
* sizeof (CHAR16
)
1138 // Print Blank Line at last line
1140 Screen
= NullScreen
+ SizeScreen
;
1141 Attribute
= NullAttributes
+ SizeAttribute
;
1143 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1145 *Attribute
= Mode
->Attribute
;
1152 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1154 // Move the cursor to the beginning of the current row.
1156 Mode
->CursorColumn
= 0;
1160 // Print the character at the current cursor position and
1161 // move the cursor right one column. If this moves the cursor
1162 // past the right edge of the display, then the line should wrap to
1163 // the beginning of the next line. This is equivalent to inserting
1164 // a CR and an LF. Note that if the cursor is at the bottom of the
1165 // display, and the line wraps, then the display will be scrolled
1168 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1170 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1171 if (*WString
== CHAR_NULL
) {
1175 if (*WString
== CHAR_BACKSPACE
) {
1179 if (*WString
== CHAR_LINEFEED
) {
1183 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1187 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
1188 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
1193 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1195 // If a wide char is at the rightmost column, then move the char
1196 // to the beginning of the next row
1198 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1199 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1201 Mode
->CursorColumn
++;
1203 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1204 NullAttributes
[Index
] = Mode
->Attribute
;
1205 if (CurrentWidth
== 1) {
1206 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1208 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1209 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1212 Index
+= CurrentWidth
;
1214 Mode
->CursorColumn
+= CurrentWidth
;
1218 // At the end of line, output carriage return and line feed
1220 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1221 DevNullTextOutOutputString (Private
, mCrLfString
);
1230 DevNullTextOutSetMode (
1231 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1236 Routine Description:
1237 Sets the output device(s) to a specified mode.
1240 Private - Private data structure pointer.
1241 ModeNumber - The mode number to set.
1244 EFI_SUCCESS - The requested text mode was set.
1245 EFI_DEVICE_ERROR - The device had an error and
1246 could not complete the request.
1247 EFI_UNSUPPORTED - The mode number was not valid.
1248 EFI_OUT_OF_RESOURCES - Out of resources.
1255 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1258 // No extra check for ModeNumber here, as it has been checked in
1259 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1261 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1263 Column
= Mode
->Columns
;
1265 if (Row
<= 0 && Column
<= 0) {
1266 return EFI_UNSUPPORTED
;
1269 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1271 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1272 Private
->DevNullColumns
= Column
;
1273 Private
->DevNullRows
= Row
;
1275 gBS
->FreePool (Private
->DevNullScreen
);
1277 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1278 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1279 if (Private
->DevNullScreen
== NULL
) {
1280 return EFI_OUT_OF_RESOURCES
;
1283 gBS
->FreePool (Private
->DevNullAttributes
);
1285 Size
= Row
* Column
* sizeof (INT32
);
1286 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1287 if (Private
->DevNullAttributes
== NULL
) {
1288 return EFI_OUT_OF_RESOURCES
;
1292 DevNullTextOutClearScreen (Private
);
1298 DevNullTextOutClearScreen (
1299 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1303 Routine Description:
1304 Clears the output device(s) display to the currently selected background
1308 Private - Protocol instance pointer.
1311 EFI_SUCCESS - The operation completed successfully.
1312 EFI_DEVICE_ERROR - The device had an error and
1313 could not complete the request.
1314 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1322 INT32 CurrentAttribute
;
1325 // Clear the DevNull Text Out Buffers.
1326 // The screen is filled with spaces.
1327 // The attributes are all synced with the current Simple Text Out Attribute
1329 Screen
= Private
->DevNullScreen
;
1330 Attributes
= Private
->DevNullAttributes
;
1331 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1333 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1334 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1336 *Attributes
= CurrentAttribute
;
1339 // Each line of the screen has a NULL on the end so we must skip over it
1344 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1346 return DevNullTextOutEnableCursor (Private
, TRUE
);
1350 DevNullTextOutSetCursorPosition (
1351 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1357 Routine Description:
1358 Sets the current coordinates of the cursor position
1361 Private - Protocol instance pointer.
1362 Column, Row - the position to set the cursor to. Must be greater than or
1363 equal to zero and less than the number of columns and rows
1367 EFI_SUCCESS - The operation completed successfully.
1368 EFI_DEVICE_ERROR - The device had an error and
1369 could not complete the request.
1370 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1371 cursor position is invalid for the current mode.
1376 // No need to do extra check here as whether (Column, Row) is valid has
1377 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1378 // always be supported.
1380 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1381 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1387 DevNullTextOutEnableCursor (
1388 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1392 Routine Description:
1394 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1395 In this driver, the cursor cannot be hidden.
1399 Private - Indicates the calling context.
1401 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1402 is set to be invisible.
1406 EFI_SUCCESS - The request is valid.
1411 Private
->TextOutMode
.CursorVisible
= Visible
;
1417 DevNullSyncGopStdOut (
1418 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1421 Routine Description:
1422 Take the DevNull TextOut device and update the Simple Text Out on every
1426 Private - Indicates the calling context.
1429 EFI_SUCCESS - The request is valid.
1430 other - Return status of TextOut->OutputString ()
1435 EFI_STATUS ReturnStatus
;
1440 UINTN CurrentColumn
;
1443 INT32 StartAttribute
;
1444 BOOLEAN StartCursorState
;
1449 CHAR16
*ScreenStart
;
1450 INT32 CurrentAttribute
;
1452 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
1455 // Save the devices Attributes, Cursor enable state and location
1457 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1458 StartRow
= Private
->TextOutMode
.CursorRow
;
1459 StartAttribute
= Private
->TextOutMode
.Attribute
;
1460 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1462 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1464 Sto
= Private
->TextOutList
[List
].TextOut
;
1467 // Skip non GOP/UGA devices
1469 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1470 Sto
->EnableCursor (Sto
, FALSE
);
1471 Sto
->ClearScreen (Sto
);
1475 ReturnStatus
= EFI_SUCCESS
;
1476 Screen
= Private
->DevNullScreen
;
1477 Attributes
= Private
->DevNullAttributes
;
1478 MaxColumn
= Private
->DevNullColumns
;
1480 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1482 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1484 if (Row
== (Private
->DevNullRows
- 1)) {
1486 // Don't ever sync the last character as it will scroll the screen
1488 Screen
[MaxColumn
- 1] = 0x00;
1492 while (Column
< MaxColumn
) {
1493 if (Screen
[Column
]) {
1494 CurrentAttribute
= Attributes
[Column
];
1495 CurrentColumn
= Column
;
1496 ScreenStart
= &Screen
[Column
];
1499 // the line end is alway 0x0. So Column should be less than MaxColumn
1500 // It should be still in the same row
1502 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1504 if (Attributes
[Column
] != CurrentAttribute
) {
1511 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1519 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1521 Sto
= Private
->TextOutList
[List
].TextOut
;
1524 // Skip non GOP/UGA devices
1526 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1527 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1528 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1529 Status
= Sto
->OutputString (Sto
, Buffer
);
1530 if (EFI_ERROR (Status
)) {
1531 ReturnStatus
= Status
;
1542 // Restore the devices Attributes, Cursor enable state and location
1544 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1545 Sto
= Private
->TextOutList
[List
].TextOut
;
1548 // Skip non GOP/UGA devices
1550 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1551 Sto
->SetAttribute (Sto
, StartAttribute
);
1552 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1553 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1554 if (EFI_ERROR (Status
)) {
1555 ReturnStatus
= Status
;
1560 gBS
->FreePool (Buffer
);
1562 return ReturnStatus
;