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
;
196 TEXT_OUT_GOP_MODE
*Mode
;
198 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
199 return EFI_INVALID_PARAMETER
;
203 // retrieve private data
205 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
207 if (Private
->HardwareNeedsStarting
) {
208 return EFI_NOT_STARTED
;
211 Status
= gBS
->AllocatePool (
213 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
216 if (EFI_ERROR (Status
)) {
220 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
222 CopyMem (*Info
, Private
->GraphicsOutput
.Mode
->Info
, *SizeOfInfo
);
223 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
224 (*Info
)->HorizontalResolution
= Mode
->HorizontalResolution
;
225 (*Info
)->VerticalResolution
= Mode
->VerticalResolution
;
226 (*Info
)->PixelsPerScanLine
= Mode
->HorizontalResolution
;
233 ConSpliterGraphicsOutputSetMode (
234 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
241 Graphics output protocol interface to set video mode
244 This - Protocol instance pointer.
245 ModeNumber - The mode number to be set.
248 EFI_SUCCESS - Graphics mode was changed.
249 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
250 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
255 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
257 EFI_STATUS ReturnStatus
;
258 TEXT_OUT_GOP_MODE
*Mode
;
260 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
263 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
264 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
266 if (ModeNumber
>= This
->Mode
->MaxMode
) {
267 return EFI_UNSUPPORTED
;
270 if (ModeNumber
== This
->Mode
->Mode
) {
274 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
277 // GopDevNullSetMode ()
279 ReturnStatus
= EFI_SUCCESS
;
282 // Free the old version
284 if (Private
->GraphicsOutputBlt
!= NULL
) {
285 gBS
->FreePool (Private
->GraphicsOutputBlt
);
289 // Allocate the virtual Blt buffer
291 Mode
= &Private
->GraphicsOutputModeBuffer
[ModeNumber
];
292 Size
= Mode
->HorizontalResolution
* Mode
->VerticalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
293 Private
->GraphicsOutputBlt
= AllocateZeroPool (Size
);
295 if (Private
->GraphicsOutputBlt
== NULL
) {
296 return EFI_OUT_OF_RESOURCES
;
299 if (!Private
->HardwareNeedsStarting
) {
300 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
301 return EFI_UNSUPPORTED
;
305 // return the worst status met
307 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
308 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
309 if (GraphicsOutput
!= NULL
) {
311 // Find corresponding ModeNumber of this GraphicsOutput instance
313 for (NumberIndex
= 0; NumberIndex
< GraphicsOutput
->Mode
->MaxMode
; NumberIndex
++) {
314 Status
= GraphicsOutput
->QueryMode (GraphicsOutput
, (UINT32
) NumberIndex
, &SizeOfInfo
, &Info
);
315 if (EFI_ERROR (Status
)) {
318 if ((Info
->HorizontalResolution
== Mode
->HorizontalResolution
) && (Info
->VerticalResolution
== Mode
->VerticalResolution
)) {
319 gBS
->FreePool (Info
);
322 gBS
->FreePool (Info
);
325 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, (UINT32
) NumberIndex
);
326 if (EFI_ERROR (Status
)) {
327 ReturnStatus
= Status
;
331 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
332 if (UgaDraw
!= NULL
) {
333 Status
= UgaDraw
->SetMode (
335 Mode
->HorizontalResolution
,
336 Mode
->VerticalResolution
,
340 if (EFI_ERROR (Status
)) {
341 ReturnStatus
= Status
;
346 This
->Mode
->Mode
= ModeNumber
;
348 Info
= This
->Mode
->Info
;
349 Info
->HorizontalResolution
= Mode
->HorizontalResolution
;
350 Info
->VerticalResolution
= Mode
->VerticalResolution
;
351 Info
->PixelsPerScanLine
= Mode
->HorizontalResolution
;
354 // Information is not enough here, so the following items remain unchanged:
355 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
356 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
357 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
360 Private
->HardwareNeedsStarting
= FALSE
;
367 DevNullGraphicsOutputBlt (
368 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
369 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
370 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
373 IN UINTN DestinationX
,
374 IN UINTN DestinationY
,
377 IN UINTN Delta OPTIONAL
383 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
384 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
385 UINTN HorizontalResolution
;
386 UINTN VerticalResolution
;
388 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
389 return EFI_INVALID_PARAMETER
;
392 if (Width
== 0 || Height
== 0) {
393 return EFI_INVALID_PARAMETER
;
397 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
400 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
401 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
404 // We need to fill the Virtual Screen buffer with the blt data.
406 if (BltOperation
== EfiBltVideoToBltBuffer
) {
408 // Video to BltBuffer: Source is Video, destination is BltBuffer
410 if ((SourceY
+ Height
) > VerticalResolution
) {
411 return EFI_INVALID_PARAMETER
;
414 if ((SourceX
+ Width
) > HorizontalResolution
) {
415 return EFI_INVALID_PARAMETER
;
418 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
419 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
421 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
422 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
423 ScreenPtr
+= HorizontalResolution
;
428 // BltBuffer to Video: Source is BltBuffer, destination is Video
430 if (DestinationY
+ Height
> VerticalResolution
) {
431 return EFI_INVALID_PARAMETER
;
434 if (DestinationX
+ Width
> HorizontalResolution
) {
435 return EFI_INVALID_PARAMETER
;
438 if ((BltOperation
== EfiBltVideoToVideo
) && (DestinationY
> SourceY
)) {
440 // Copy backwards, only care the Video to Video Blt
442 ScreenPtr
= &Private
->GraphicsOutputBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
443 SrcY
= SourceY
+ Height
- 1;
447 // Copy forwards, for other cases
449 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
454 while (Height
!= 0) {
455 if (BltOperation
== EfiBltVideoFill
) {
456 for (Index
= 0; Index
< Width
; Index
++) {
457 ScreenPtr
[Index
] = *BltBuffer
;
460 if (BltOperation
== EfiBltBufferToVideo
) {
461 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
463 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
466 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
470 ScreenPtr
+= HorizontalResolution
;
473 ScreenPtr
-= HorizontalResolution
;
485 ConSpliterGraphicsOutputBlt (
486 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
487 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
488 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
491 IN UINTN DestinationX
,
492 IN UINTN DestinationY
,
495 IN UINTN Delta OPTIONAL
500 The following table defines actions for BltOperations:
501 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
502 directly to every pixel of the video display rectangle
503 (DestinationX, DestinationY)
504 (DestinationX + Width, DestinationY + Height).
505 Only one pixel will be used from the BltBuffer. Delta is NOT used.
506 EfiBltVideoToBltBuffer - Read data from the video display rectangle
507 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
508 the BltBuffer rectangle (DestinationX, DestinationY )
509 (DestinationX + Width, DestinationY + Height). If DestinationX or
510 DestinationY is not zero then Delta must be set to the length in bytes
511 of a row in the BltBuffer.
512 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
513 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
514 video display rectangle (DestinationX, DestinationY)
515 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
516 not zero then Delta must be set to the length in bytes of a row in the
518 EfiBltVideoToVideo - Copy from the video display rectangle
519 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
520 to the video display rectangle (DestinationX, DestinationY)
521 (DestinationX + Width, DestinationY + Height).
522 The BltBuffer and Delta are not used in this mode.
525 This - Protocol instance pointer.
526 BltBuffer - Buffer containing data to blit into video buffer. This
527 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
528 BltOperation - Operation to perform on BlitBuffer and video memory
529 SourceX - X coordinate of source for the BltBuffer.
530 SourceY - Y coordinate of source for the BltBuffer.
531 DestinationX - X coordinate of destination for the BltBuffer.
532 DestinationY - Y coordinate of destination for the BltBuffer.
533 Width - Width of rectangle in BltBuffer in pixels.
534 Height - Hight of rectangle in BltBuffer in pixels.
538 EFI_SUCCESS - The Blt operation completed.
539 EFI_INVALID_PARAMETER - BltOperation is not valid.
540 EFI_DEVICE_ERROR - A hardware error occured writting to the video
546 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
548 EFI_STATUS ReturnStatus
;
549 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
550 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
552 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
555 // Sync up DevNull GOP device
557 ReturnStatus
= DevNullGraphicsOutputBlt (
570 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
574 // return the worst status met
576 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
577 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
578 if (GraphicsOutput
!= NULL
) {
579 Status
= GraphicsOutput
->Blt (
591 if (EFI_ERROR (Status
)) {
592 ReturnStatus
= Status
;
593 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
595 // Only need to read the data into buffer one time
601 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
602 if (UgaDraw
!= NULL
) {
603 Status
= UgaDraw
->Blt (
605 (EFI_UGA_PIXEL
*) BltBuffer
,
606 (EFI_UGA_BLT_OPERATION
) BltOperation
,
615 if (EFI_ERROR (Status
)) {
616 ReturnStatus
= Status
;
617 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
619 // Only need to read the data into buffer one time
631 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
632 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
633 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
636 if (GraphicsOutput
!= NULL
) {
637 return GraphicsOutput
->Blt (
639 Private
->GraphicsOutputBlt
,
645 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
646 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
650 return UgaDraw
->Blt (
652 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
653 EfiUgaBltBufferToVideo
,
658 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
659 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
669 ConSpliterUgaDrawGetMode (
670 IN EFI_UGA_DRAW_PROTOCOL
*This
,
671 OUT UINT32
*HorizontalResolution
,
672 OUT UINT32
*VerticalResolution
,
673 OUT UINT32
*ColorDepth
,
674 OUT UINT32
*RefreshRate
679 Return the current video mode information.
682 This - Protocol instance pointer.
683 HorizontalResolution - Current video horizontal resolution in pixels
684 VerticalResolution - Current video vertical resolution in pixels
685 ColorDepth - Current video color depth in bits per pixel
686 RefreshRate - Current video refresh rate in Hz.
689 EFI_SUCCESS - Mode information returned.
690 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
691 EFI_INVALID_PARAMETER - One of the input args was NULL.
695 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
697 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
698 return EFI_INVALID_PARAMETER
;
701 // retrieve private data
703 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
705 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
706 *VerticalResolution
= Private
->UgaVerticalResolution
;
707 *ColorDepth
= Private
->UgaColorDepth
;
708 *RefreshRate
= Private
->UgaRefreshRate
;
715 ConSpliterUgaDrawSetMode (
716 IN EFI_UGA_DRAW_PROTOCOL
*This
,
717 IN UINT32 HorizontalResolution
,
718 IN UINT32 VerticalResolution
,
719 IN UINT32 ColorDepth
,
720 IN UINT32 RefreshRate
725 Return the current video mode information.
728 This - Protocol instance pointer.
729 HorizontalResolution - Current video horizontal resolution in pixels
730 VerticalResolution - Current video vertical resolution in pixels
731 ColorDepth - Current video color depth in bits per pixel
732 RefreshRate - Current video refresh rate in Hz.
735 EFI_SUCCESS - Mode information returned.
736 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
737 EFI_OUT_OF_RESOURCES - Out of resources.
742 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
744 EFI_STATUS ReturnStatus
;
747 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
750 // UgaDevNullSetMode ()
752 ReturnStatus
= EFI_SUCCESS
;
755 // Free the old version
757 gBS
->FreePool (Private
->UgaBlt
);
760 // Allocate the virtual Blt buffer
762 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
763 Private
->UgaBlt
= AllocateZeroPool (Size
);
764 if (Private
->UgaBlt
== NULL
) {
765 return EFI_OUT_OF_RESOURCES
;
769 // Update the Mode data
771 Private
->UgaHorizontalResolution
= HorizontalResolution
;
772 Private
->UgaVerticalResolution
= VerticalResolution
;
773 Private
->UgaColorDepth
= ColorDepth
;
774 Private
->UgaRefreshRate
= RefreshRate
;
776 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
780 // return the worst status met
782 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
783 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
784 Status
= Private
->TextOutList
[Index
].UgaDraw
->SetMode (
785 Private
->TextOutList
[Index
].UgaDraw
,
786 HorizontalResolution
,
791 if (EFI_ERROR (Status
)) {
792 ReturnStatus
= Status
;
802 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
803 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
804 IN EFI_UGA_BLT_OPERATION BltOperation
,
807 IN UINTN DestinationX
,
808 IN UINTN DestinationY
,
811 IN UINTN Delta OPTIONAL
817 EFI_UGA_PIXEL
*BltPtr
;
818 EFI_UGA_PIXEL
*ScreenPtr
;
819 UINT32 HorizontalResolution
;
820 UINT32 VerticalResolution
;
822 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
823 return EFI_INVALID_PARAMETER
;
826 if (Width
== 0 || Height
== 0) {
827 return EFI_INVALID_PARAMETER
;
831 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
834 HorizontalResolution
= Private
->UgaHorizontalResolution
;
835 VerticalResolution
= Private
->UgaVerticalResolution
;
838 // We need to fill the Virtual Screen buffer with the blt data.
840 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
842 // Video to BltBuffer: Source is Video, destination is BltBuffer
844 if ((SourceY
+ Height
) > VerticalResolution
) {
845 return EFI_INVALID_PARAMETER
;
848 if ((SourceX
+ Width
) > HorizontalResolution
) {
849 return EFI_INVALID_PARAMETER
;
852 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
853 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
855 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
856 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
857 ScreenPtr
+= HorizontalResolution
;
862 // BltBuffer to Video: Source is BltBuffer, destination is Video
864 if (DestinationY
+ Height
> VerticalResolution
) {
865 return EFI_INVALID_PARAMETER
;
868 if (DestinationX
+ Width
> HorizontalResolution
) {
869 return EFI_INVALID_PARAMETER
;
872 if ((BltOperation
== EfiUgaVideoToVideo
) && (DestinationY
> SourceY
)) {
874 // Copy backwards, only care the Video to Video Blt
876 ScreenPtr
= &Private
->UgaBlt
[(DestinationY
+ Height
- 1) * HorizontalResolution
+ DestinationX
];
877 SrcY
= SourceY
+ Height
- 1;
881 // Copy forwards, for other cases
883 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
888 while (Height
!= 0) {
889 if (BltOperation
== EfiUgaVideoFill
) {
890 for (Index
= 0; Index
< Width
; Index
++) {
891 ScreenPtr
[Index
] = *BltBuffer
;
894 if (BltOperation
== EfiUgaBltBufferToVideo
) {
895 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
897 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
900 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
904 ScreenPtr
+= HorizontalResolution
;
907 ScreenPtr
-= HorizontalResolution
;
919 ConSpliterUgaDrawBlt (
920 IN EFI_UGA_DRAW_PROTOCOL
*This
,
921 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
922 IN EFI_UGA_BLT_OPERATION BltOperation
,
925 IN UINTN DestinationX
,
926 IN UINTN DestinationY
,
929 IN UINTN Delta OPTIONAL
934 The following table defines actions for BltOperations:
935 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
936 directly to every pixel of the video display rectangle
937 (DestinationX, DestinationY)
938 (DestinationX + Width, DestinationY + Height).
939 Only one pixel will be used from the BltBuffer. Delta is NOT used.
940 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
941 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
942 the BltBuffer rectangle (DestinationX, DestinationY )
943 (DestinationX + Width, DestinationY + Height). If DestinationX or
944 DestinationY is not zero then Delta must be set to the length in bytes
945 of a row in the BltBuffer.
946 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
947 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
948 video display rectangle (DestinationX, DestinationY)
949 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
950 not zero then Delta must be set to the length in bytes of a row in the
952 EfiUgaVideoToVideo - Copy from the video display rectangle
953 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
954 to the video display rectangle (DestinationX, DestinationY)
955 (DestinationX + Width, DestinationY + Height).
956 The BltBuffer and Delta are not used in this mode.
959 This - Protocol instance pointer.
960 BltBuffer - Buffer containing data to blit into video buffer. This
961 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
962 BltOperation - Operation to perform on BlitBuffer and video memory
963 SourceX - X coordinate of source for the BltBuffer.
964 SourceY - Y coordinate of source for the BltBuffer.
965 DestinationX - X coordinate of destination for the BltBuffer.
966 DestinationY - Y coordinate of destination for the BltBuffer.
967 Width - Width of rectangle in BltBuffer in pixels.
968 Height - Hight of rectangle in BltBuffer in pixels.
972 EFI_SUCCESS - The Blt operation completed.
973 EFI_INVALID_PARAMETER - BltOperation is not valid.
974 EFI_DEVICE_ERROR - A hardware error occured writting to the video
980 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
982 EFI_STATUS ReturnStatus
;
984 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
987 // Sync up DevNull UGA device
989 ReturnStatus
= DevNullUgaBlt (
1001 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
1002 return ReturnStatus
;
1005 // return the worst status met
1007 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
1008 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
1009 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
1010 Private
->TextOutList
[Index
].UgaDraw
,
1021 if (EFI_ERROR (Status
)) {
1022 ReturnStatus
= Status
;
1023 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1025 // Only need to read the data into buffer one time
1032 return ReturnStatus
;
1037 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1038 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1041 return UgaDraw
->Blt (
1044 EfiUgaBltBufferToVideo
,
1049 Private
->UgaHorizontalResolution
,
1050 Private
->UgaVerticalResolution
,
1051 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1057 DevNullTextOutOutputString (
1058 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1063 Routine Description:
1064 Write a Unicode string to the output device.
1067 Private - Pointer to the console output splitter's private data. It
1068 indicates the calling context.
1069 WString - The NULL-terminated Unicode string to be displayed on the output
1070 device(s). All output devices must also support the Unicode
1071 drawing defined in this file.
1074 EFI_SUCCESS - The string was output to the device.
1075 EFI_DEVICE_ERROR - The device reported an error while attempting to
1077 EFI_UNSUPPORTED - The output device's mode is not currently in a
1079 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1080 characters in the Unicode string could not be
1081 rendered and were skipped.
1086 UINTN SizeAttribute
;
1088 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1095 INT32
*NullAttributes
;
1100 Mode
= &Private
->TextOutMode
;
1101 NullScreen
= Private
->DevNullScreen
;
1102 NullAttributes
= Private
->DevNullAttributes
;
1103 LastRow
= Private
->DevNullRows
- 1;
1104 MaxColumn
= Private
->DevNullColumns
;
1106 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1114 if (*WString
== CHAR_BACKSPACE
) {
1116 // If the cursor is at the left edge of the display, then move the cursor
1119 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1121 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1125 // If the cursor is not at the left edge of the display,
1126 // then move the cursor left one column.
1128 if (Mode
->CursorColumn
> 0) {
1129 Mode
->CursorColumn
--;
1130 if (Mode
->CursorColumn
> 0 &&
1131 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1133 Mode
->CursorColumn
--;
1136 // Insert an extra backspace
1138 InsertChar
= CHAR_BACKSPACE
;
1143 InsertChar
= TempChar
;
1156 } else if (*WString
== CHAR_LINEFEED
) {
1158 // If the cursor is at the bottom of the display,
1159 // then scroll the display one row, and do not update
1160 // the cursor position. Otherwise, move the cursor down one row.
1162 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1164 // Scroll Screen Up One Row
1166 SizeAttribute
= LastRow
* MaxColumn
;
1169 NullAttributes
+ MaxColumn
,
1170 SizeAttribute
* sizeof (INT32
)
1174 // Each row has an ending CHAR_NULL. So one more character each line
1175 // for DevNullScreen than DevNullAttributes
1177 SizeScreen
= SizeAttribute
+ LastRow
;
1180 NullScreen
+ (MaxColumn
+ 1),
1181 SizeScreen
* sizeof (CHAR16
)
1185 // Print Blank Line at last line
1187 Screen
= NullScreen
+ SizeScreen
;
1188 Attribute
= NullAttributes
+ SizeAttribute
;
1190 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1192 *Attribute
= Mode
->Attribute
;
1199 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1201 // Move the cursor to the beginning of the current row.
1203 Mode
->CursorColumn
= 0;
1207 // Print the character at the current cursor position and
1208 // move the cursor right one column. If this moves the cursor
1209 // past the right edge of the display, then the line should wrap to
1210 // the beginning of the next line. This is equivalent to inserting
1211 // a CR and an LF. Note that if the cursor is at the bottom of the
1212 // display, and the line wraps, then the display will be scrolled
1215 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1217 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1218 if (*WString
== CHAR_NULL
) {
1222 if (*WString
== CHAR_BACKSPACE
) {
1226 if (*WString
== CHAR_LINEFEED
) {
1230 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1234 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
1235 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
1240 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1242 // If a wide char is at the rightmost column, then move the char
1243 // to the beginning of the next row
1245 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1246 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1248 Mode
->CursorColumn
++;
1250 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1251 NullAttributes
[Index
] = Mode
->Attribute
;
1252 if (CurrentWidth
== 1) {
1253 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1255 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1256 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1259 Index
+= CurrentWidth
;
1261 Mode
->CursorColumn
+= CurrentWidth
;
1265 // At the end of line, output carriage return and line feed
1267 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1268 DevNullTextOutOutputString (Private
, mCrLfString
);
1277 DevNullTextOutSetMode (
1278 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1283 Routine Description:
1284 Sets the output device(s) to a specified mode.
1287 Private - Private data structure pointer.
1288 ModeNumber - The mode number to set.
1291 EFI_SUCCESS - The requested text mode was set.
1292 EFI_DEVICE_ERROR - The device had an error and
1293 could not complete the request.
1294 EFI_UNSUPPORTED - The mode number was not valid.
1295 EFI_OUT_OF_RESOURCES - Out of resources.
1302 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1305 // No extra check for ModeNumber here, as it has been checked in
1306 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1308 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1310 Column
= Mode
->Columns
;
1312 if (Row
<= 0 && Column
<= 0) {
1313 return EFI_UNSUPPORTED
;
1316 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1318 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1319 Private
->DevNullColumns
= Column
;
1320 Private
->DevNullRows
= Row
;
1322 gBS
->FreePool (Private
->DevNullScreen
);
1324 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1325 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1326 if (Private
->DevNullScreen
== NULL
) {
1327 return EFI_OUT_OF_RESOURCES
;
1330 gBS
->FreePool (Private
->DevNullAttributes
);
1332 Size
= Row
* Column
* sizeof (INT32
);
1333 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1334 if (Private
->DevNullAttributes
== NULL
) {
1335 return EFI_OUT_OF_RESOURCES
;
1339 DevNullTextOutClearScreen (Private
);
1345 DevNullTextOutClearScreen (
1346 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1350 Routine Description:
1351 Clears the output device(s) display to the currently selected background
1355 Private - Protocol instance pointer.
1358 EFI_SUCCESS - The operation completed successfully.
1359 EFI_DEVICE_ERROR - The device had an error and
1360 could not complete the request.
1361 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1369 INT32 CurrentAttribute
;
1372 // Clear the DevNull Text Out Buffers.
1373 // The screen is filled with spaces.
1374 // The attributes are all synced with the current Simple Text Out Attribute
1376 Screen
= Private
->DevNullScreen
;
1377 Attributes
= Private
->DevNullAttributes
;
1378 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1380 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1381 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1383 *Attributes
= CurrentAttribute
;
1386 // Each line of the screen has a NULL on the end so we must skip over it
1391 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1393 return DevNullTextOutEnableCursor (Private
, TRUE
);
1397 DevNullTextOutSetCursorPosition (
1398 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1404 Routine Description:
1405 Sets the current coordinates of the cursor position
1408 Private - Protocol instance pointer.
1409 Column, Row - the position to set the cursor to. Must be greater than or
1410 equal to zero and less than the number of columns and rows
1414 EFI_SUCCESS - The operation completed successfully.
1415 EFI_DEVICE_ERROR - The device had an error and
1416 could not complete the request.
1417 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1418 cursor position is invalid for the current mode.
1423 // No need to do extra check here as whether (Column, Row) is valid has
1424 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1425 // always be supported.
1427 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1428 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1434 DevNullTextOutEnableCursor (
1435 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1439 Routine Description:
1441 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1442 In this driver, the cursor cannot be hidden.
1446 Private - Indicates the calling context.
1448 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1449 is set to be invisible.
1453 EFI_SUCCESS - The request is valid.
1458 Private
->TextOutMode
.CursorVisible
= Visible
;
1464 DevNullSyncGopStdOut (
1465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1468 Routine Description:
1469 Take the DevNull TextOut device and update the Simple Text Out on every
1473 Private - Indicates the calling context.
1476 EFI_SUCCESS - The request is valid.
1477 other - Return status of TextOut->OutputString ()
1482 EFI_STATUS ReturnStatus
;
1487 UINTN CurrentColumn
;
1490 INT32 StartAttribute
;
1491 BOOLEAN StartCursorState
;
1496 CHAR16
*ScreenStart
;
1497 INT32 CurrentAttribute
;
1499 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
1502 // Save the devices Attributes, Cursor enable state and location
1504 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1505 StartRow
= Private
->TextOutMode
.CursorRow
;
1506 StartAttribute
= Private
->TextOutMode
.Attribute
;
1507 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1509 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1511 Sto
= Private
->TextOutList
[List
].TextOut
;
1514 // Skip non GOP/UGA devices
1516 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1517 Sto
->EnableCursor (Sto
, FALSE
);
1518 Sto
->ClearScreen (Sto
);
1522 ReturnStatus
= EFI_SUCCESS
;
1523 Screen
= Private
->DevNullScreen
;
1524 Attributes
= Private
->DevNullAttributes
;
1525 MaxColumn
= Private
->DevNullColumns
;
1527 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1529 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1531 if (Row
== (Private
->DevNullRows
- 1)) {
1533 // Don't ever sync the last character as it will scroll the screen
1535 Screen
[MaxColumn
- 1] = 0x00;
1539 while (Column
< MaxColumn
) {
1540 if (Screen
[Column
]) {
1541 CurrentAttribute
= Attributes
[Column
];
1542 CurrentColumn
= Column
;
1543 ScreenStart
= &Screen
[Column
];
1546 // the line end is alway 0x0. So Column should be less than MaxColumn
1547 // It should be still in the same row
1549 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1551 if (Attributes
[Column
] != CurrentAttribute
) {
1558 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1566 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1568 Sto
= Private
->TextOutList
[List
].TextOut
;
1571 // Skip non GOP/UGA devices
1573 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1574 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1575 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1576 Status
= Sto
->OutputString (Sto
, Buffer
);
1577 if (EFI_ERROR (Status
)) {
1578 ReturnStatus
= Status
;
1589 // Restore the devices Attributes, Cursor enable state and location
1591 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1592 Sto
= Private
->TextOutList
[List
].TextOut
;
1595 // Skip non GOP/UGA devices
1597 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1598 Sto
->SetAttribute (Sto
, StartAttribute
);
1599 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1600 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1601 if (EFI_ERROR (Status
)) {
1602 ReturnStatus
= Status
;
1607 gBS
->FreePool (Buffer
);
1609 return ReturnStatus
;