3 Copyright (c) 2006 - 2007, 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 // Judge current mode with wanted mode at first.
122 if (Private
->ConsoleOutputMode
== Mode
) {
127 TextAndGop
= &Private
->TextOutList
[0];
128 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
129 if ((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
)) {
135 if ((!Supported
) && (Mode
== EfiConsoleControlScreenGraphics
)) {
136 return EFI_UNSUPPORTED
;
139 Private
->ConsoleOutputMode
= Mode
;
141 TextAndGop
= &Private
->TextOutList
[0];
142 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++, TextAndGop
++) {
144 TextAndGop
->TextOutEnabled
= TRUE
;
146 // If we are going into Graphics mode disable ConOut to any UGA device
148 if ((Mode
== EfiConsoleControlScreenGraphics
) &&((TextAndGop
->GraphicsOutput
!= NULL
) || (TextAndGop
->UgaDraw
!= NULL
))) {
149 TextAndGop
->TextOutEnabled
= FALSE
;
150 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
151 DevNullGopSync (Private
, TextAndGop
->GraphicsOutput
, TextAndGop
->UgaDraw
);
153 DevNullUgaSync (Private
, TextAndGop
->UgaDraw
);
158 if (Mode
== EfiConsoleControlScreenText
) {
159 DevNullSyncGopStdOut (Private
);
165 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
168 ConSpliterGraphicsOutputQueryMode (
169 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
170 IN UINT32 ModeNumber
,
171 OUT UINTN
*SizeOfInfo
,
172 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
177 Return the current video mode information.
180 This - Protocol instance pointer.
181 ModeNumber - The mode number to return information on.
182 Info - Caller allocated buffer that returns information about ModeNumber.
183 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
186 EFI_SUCCESS - Mode information returned.
187 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
188 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
189 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
190 EFI_INVALID_PARAMETER - One of the input args was NULL.
194 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
195 TEXT_OUT_GOP_MODE
*Mode
;
197 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
198 return EFI_INVALID_PARAMETER
;
202 // retrieve private data
204 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
206 if (Private
->HardwareNeedsStarting
) {
207 return EFI_NOT_STARTED
;
210 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
213 return EFI_OUT_OF_RESOURCES
;
216 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
218 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
219 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
220 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
221 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
222 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
229 ConSpliterGraphicsOutputSetMode (
230 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
237 Graphics output protocol interface to set video mode
240 This - Protocol instance pointer.
241 ModeNumber - The mode number to be set.
244 EFI_SUCCESS - Graphics mode was changed.
245 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
246 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
251 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
253 EFI_STATUS ReturnStatus
;
254 TEXT_OUT_GOP_MODE
*Mode
;
256 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
259 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
260 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
262 if (ModeNumber
>= This
->Mode
->MaxMode
) {
263 return EFI_UNSUPPORTED
;
266 if (ModeNumber
== This
->Mode
->Mode
) {
270 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
273 // GopDevNullSetMode ()
275 ReturnStatus
= EFI_SUCCESS
;
278 // Free the old version
280 if (Private
->GraphicsOutputBlt
!= NULL
) {
281 FreePool (Private
->GraphicsOutputBlt
);
285 // Allocate the virtual Blt buffer
287 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
288 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
289 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
291 if (Private
->GraphicsOutputBlt
== NULL
) {
292 return EFI_OUT_OF_RESOURCES
;
295 if (!Private
->HardwareNeedsStarting
) {
296 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
297 return EFI_UNSUPPORTED
;
301 // return the worst status met
303 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
304 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
305 if (GraphicsOutput
!= NULL
) {
307 // Find corresponding ModeNumber of this GraphicsOutput instance
309 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
310 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
311 if (EFI_ERROR (Status
)) {
314 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
321 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
322 if (EFI_ERROR (Status
)) {
323 ReturnStatus
= Status
;
327 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
328 if (UgaDraw
!= NULL
) {
329 Status
= UgaDraw
->SetMode (
331 Mode
->HorizontalResolution
,
332 Mode
->VerticalResolution
,
336 if (EFI_ERROR (Status
)) {
337 ReturnStatus
= Status
;
342 This
->Mode
->Mode
= ModeNumber
;
344 Info
= This
->Mode
->Info
;
345 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
346 Info
->VerticalResolution
= Mode
->VerticalResolution
;
347 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
350 // Information is not enough here, so the following items remain unchanged:
351 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
352 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
353 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
356 Private
->HardwareNeedsStarting
= FALSE
;
363 DevNullGraphicsOutputBlt (
364 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
365 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
366 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
369 IN UINTN DestinationX
,
370 IN UINTN DestinationY
,
373 IN UINTN Delta OPTIONAL
379 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
380 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
381 UINTN HorizontalResolution
;
382 UINTN VerticalResolution
;
384 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
385 return EFI_INVALID_PARAMETER
;
388 if (Width
== 0 || Height
== 0) {
389 return EFI_INVALID_PARAMETER
;
393 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
396 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
397 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
400 // We need to fill the Virtual Screen buffer with the blt data.
402 if (BltOperation
== EfiBltVideoToBltBuffer
) {
404 // Video to BltBuffer: Source is Video, destination is BltBuffer
406 if ((SourceY
+ Height
) > VerticalResolution
) {
407 return EFI_INVALID_PARAMETER
;
410 if ((SourceX
+ Width
) > HorizontalResolution
) {
411 return EFI_INVALID_PARAMETER
;
414 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
415 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
417 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
418 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
419 ScreenPtr
+= HorizontalResolution
;
424 // BltBuffer to Video: Source is BltBuffer, destination is Video
426 if (DestinationY
+ Height
> VerticalResolution
) {
427 return EFI_INVALID_PARAMETER
;
430 if (DestinationX
+ Width
> HorizontalResolution
) {
431 return EFI_INVALID_PARAMETER
;
434 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
436 // Copy backwards, only care the Video to Video Blt
438 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
439 SrcY
= SourceY
+ Height
- 1;
443 // Copy forwards, for other cases
445 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
450 while (Height
!= 0) {
451 if (BltOperation
== EfiBltVideoFill
) {
452 for (Index
= 0; Index
< Width
; Index
++) {
453 ScreenPtr
[Index
] = *BltBuffer
;
456 if (BltOperation
== EfiBltBufferToVideo
) {
457 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
459 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
462 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
466 ScreenPtr
+= HorizontalResolution
;
469 ScreenPtr
-= HorizontalResolution
;
481 ConSpliterGraphicsOutputBlt (
482 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
483 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
484 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
487 IN UINTN DestinationX
,
488 IN UINTN DestinationY
,
491 IN UINTN Delta OPTIONAL
496 The following table defines actions for BltOperations:
497 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
498 directly to every pixel of the video display rectangle
499 (DestinationX, DestinationY)
500 (DestinationX + Width, DestinationY + Height).
501 Only one pixel will be used from the BltBuffer. Delta is NOT used.
502 EfiBltVideoToBltBuffer - Read data from the video display rectangle
503 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
504 the BltBuffer rectangle (DestinationX, DestinationY )
505 (DestinationX + Width, DestinationY + Height). If DestinationX or
506 DestinationY is not zero then Delta must be set to the length in bytes
507 of a row in the BltBuffer.
508 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
509 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
510 video display rectangle (DestinationX, DestinationY)
511 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
512 not zero then Delta must be set to the length in bytes of a row in the
514 EfiBltVideoToVideo - Copy from the video display rectangle
515 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
516 to the video display rectangle (DestinationX, DestinationY)
517 (DestinationX + Width, DestinationY + Height).
518 The BltBuffer and Delta are not used in this mode.
521 This - Protocol instance pointer.
522 BltBuffer - Buffer containing data to blit into video buffer. This
523 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
524 BltOperation - Operation to perform on BlitBuffer and video memory
525 SourceX - X coordinate of source for the BltBuffer.
526 SourceY - Y coordinate of source for the BltBuffer.
527 DestinationX - X coordinate of destination for the BltBuffer.
528 DestinationY - Y coordinate of destination for the BltBuffer.
529 Width - Width of rectangle in BltBuffer in pixels.
530 Height - Hight of rectangle in BltBuffer in pixels.
534 EFI_SUCCESS - The Blt operation completed.
535 EFI_INVALID_PARAMETER - BltOperation is not valid.
536 EFI_DEVICE_ERROR - A hardware error occured writting to the video
542 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
544 EFI_STATUS ReturnStatus
;
545 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
546 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
548 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
551 // Sync up DevNull GOP device
553 ReturnStatus
= DevNullGraphicsOutputBlt (
566 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
570 // return the worst status met
572 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
573 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
574 if (GraphicsOutput
!= NULL
) {
575 Status
= GraphicsOutput
->Blt (
587 if (EFI_ERROR (Status
)) {
588 ReturnStatus
= Status
;
589 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
591 // Only need to read the data into buffer one time
597 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
598 if (UgaDraw
!= NULL
) {
599 Status
= UgaDraw
->Blt (
601 (EFI_UGA_PIXEL
*) BltBuffer
,
602 (EFI_UGA_BLT_OPERATION
) BltOperation
,
611 if (EFI_ERROR (Status
)) {
612 ReturnStatus
= Status
;
613 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
615 // Only need to read the data into buffer one time
627 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
628 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
629 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
632 if (GraphicsOutput
!= NULL
) {
633 return GraphicsOutput
->Blt (
635 Private
->GraphicsOutputBlt
,
641 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
642 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
646 return UgaDraw
->Blt (
648 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
649 EfiUgaBltBufferToVideo
,
654 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
655 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
665 ConSpliterUgaDrawGetMode (
666 IN EFI_UGA_DRAW_PROTOCOL
*This
,
667 OUT UINT32
*HorizontalResolution
,
668 OUT UINT32
*VerticalResolution
,
669 OUT UINT32
*ColorDepth
,
670 OUT UINT32
*RefreshRate
675 Return the current video mode information.
678 This - Protocol instance pointer.
679 HorizontalResolution - Current video horizontal resolution in pixels
680 VerticalResolution - Current video vertical resolution in pixels
681 ColorDepth - Current video color depth in bits per pixel
682 RefreshRate - Current video refresh rate in Hz.
685 EFI_SUCCESS - Mode information returned.
686 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
687 EFI_INVALID_PARAMETER - One of the input args was NULL.
691 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
693 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
694 return EFI_INVALID_PARAMETER
;
697 // retrieve private data
699 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
701 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
702 *VerticalResolution
= Private
->UgaVerticalResolution
;
703 *ColorDepth
= Private
->UgaColorDepth
;
704 *RefreshRate
= Private
->UgaRefreshRate
;
711 ConSpliterUgaDrawSetMode (
712 IN EFI_UGA_DRAW_PROTOCOL
*This
,
713 IN UINT32 HorizontalResolution
,
714 IN UINT32 VerticalResolution
,
715 IN UINT32 ColorDepth
,
716 IN UINT32 RefreshRate
721 Return the current video mode information.
724 This - Protocol instance pointer.
725 HorizontalResolution - Current video horizontal resolution in pixels
726 VerticalResolution - Current video vertical resolution in pixels
727 ColorDepth - Current video color depth in bits per pixel
728 RefreshRate - Current video refresh rate in Hz.
731 EFI_SUCCESS - Mode information returned.
732 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
733 EFI_OUT_OF_RESOURCES - Out of resources.
738 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
740 EFI_STATUS ReturnStatus
;
743 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
746 // UgaDevNullSetMode ()
748 ReturnStatus
= EFI_SUCCESS
;
751 // Free the old version
753 FreePool (Private
->UgaBlt
);
756 // Allocate the virtual Blt buffer
758 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
759 Private
->UgaBlt
= AllocateZeroPool (Size
);
760 if (Private
->UgaBlt
== NULL
) {
761 return EFI_OUT_OF_RESOURCES
;
765 // Update the Mode data
767 Private
->UgaHorizontalResolution
= HorizontalResolution
;
768 Private
->UgaVerticalResolution
= VerticalResolution
;
769 Private
->UgaColorDepth
= ColorDepth
;
770 Private
->UgaRefreshRate
= RefreshRate
;
772 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
776 // return the worst status met
778 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
779 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
780 Status
= Private
->TextOutList
[Index
].UgaDraw
->SetMode (
781 Private
->TextOutList
[Index
].UgaDraw
,
782 HorizontalResolution
,
787 if (EFI_ERROR (Status
)) {
788 ReturnStatus
= Status
;
798 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
799 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
800 IN EFI_UGA_BLT_OPERATION BltOperation
,
803 IN UINTN DestinationX
,
804 IN UINTN DestinationY
,
807 IN UINTN Delta OPTIONAL
813 EFI_UGA_PIXEL
*BltPtr
;
814 EFI_UGA_PIXEL
*ScreenPtr
;
815 UINT32 HorizontalResolution
;
816 UINT32 VerticalResolution
;
818 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
819 return EFI_INVALID_PARAMETER
;
822 if (Width
== 0 || Height
== 0) {
823 return EFI_INVALID_PARAMETER
;
827 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
830 HorizontalResolution
= Private
->UgaHorizontalResolution
;
831 VerticalResolution
= Private
->UgaVerticalResolution
;
834 // We need to fill the Virtual Screen buffer with the blt data.
836 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
838 // Video to BltBuffer: Source is Video, destination is BltBuffer
840 if ((SourceY
+ Height
) > VerticalResolution
) {
841 return EFI_INVALID_PARAMETER
;
844 if ((SourceX
+ Width
) > HorizontalResolution
) {
845 return EFI_INVALID_PARAMETER
;
848 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
849 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
851 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
852 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
853 ScreenPtr
+= HorizontalResolution
;
858 // BltBuffer to Video: Source is BltBuffer, destination is Video
860 if (DestinationY
+ Height
> VerticalResolution
) {
861 return EFI_INVALID_PARAMETER
;
864 if (DestinationX
+ Width
> HorizontalResolution
) {
865 return EFI_INVALID_PARAMETER
;
868 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
870 // Copy backwards, only care the Video to Video Blt
872 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
873 SrcY
= SourceY
+ Height
- 1;
877 // Copy forwards, for other cases
879 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
884 while (Height
!= 0) {
885 if (BltOperation
== EfiUgaVideoFill
) {
886 for (Index
= 0; Index
< Width
; Index
++) {
887 ScreenPtr
[Index
] = *BltBuffer
;
890 if (BltOperation
== EfiUgaBltBufferToVideo
) {
891 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
893 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
896 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
900 ScreenPtr
+= HorizontalResolution
;
903 ScreenPtr
-= HorizontalResolution
;
915 ConSpliterUgaDrawBlt (
916 IN EFI_UGA_DRAW_PROTOCOL
*This
,
917 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
918 IN EFI_UGA_BLT_OPERATION BltOperation
,
921 IN UINTN DestinationX
,
922 IN UINTN DestinationY
,
925 IN UINTN Delta OPTIONAL
930 The following table defines actions for BltOperations:
931 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
932 directly to every pixel of the video display rectangle
933 (DestinationX, DestinationY)
934 (DestinationX + Width, DestinationY + Height).
935 Only one pixel will be used from the BltBuffer. Delta is NOT used.
936 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
937 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
938 the BltBuffer rectangle (DestinationX, DestinationY )
939 (DestinationX + Width, DestinationY + Height). If DestinationX or
940 DestinationY is not zero then Delta must be set to the length in bytes
941 of a row in the BltBuffer.
942 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
943 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
944 video display rectangle (DestinationX, DestinationY)
945 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
946 not zero then Delta must be set to the length in bytes of a row in the
948 EfiUgaVideoToVideo - Copy from the video display rectangle
949 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
950 to the video display rectangle (DestinationX, DestinationY)
951 (DestinationX + Width, DestinationY + Height).
952 The BltBuffer and Delta are not used in this mode.
955 This - Protocol instance pointer.
956 BltBuffer - Buffer containing data to blit into video buffer. This
957 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
958 BltOperation - Operation to perform on BlitBuffer and video memory
959 SourceX - X coordinate of source for the BltBuffer.
960 SourceY - Y coordinate of source for the BltBuffer.
961 DestinationX - X coordinate of destination for the BltBuffer.
962 DestinationY - Y coordinate of destination for the BltBuffer.
963 Width - Width of rectangle in BltBuffer in pixels.
964 Height - Hight of rectangle in BltBuffer in pixels.
968 EFI_SUCCESS - The Blt operation completed.
969 EFI_INVALID_PARAMETER - BltOperation is not valid.
970 EFI_DEVICE_ERROR - A hardware error occured writting to the video
976 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
978 EFI_STATUS ReturnStatus
;
980 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
983 // Sync up DevNull UGA device
985 ReturnStatus
= DevNullUgaBlt (
997 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1001 // return the worst status met
1003 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1004 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
1005 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1006 Private
->TextOutList
[Index
].UgaDraw
,
1017 if (EFI_ERROR (Status
)) {
1018 ReturnStatus
= Status
;
1019 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1021 // Only need to read the data into buffer one time
1028 return ReturnStatus
;
1033 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1034 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1037 return UgaDraw
->Blt (
1040 EfiUgaBltBufferToVideo
,
1045 Private
->UgaHorizontalResolution
,
1046 Private
->UgaVerticalResolution
,
1047 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1053 DevNullTextOutOutputString (
1054 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1059 Routine Description:
1060 Write a Unicode string to the output device.
1063 Private - Pointer to the console output splitter's private data. It
1064 indicates the calling context.
1065 WString - The NULL-terminated Unicode string to be displayed on the output
1066 device(s). All output devices must also support the Unicode
1067 drawing defined in this file.
1070 EFI_SUCCESS - The string was output to the device.
1071 EFI_DEVICE_ERROR - The device reported an error while attempting to
1073 EFI_UNSUPPORTED - The output device's mode is not currently in a
1075 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1076 characters in the Unicode string could not be
1077 rendered and were skipped.
1082 UINTN SizeAttribute
;
1084 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1091 INT32
*NullAttributes
;
1096 Mode
= &Private
->TextOutMode
;
1097 NullScreen
= Private
->DevNullScreen
;
1098 NullAttributes
= Private
->DevNullAttributes
;
1099 LastRow
= Private
->DevNullRows
- 1;
1100 MaxColumn
= Private
->DevNullColumns
;
1102 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1110 if (*WString
== CHAR_BACKSPACE
) {
1112 // If the cursor is at the left edge of the display, then move the cursor
1115 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1117 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1121 // If the cursor is not at the left edge of the display,
1122 // then move the cursor left one column.
1124 if (Mode
->CursorColumn
> 0) {
1125 Mode
->CursorColumn
--;
1126 if (Mode
->CursorColumn
> 0 &&
1127 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1129 Mode
->CursorColumn
--;
1132 // Insert an extra backspace
1134 InsertChar
= CHAR_BACKSPACE
;
1139 InsertChar
= TempChar
;
1152 } else if (*WString
== CHAR_LINEFEED
) {
1154 // If the cursor is at the bottom of the display,
1155 // then scroll the display one row, and do not update
1156 // the cursor position. Otherwise, move the cursor down one row.
1158 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1160 // Scroll Screen Up One Row
1162 SizeAttribute
= LastRow
* MaxColumn
;
1165 NullAttributes
+ MaxColumn
,
1166 SizeAttribute
* sizeof (INT32
)
1170 // Each row has an ending CHAR_NULL. So one more character each line
1171 // for DevNullScreen than DevNullAttributes
1173 SizeScreen
= SizeAttribute
+ LastRow
;
1176 NullScreen
+ (MaxColumn
+ 1),
1177 SizeScreen
* sizeof (CHAR16
)
1181 // Print Blank Line at last line
1183 Screen
= NullScreen
+ SizeScreen
;
1184 Attribute
= NullAttributes
+ SizeAttribute
;
1186 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1188 *Attribute
= Mode
->Attribute
;
1195 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1197 // Move the cursor to the beginning of the current row.
1199 Mode
->CursorColumn
= 0;
1203 // Print the character at the current cursor position and
1204 // move the cursor right one column. If this moves the cursor
1205 // past the right edge of the display, then the line should wrap to
1206 // the beginning of the next line. This is equivalent to inserting
1207 // a CR and an LF. Note that if the cursor is at the bottom of the
1208 // display, and the line wraps, then the display will be scrolled
1211 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1213 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1214 if (*WString
== CHAR_NULL
) {
1218 if (*WString
== CHAR_BACKSPACE
) {
1222 if (*WString
== CHAR_LINEFEED
) {
1226 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1230 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
1231 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
1236 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1238 // If a wide char is at the rightmost column, then move the char
1239 // to the beginning of the next row
1241 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1242 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1244 Mode
->CursorColumn
++;
1246 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1247 NullAttributes
[Index
] = Mode
->Attribute
;
1248 if (CurrentWidth
== 1) {
1249 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1251 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1252 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1255 Index
+= CurrentWidth
;
1257 Mode
->CursorColumn
+= CurrentWidth
;
1261 // At the end of line, output carriage return and line feed
1263 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1264 DevNullTextOutOutputString (Private
, mCrLfString
);
1273 DevNullTextOutSetMode (
1274 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1279 Routine Description:
1280 Sets the output device(s) to a specified mode.
1283 Private - Private data structure pointer.
1284 ModeNumber - The mode number to set.
1287 EFI_SUCCESS - The requested text mode was set.
1288 EFI_DEVICE_ERROR - The device had an error and
1289 could not complete the request.
1290 EFI_UNSUPPORTED - The mode number was not valid.
1291 EFI_OUT_OF_RESOURCES - Out of resources.
1298 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1301 // No extra check for ModeNumber here, as it has been checked in
1302 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1304 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1306 Column
= Mode
->Columns
;
1308 if (Row
<= 0 && Column
<= 0) {
1309 return EFI_UNSUPPORTED
;
1312 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1314 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1315 Private
->DevNullColumns
= Column
;
1316 Private
->DevNullRows
= Row
;
1318 FreePool (Private
->DevNullScreen
);
1320 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1321 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1322 if (Private
->DevNullScreen
== NULL
) {
1323 return EFI_OUT_OF_RESOURCES
;
1326 FreePool (Private
->DevNullAttributes
);
1328 Size
= Row
* Column
* sizeof (INT32
);
1329 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1330 if (Private
->DevNullAttributes
== NULL
) {
1331 return EFI_OUT_OF_RESOURCES
;
1335 DevNullTextOutClearScreen (Private
);
1341 DevNullTextOutClearScreen (
1342 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1346 Routine Description:
1347 Clears the output device(s) display to the currently selected background
1351 Private - Protocol instance pointer.
1354 EFI_SUCCESS - The operation completed successfully.
1355 EFI_DEVICE_ERROR - The device had an error and
1356 could not complete the request.
1357 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1365 INT32 CurrentAttribute
;
1368 // Clear the DevNull Text Out Buffers.
1369 // The screen is filled with spaces.
1370 // The attributes are all synced with the current Simple Text Out Attribute
1372 Screen
= Private
->DevNullScreen
;
1373 Attributes
= Private
->DevNullAttributes
;
1374 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1376 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1377 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1379 *Attributes
= CurrentAttribute
;
1382 // Each line of the screen has a NULL on the end so we must skip over it
1387 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1389 return DevNullTextOutEnableCursor (Private
, TRUE
);
1393 DevNullTextOutSetCursorPosition (
1394 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1400 Routine Description:
1401 Sets the current coordinates of the cursor position
1404 Private - Protocol instance pointer.
1405 Column, Row - the position to set the cursor to. Must be greater than or
1406 equal to zero and less than the number of columns and rows
1410 EFI_SUCCESS - The operation completed successfully.
1411 EFI_DEVICE_ERROR - The device had an error and
1412 could not complete the request.
1413 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1414 cursor position is invalid for the current mode.
1419 // No need to do extra check here as whether (Column, Row) is valid has
1420 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1421 // always be supported.
1423 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1424 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1430 DevNullTextOutEnableCursor (
1431 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1435 Routine Description:
1437 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1438 In this driver, the cursor cannot be hidden.
1442 Private - Indicates the calling context.
1444 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1445 is set to be invisible.
1449 EFI_SUCCESS - The request is valid.
1454 Private
->TextOutMode
.CursorVisible
= Visible
;
1460 DevNullSyncGopStdOut (
1461 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1464 Routine Description:
1465 Take the DevNull TextOut device and update the Simple Text Out on every
1469 Private - Indicates the calling context.
1472 EFI_SUCCESS - The request is valid.
1473 other - Return status of TextOut->OutputString ()
1478 EFI_STATUS ReturnStatus
;
1483 UINTN CurrentColumn
;
1486 INT32 StartAttribute
;
1487 BOOLEAN StartCursorState
;
1492 CHAR16
*ScreenStart
;
1493 INT32 CurrentAttribute
;
1495 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
1498 // Save the devices Attributes, Cursor enable state and location
1500 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1501 StartRow
= Private
->TextOutMode
.CursorRow
;
1502 StartAttribute
= Private
->TextOutMode
.Attribute
;
1503 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1505 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1507 Sto
= Private
->TextOutList
[List
].TextOut
;
1510 // Skip non GOP/UGA devices
1512 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1513 Sto
->EnableCursor (Sto
, FALSE
);
1514 Sto
->ClearScreen (Sto
);
1518 ReturnStatus
= EFI_SUCCESS
;
1519 Screen
= Private
->DevNullScreen
;
1520 Attributes
= Private
->DevNullAttributes
;
1521 MaxColumn
= Private
->DevNullColumns
;
1523 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1525 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1527 if (Row
== (Private
->DevNullRows
- 1)) {
1529 // Don't ever sync the last character as it will scroll the screen
1531 Screen
[MaxColumn
- 1] = 0x00;
1535 while (Column
< MaxColumn
) {
1536 if (Screen
[Column
]) {
1537 CurrentAttribute
= Attributes
[Column
];
1538 CurrentColumn
= Column
;
1539 ScreenStart
= &Screen
[Column
];
1542 // the line end is alway 0x0. So Column should be less than MaxColumn
1543 // It should be still in the same row
1545 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1547 if (Attributes
[Column
] != CurrentAttribute
) {
1554 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1562 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1564 Sto
= Private
->TextOutList
[List
].TextOut
;
1567 // Skip non GOP/UGA devices
1569 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1570 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1571 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1572 Status
= Sto
->OutputString (Sto
, Buffer
);
1573 if (EFI_ERROR (Status
)) {
1574 ReturnStatus
= Status
;
1585 // Restore the devices Attributes, Cursor enable state and location
1587 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1588 Sto
= Private
->TextOutList
[List
].TextOut
;
1591 // Skip non GOP/UGA devices
1593 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1594 Sto
->SetAttribute (Sto
, StartAttribute
);
1595 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1596 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1597 if (EFI_ERROR (Status
)) {
1598 ReturnStatus
= Status
;
1605 return ReturnStatus
;