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 // 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
382 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltPtr
;
383 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ScreenPtr
;
384 UINTN HorizontalResolution
;
385 UINTN VerticalResolution
;
387 if ((BltOperation
< EfiBltVideoFill
) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
388 return EFI_INVALID_PARAMETER
;
391 if (Width
== 0 || Height
== 0) {
392 return EFI_INVALID_PARAMETER
;
396 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
399 HorizontalResolution
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
400 VerticalResolution
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
403 // We need to fill the Virtual Screen buffer with the blt data.
405 if (BltOperation
== EfiBltVideoToBltBuffer
) {
407 // Video to BltBuffer: Source is Video, destination is BltBuffer
409 if ((SourceY
+ Height
) > VerticalResolution
) {
410 return EFI_INVALID_PARAMETER
;
413 if ((SourceX
+ Width
) > HorizontalResolution
) {
414 return EFI_INVALID_PARAMETER
;
417 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
418 ScreenPtr
= &Private
->GraphicsOutputBlt
[SourceY
* HorizontalResolution
+ SourceX
];
420 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
421 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
422 ScreenPtr
+= HorizontalResolution
;
427 // BltBuffer to Video: Source is BltBuffer, destination is Video
429 if (DestinationY
+ Height
> VerticalResolution
) {
430 return EFI_INVALID_PARAMETER
;
433 if (DestinationX
+ Width
> HorizontalResolution
) {
434 return EFI_INVALID_PARAMETER
;
437 ScreenPtr
= &Private
->GraphicsOutputBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
440 if (BltOperation
== EfiBltVideoFill
) {
441 for (Index
= 0; Index
< Width
; Index
++) {
442 ScreenPtr
[Index
] = *BltBuffer
;
445 if (BltOperation
== EfiBltBufferToVideo
) {
446 BltPtr
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
448 BltPtr
= &Private
->GraphicsOutputBlt
[SrcY
* HorizontalResolution
+ SourceX
];
451 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
454 ScreenPtr
+= HorizontalResolution
;
465 ConSpliterGraphicsOutputBlt (
466 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
467 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
468 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
471 IN UINTN DestinationX
,
472 IN UINTN DestinationY
,
475 IN UINTN Delta OPTIONAL
480 The following table defines actions for BltOperations:
481 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
482 directly to every pixel of the video display rectangle
483 (DestinationX, DestinationY)
484 (DestinationX + Width, DestinationY + Height).
485 Only one pixel will be used from the BltBuffer. Delta is NOT used.
486 EfiBltVideoToBltBuffer - Read data from the video display rectangle
487 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
488 the BltBuffer rectangle (DestinationX, DestinationY )
489 (DestinationX + Width, DestinationY + Height). If DestinationX or
490 DestinationY is not zero then Delta must be set to the length in bytes
491 of a row in the BltBuffer.
492 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
493 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
494 video display rectangle (DestinationX, DestinationY)
495 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
496 not zero then Delta must be set to the length in bytes of a row in the
498 EfiBltVideoToVideo - Copy from the video display rectangle
499 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
500 to the video display rectangle (DestinationX, DestinationY)
501 (DestinationX + Width, DestinationY + Height).
502 The BltBuffer and Delta are not used in this mode.
505 This - Protocol instance pointer.
506 BltBuffer - Buffer containing data to blit into video buffer. This
507 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
508 BltOperation - Operation to perform on BlitBuffer and video memory
509 SourceX - X coordinate of source for the BltBuffer.
510 SourceY - Y coordinate of source for the BltBuffer.
511 DestinationX - X coordinate of destination for the BltBuffer.
512 DestinationY - Y coordinate of destination for the BltBuffer.
513 Width - Width of rectangle in BltBuffer in pixels.
514 Height - Hight of rectangle in BltBuffer in pixels.
518 EFI_SUCCESS - The Blt operation completed.
519 EFI_INVALID_PARAMETER - BltOperation is not valid.
520 EFI_DEVICE_ERROR - A hardware error occured writting to the video
526 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
528 EFI_STATUS ReturnStatus
;
529 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
530 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
532 Private
= GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
535 // Sync up DevNull GOP device
537 ReturnStatus
= DevNullGraphicsOutputBlt (
550 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
554 // return the worst status met
556 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
557 GraphicsOutput
= Private
->TextOutList
[Index
].GraphicsOutput
;
558 if (GraphicsOutput
!= NULL
) {
559 Status
= GraphicsOutput
->Blt (
571 if (EFI_ERROR (Status
)) {
572 ReturnStatus
= Status
;
573 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
575 // Only need to read the data into buffer one time
581 UgaDraw
= Private
->TextOutList
[Index
].UgaDraw
;
582 if (UgaDraw
!= NULL
) {
583 Status
= UgaDraw
->Blt (
585 (EFI_UGA_PIXEL
*) BltBuffer
,
586 (EFI_UGA_BLT_OPERATION
) BltOperation
,
595 if (EFI_ERROR (Status
)) {
596 ReturnStatus
= Status
;
597 } else if (BltOperation
== EfiBltVideoToBltBuffer
) {
599 // Only need to read the data into buffer one time
611 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
612 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
613 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
616 if (GraphicsOutput
!= NULL
) {
617 return GraphicsOutput
->Blt (
619 Private
->GraphicsOutputBlt
,
625 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
626 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
630 return UgaDraw
->Blt (
632 (EFI_UGA_PIXEL
*) Private
->GraphicsOutputBlt
,
633 EfiUgaBltBufferToVideo
,
638 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
,
639 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
,
649 ConSpliterUgaDrawGetMode (
650 IN EFI_UGA_DRAW_PROTOCOL
*This
,
651 OUT UINT32
*HorizontalResolution
,
652 OUT UINT32
*VerticalResolution
,
653 OUT UINT32
*ColorDepth
,
654 OUT UINT32
*RefreshRate
659 Return the current video mode information.
662 This - Protocol instance pointer.
663 HorizontalResolution - Current video horizontal resolution in pixels
664 VerticalResolution - Current video vertical resolution in pixels
665 ColorDepth - Current video color depth in bits per pixel
666 RefreshRate - Current video refresh rate in Hz.
669 EFI_SUCCESS - Mode information returned.
670 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
671 EFI_INVALID_PARAMETER - One of the input args was NULL.
675 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
677 if (!(HorizontalResolution
&& VerticalResolution
&& RefreshRate
&& ColorDepth
)) {
678 return EFI_INVALID_PARAMETER
;
681 // retrieve private data
683 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
685 *HorizontalResolution
= Private
->UgaHorizontalResolution
;
686 *VerticalResolution
= Private
->UgaVerticalResolution
;
687 *ColorDepth
= Private
->UgaColorDepth
;
688 *RefreshRate
= Private
->UgaRefreshRate
;
695 ConSpliterUgaDrawSetMode (
696 IN EFI_UGA_DRAW_PROTOCOL
*This
,
697 IN UINT32 HorizontalResolution
,
698 IN UINT32 VerticalResolution
,
699 IN UINT32 ColorDepth
,
700 IN UINT32 RefreshRate
705 Return the current video mode information.
708 This - Protocol instance pointer.
709 HorizontalResolution - Current video horizontal resolution in pixels
710 VerticalResolution - Current video vertical resolution in pixels
711 ColorDepth - Current video color depth in bits per pixel
712 RefreshRate - Current video refresh rate in Hz.
715 EFI_SUCCESS - Mode information returned.
716 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
717 EFI_OUT_OF_RESOURCES - Out of resources.
722 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
724 EFI_STATUS ReturnStatus
;
727 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
730 // UgaDevNullSetMode ()
732 ReturnStatus
= EFI_SUCCESS
;
735 // Free the old version
737 gBS
->FreePool (Private
->UgaBlt
);
740 // Allocate the virtual Blt buffer
742 Size
= HorizontalResolution
* VerticalResolution
* sizeof (EFI_UGA_PIXEL
);
743 Private
->UgaBlt
= AllocateZeroPool (Size
);
744 if (Private
->UgaBlt
== NULL
) {
745 return EFI_OUT_OF_RESOURCES
;
749 // Update the Mode data
751 Private
->UgaHorizontalResolution
= HorizontalResolution
;
752 Private
->UgaVerticalResolution
= VerticalResolution
;
753 Private
->UgaColorDepth
= ColorDepth
;
754 Private
->UgaRefreshRate
= RefreshRate
;
756 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
760 // return the worst status met
762 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
763 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
764 Status
= Private
->TextOutList
[Index
].UgaDraw
->SetMode (
765 Private
->TextOutList
[Index
].UgaDraw
,
766 HorizontalResolution
,
771 if (EFI_ERROR (Status
)) {
772 ReturnStatus
= Status
;
782 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
783 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
784 IN EFI_UGA_BLT_OPERATION BltOperation
,
787 IN UINTN DestinationX
,
788 IN UINTN DestinationY
,
791 IN UINTN Delta OPTIONAL
796 EFI_UGA_PIXEL
*BltPtr
;
797 EFI_UGA_PIXEL
*ScreenPtr
;
798 UINT32 HorizontalResolution
;
799 UINT32 VerticalResolution
;
801 if ((BltOperation
< 0) || (BltOperation
>= EfiUgaBltMax
)) {
802 return EFI_INVALID_PARAMETER
;
805 if (Width
== 0 || Height
== 0) {
806 return EFI_INVALID_PARAMETER
;
810 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
813 HorizontalResolution
= Private
->UgaHorizontalResolution
;
814 VerticalResolution
= Private
->UgaVerticalResolution
;
817 // We need to fill the Virtual Screen buffer with the blt data.
819 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
821 // Video to BltBuffer: Source is Video, destination is BltBuffer
823 if ((SourceY
+ Height
) > VerticalResolution
) {
824 return EFI_INVALID_PARAMETER
;
827 if ((SourceX
+ Width
) > HorizontalResolution
) {
828 return EFI_INVALID_PARAMETER
;
831 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ DestinationY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
832 ScreenPtr
= &Private
->UgaBlt
[SourceY
* HorizontalResolution
+ SourceX
];
834 CopyMem (BltPtr
, ScreenPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
835 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltPtr
+ Delta
);
836 ScreenPtr
+= HorizontalResolution
;
841 // BltBuffer to Video: Source is BltBuffer, destination is Video
843 if (DestinationY
+ Height
> VerticalResolution
) {
844 return EFI_INVALID_PARAMETER
;
847 if (DestinationX
+ Width
> HorizontalResolution
) {
848 return EFI_INVALID_PARAMETER
;
851 ScreenPtr
= &Private
->UgaBlt
[DestinationY
* HorizontalResolution
+ DestinationX
];
854 if (BltOperation
== EfiUgaVideoFill
) {
855 for (Index
= 0; Index
< Width
; Index
++) {
856 ScreenPtr
[Index
] = *BltBuffer
;
859 if (BltOperation
== EfiUgaBltBufferToVideo
) {
860 BltPtr
= (EFI_UGA_PIXEL
*) ((UINT8
*) BltBuffer
+ SrcY
* Delta
+ SourceX
* sizeof (EFI_UGA_PIXEL
));
862 BltPtr
= &Private
->UgaBlt
[SrcY
* HorizontalResolution
+ SourceX
];
865 CopyMem (ScreenPtr
, BltPtr
, Width
* sizeof (EFI_UGA_PIXEL
));
868 ScreenPtr
+= HorizontalResolution
;
879 ConSpliterUgaDrawBlt (
880 IN EFI_UGA_DRAW_PROTOCOL
*This
,
881 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
882 IN EFI_UGA_BLT_OPERATION BltOperation
,
885 IN UINTN DestinationX
,
886 IN UINTN DestinationY
,
889 IN UINTN Delta OPTIONAL
894 The following table defines actions for BltOperations:
895 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
896 directly to every pixel of the video display rectangle
897 (DestinationX, DestinationY)
898 (DestinationX + Width, DestinationY + Height).
899 Only one pixel will be used from the BltBuffer. Delta is NOT used.
900 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
901 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
902 the BltBuffer rectangle (DestinationX, DestinationY )
903 (DestinationX + Width, DestinationY + Height). If DestinationX or
904 DestinationY is not zero then Delta must be set to the length in bytes
905 of a row in the BltBuffer.
906 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
907 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
908 video display rectangle (DestinationX, DestinationY)
909 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
910 not zero then Delta must be set to the length in bytes of a row in the
912 EfiUgaVideoToVideo - Copy from the video display rectangle
913 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
914 to the video display rectangle (DestinationX, DestinationY)
915 (DestinationX + Width, DestinationY + Height).
916 The BltBuffer and Delta are not used in this mode.
919 This - Protocol instance pointer.
920 BltBuffer - Buffer containing data to blit into video buffer. This
921 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
922 BltOperation - Operation to perform on BlitBuffer and video memory
923 SourceX - X coordinate of source for the BltBuffer.
924 SourceY - Y coordinate of source for the BltBuffer.
925 DestinationX - X coordinate of destination for the BltBuffer.
926 DestinationY - Y coordinate of destination for the BltBuffer.
927 Width - Width of rectangle in BltBuffer in pixels.
928 Height - Hight of rectangle in BltBuffer in pixels.
932 EFI_SUCCESS - The Blt operation completed.
933 EFI_INVALID_PARAMETER - BltOperation is not valid.
934 EFI_DEVICE_ERROR - A hardware error occured writting to the video
940 TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
;
942 EFI_STATUS ReturnStatus
;
944 Private
= UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This
);
947 // Sync up DevNull UGA device
949 ReturnStatus
= DevNullUgaBlt (
961 if (Private
->ConsoleOutputMode
!= EfiConsoleControlScreenGraphics
) {
965 // return the worst status met
967 for (Index
= 0; Index
< Private
->CurrentNumberOfConsoles
; Index
++) {
968 if (Private
->TextOutList
[Index
].UgaDraw
!= NULL
) {
969 Status
= Private
->TextOutList
[Index
].UgaDraw
->Blt (
970 Private
->TextOutList
[Index
].UgaDraw
,
981 if (EFI_ERROR (Status
)) {
982 ReturnStatus
= Status
;
983 } else if (BltOperation
== EfiUgaVideoToBltBuffer
) {
985 // Only need to read the data into buffer one time
997 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
998 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
1001 return UgaDraw
->Blt (
1004 EfiUgaBltBufferToVideo
,
1009 Private
->UgaHorizontalResolution
,
1010 Private
->UgaVerticalResolution
,
1011 Private
->UgaHorizontalResolution
* sizeof (EFI_UGA_PIXEL
)
1017 DevNullTextOutOutputString (
1018 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1023 Routine Description:
1024 Write a Unicode string to the output device.
1027 Private - Pointer to the console output splitter's private data. It
1028 indicates the calling context.
1029 WString - The NULL-terminated Unicode string to be displayed on the output
1030 device(s). All output devices must also support the Unicode
1031 drawing defined in this file.
1034 EFI_SUCCESS - The string was output to the device.
1035 EFI_DEVICE_ERROR - The device reported an error while attempting to
1037 EFI_UNSUPPORTED - The output device's mode is not currently in a
1039 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
1040 characters in the Unicode string could not be
1041 rendered and were skipped.
1046 UINTN SizeAttribute
;
1048 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
1055 INT32
*NullAttributes
;
1060 Mode
= &Private
->TextOutMode
;
1061 NullScreen
= Private
->DevNullScreen
;
1062 NullAttributes
= Private
->DevNullAttributes
;
1063 LastRow
= Private
->DevNullRows
- 1;
1064 MaxColumn
= Private
->DevNullColumns
;
1066 if (Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1074 if (*WString
== CHAR_BACKSPACE
) {
1076 // If the cursor is at the left edge of the display, then move the cursor
1079 if (Mode
->CursorColumn
== 0 && Mode
->CursorRow
> 0) {
1081 Mode
->CursorColumn
= (INT32
) MaxColumn
;
1085 // If the cursor is not at the left edge of the display,
1086 // then move the cursor left one column.
1088 if (Mode
->CursorColumn
> 0) {
1089 Mode
->CursorColumn
--;
1090 if (Mode
->CursorColumn
> 0 &&
1091 NullAttributes
[Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
- 1] & EFI_WIDE_ATTRIBUTE
1093 Mode
->CursorColumn
--;
1096 // Insert an extra backspace
1098 InsertChar
= CHAR_BACKSPACE
;
1103 InsertChar
= TempChar
;
1116 } else if (*WString
== CHAR_LINEFEED
) {
1118 // If the cursor is at the bottom of the display,
1119 // then scroll the display one row, and do not update
1120 // the cursor position. Otherwise, move the cursor down one row.
1122 if (Mode
->CursorRow
== (INT32
) (LastRow
)) {
1124 // Scroll Screen Up One Row
1126 SizeAttribute
= LastRow
* MaxColumn
;
1129 NullAttributes
+ MaxColumn
,
1130 SizeAttribute
* sizeof (INT32
)
1134 // Each row has an ending CHAR_NULL. So one more character each line
1135 // for DevNullScreen than DevNullAttributes
1137 SizeScreen
= SizeAttribute
+ LastRow
;
1140 NullScreen
+ (MaxColumn
+ 1),
1141 SizeScreen
* sizeof (CHAR16
)
1145 // Print Blank Line at last line
1147 Screen
= NullScreen
+ SizeScreen
;
1148 Attribute
= NullAttributes
+ SizeAttribute
;
1150 for (Index
= 0; Index
< MaxColumn
; Index
++, Screen
++, Attribute
++) {
1152 *Attribute
= Mode
->Attribute
;
1159 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
1161 // Move the cursor to the beginning of the current row.
1163 Mode
->CursorColumn
= 0;
1167 // Print the character at the current cursor position and
1168 // move the cursor right one column. If this moves the cursor
1169 // past the right edge of the display, then the line should wrap to
1170 // the beginning of the next line. This is equivalent to inserting
1171 // a CR and an LF. Note that if the cursor is at the bottom of the
1172 // display, and the line wraps, then the display will be scrolled
1175 Index
= Mode
->CursorRow
* MaxColumn
+ Mode
->CursorColumn
;
1177 while (Mode
->CursorColumn
< (INT32
) MaxColumn
) {
1178 if (*WString
== CHAR_NULL
) {
1182 if (*WString
== CHAR_BACKSPACE
) {
1186 if (*WString
== CHAR_LINEFEED
) {
1190 if (*WString
== CHAR_CARRIAGE_RETURN
) {
1194 if (*WString
== WIDE_CHAR
|| *WString
== NARROW_CHAR
) {
1195 CurrentWidth
= (*WString
== WIDE_CHAR
) ? 2 : 1;
1200 if (Mode
->CursorColumn
+ CurrentWidth
> (INT32
) MaxColumn
) {
1202 // If a wide char is at the rightmost column, then move the char
1203 // to the beginning of the next row
1205 NullScreen
[Index
+ Mode
->CursorRow
] = L
' ';
1206 NullAttributes
[Index
] = Mode
->Attribute
| (UINT32
) EFI_WIDE_ATTRIBUTE
;
1208 Mode
->CursorColumn
++;
1210 NullScreen
[Index
+ Mode
->CursorRow
] = *WString
;
1211 NullAttributes
[Index
] = Mode
->Attribute
;
1212 if (CurrentWidth
== 1) {
1213 NullAttributes
[Index
] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1215 NullAttributes
[Index
] |= (UINT32
) EFI_WIDE_ATTRIBUTE
;
1216 NullAttributes
[Index
+ 1] &= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
1219 Index
+= CurrentWidth
;
1221 Mode
->CursorColumn
+= CurrentWidth
;
1225 // At the end of line, output carriage return and line feed
1227 if (Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
1228 DevNullTextOutOutputString (Private
, mCrLfString
);
1237 DevNullTextOutSetMode (
1238 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1243 Routine Description:
1244 Sets the output device(s) to a specified mode.
1247 Private - Private data structure pointer.
1248 ModeNumber - The mode number to set.
1251 EFI_SUCCESS - The requested text mode was set.
1252 EFI_DEVICE_ERROR - The device had an error and
1253 could not complete the request.
1254 EFI_UNSUPPORTED - The mode number was not valid.
1255 EFI_OUT_OF_RESOURCES - Out of resources.
1262 TEXT_OUT_SPLITTER_QUERY_DATA
*Mode
;
1265 // No extra check for ModeNumber here, as it has been checked in
1266 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1268 Mode
= &(Private
->TextOutQueryData
[ModeNumber
]);
1270 Column
= Mode
->Columns
;
1272 if (Row
<= 0 && Column
<= 0) {
1273 return EFI_UNSUPPORTED
;
1276 if (Private
->DevNullColumns
!= Column
|| Private
->DevNullRows
!= Row
) {
1278 Private
->TextOutMode
.Mode
= (INT32
) ModeNumber
;
1279 Private
->DevNullColumns
= Column
;
1280 Private
->DevNullRows
= Row
;
1282 gBS
->FreePool (Private
->DevNullScreen
);
1284 Size
= (Row
* (Column
+ 1)) * sizeof (CHAR16
);
1285 Private
->DevNullScreen
= AllocateZeroPool (Size
);
1286 if (Private
->DevNullScreen
== NULL
) {
1287 return EFI_OUT_OF_RESOURCES
;
1290 gBS
->FreePool (Private
->DevNullAttributes
);
1292 Size
= Row
* Column
* sizeof (INT32
);
1293 Private
->DevNullAttributes
= AllocateZeroPool (Size
);
1294 if (Private
->DevNullAttributes
== NULL
) {
1295 return EFI_OUT_OF_RESOURCES
;
1299 DevNullTextOutClearScreen (Private
);
1305 DevNullTextOutClearScreen (
1306 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1310 Routine Description:
1311 Clears the output device(s) display to the currently selected background
1315 Private - Protocol instance pointer.
1318 EFI_SUCCESS - The operation completed successfully.
1319 EFI_DEVICE_ERROR - The device had an error and
1320 could not complete the request.
1321 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1329 INT32 CurrentAttribute
;
1332 // Clear the DevNull Text Out Buffers.
1333 // The screen is filled with spaces.
1334 // The attributes are all synced with the current Simple Text Out Attribute
1336 Screen
= Private
->DevNullScreen
;
1337 Attributes
= Private
->DevNullAttributes
;
1338 CurrentAttribute
= Private
->TextOutMode
.Attribute
;
1340 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++) {
1341 for (Column
= 0; Column
< Private
->DevNullColumns
; Column
++, Screen
++, Attributes
++) {
1343 *Attributes
= CurrentAttribute
;
1346 // Each line of the screen has a NULL on the end so we must skip over it
1351 DevNullTextOutSetCursorPosition (Private
, 0, 0);
1353 return DevNullTextOutEnableCursor (Private
, TRUE
);
1357 DevNullTextOutSetCursorPosition (
1358 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1364 Routine Description:
1365 Sets the current coordinates of the cursor position
1368 Private - Protocol instance pointer.
1369 Column, Row - the position to set the cursor to. Must be greater than or
1370 equal to zero and less than the number of columns and rows
1374 EFI_SUCCESS - The operation completed successfully.
1375 EFI_DEVICE_ERROR - The device had an error and
1376 could not complete the request.
1377 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1378 cursor position is invalid for the current mode.
1383 // No need to do extra check here as whether (Column, Row) is valid has
1384 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1385 // always be supported.
1387 Private
->TextOutMode
.CursorColumn
= (INT32
) Column
;
1388 Private
->TextOutMode
.CursorRow
= (INT32
) Row
;
1394 DevNullTextOutEnableCursor (
1395 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
,
1399 Routine Description:
1401 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1402 In this driver, the cursor cannot be hidden.
1406 Private - Indicates the calling context.
1408 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1409 is set to be invisible.
1413 EFI_SUCCESS - The request is valid.
1418 Private
->TextOutMode
.CursorVisible
= Visible
;
1424 DevNullSyncGopStdOut (
1425 IN TEXT_OUT_SPLITTER_PRIVATE_DATA
*Private
1428 Routine Description:
1429 Take the DevNull TextOut device and update the Simple Text Out on every
1433 Private - Indicates the calling context.
1436 EFI_SUCCESS - The request is valid.
1437 other - Return status of TextOut->OutputString ()
1442 EFI_STATUS ReturnStatus
;
1447 UINTN CurrentColumn
;
1450 INT32 StartAttribute
;
1451 BOOLEAN StartCursorState
;
1456 CHAR16
*ScreenStart
;
1457 INT32 CurrentAttribute
;
1459 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
1462 // Save the devices Attributes, Cursor enable state and location
1464 StartColumn
= Private
->TextOutMode
.CursorColumn
;
1465 StartRow
= Private
->TextOutMode
.CursorRow
;
1466 StartAttribute
= Private
->TextOutMode
.Attribute
;
1467 StartCursorState
= Private
->TextOutMode
.CursorVisible
;
1469 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1471 Sto
= Private
->TextOutList
[List
].TextOut
;
1474 // Skip non GOP/UGA devices
1476 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1477 Sto
->EnableCursor (Sto
, FALSE
);
1478 Sto
->ClearScreen (Sto
);
1482 ReturnStatus
= EFI_SUCCESS
;
1483 Screen
= Private
->DevNullScreen
;
1484 Attributes
= Private
->DevNullAttributes
;
1485 MaxColumn
= Private
->DevNullColumns
;
1487 Buffer
= AllocateZeroPool ((MaxColumn
+ 1) * sizeof (CHAR16
));
1489 for (Row
= 0; Row
< Private
->DevNullRows
; Row
++, Screen
+= (MaxColumn
+ 1), Attributes
+= MaxColumn
) {
1491 if (Row
== (Private
->DevNullRows
- 1)) {
1493 // Don't ever sync the last character as it will scroll the screen
1495 Screen
[MaxColumn
- 1] = 0x00;
1499 while (Column
< MaxColumn
) {
1500 if (Screen
[Column
]) {
1501 CurrentAttribute
= Attributes
[Column
];
1502 CurrentColumn
= Column
;
1503 ScreenStart
= &Screen
[Column
];
1506 // the line end is alway 0x0. So Column should be less than MaxColumn
1507 // It should be still in the same row
1509 for (Str
= ScreenStart
, BufferTail
= Buffer
; *Str
!= 0; Str
++, Column
++) {
1511 if (Attributes
[Column
] != CurrentAttribute
) {
1518 if (Attributes
[Column
] & EFI_WIDE_ATTRIBUTE
) {
1526 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1528 Sto
= Private
->TextOutList
[List
].TextOut
;
1531 // Skip non GOP/UGA devices
1533 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1534 Sto
->SetAttribute (Sto
, CurrentAttribute
);
1535 Sto
->SetCursorPosition (Sto
, CurrentColumn
, Row
);
1536 Status
= Sto
->OutputString (Sto
, Buffer
);
1537 if (EFI_ERROR (Status
)) {
1538 ReturnStatus
= Status
;
1549 // Restore the devices Attributes, Cursor enable state and location
1551 for (List
= 0; List
< Private
->CurrentNumberOfConsoles
; List
++) {
1552 Sto
= Private
->TextOutList
[List
].TextOut
;
1555 // Skip non GOP/UGA devices
1557 if ((Private
->TextOutList
[List
].GraphicsOutput
!= NULL
) || (Private
->TextOutList
[List
].UgaDraw
!= NULL
)) {
1558 Sto
->SetAttribute (Sto
, StartAttribute
);
1559 Sto
->SetCursorPosition (Sto
, StartColumn
, StartRow
);
1560 Status
= Sto
->EnableCursor (Sto
, StartCursorState
);
1561 if (EFI_ERROR (Status
)) {
1562 ReturnStatus
= Status
;
1567 gBS
->FreePool (Buffer
);
1569 return ReturnStatus
;