3 Copyright (c) 2006 - 2007, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
14 ConSplitterGraphics.c
\r
18 Support for ConsoleControl protocol. Support for UGA Draw spliter.
\r
19 Support for DevNull Console Out. This console uses memory buffers
\r
20 to represnt the console. It allows a console to start very early and
\r
21 when a new console is added it is synced up with the current console
\r
25 #include "ConSplitter.h"
\r
28 static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
\r
32 ConSpliterConsoleControlGetMode (
\r
33 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
\r
34 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
\r
35 OUT BOOLEAN *GopExists,
\r
36 OUT BOOLEAN *StdInLocked
\r
40 Routine Description:
\r
41 Return the current video mode information. Also returns info about existence
\r
42 of UGA Draw devices in system, and if the Std In device is locked. All the
\r
43 arguments are optional and only returned if a non NULL pointer is passed in.
\r
46 This - Protocol instance pointer.
\r
47 Mode - Are we in text of grahics mode.
\r
48 UgaExists - TRUE if UGA Spliter has found a UGA device
\r
49 StdInLocked - TRUE if StdIn device is keyboard locked
\r
52 EFI_SUCCESS - Mode information returned.
\r
53 EFI_INVALID_PARAMETER - Invalid parameters.
\r
57 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
60 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
63 return EFI_INVALID_PARAMETER;
\r
66 *Mode = Private->ConsoleOutputMode;
\r
68 if (GopExists != NULL) {
\r
70 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
\r
71 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {
\r
78 if (StdInLocked != NULL) {
\r
79 *StdInLocked = ConSpliterConssoleControlStdInLocked ();
\r
87 ConSpliterConsoleControlSetMode (
\r
88 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
\r
89 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
\r
93 Routine Description:
\r
94 Set the current mode to either text or graphics. Graphics is
\r
98 This - Protocol instance pointer.
\r
99 Mode - Mode to set the
\r
102 EFI_SUCCESS - Mode information returned.
\r
103 EFI_INVALID_PARAMETER - Invalid parameter.
\r
104 EFI_UNSUPPORTED - Operation unsupported.
\r
108 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
110 TEXT_OUT_AND_GOP_DATA *TextAndGop;
\r
113 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
115 if (Mode >= EfiConsoleControlScreenMaxValue) {
\r
116 return EFI_INVALID_PARAMETER;
\r
120 // Judge current mode with wanted mode at first.
\r
122 if (Private->ConsoleOutputMode == Mode) {
\r
123 return EFI_SUCCESS;
\r
127 TextAndGop = &Private->TextOutList[0];
\r
128 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
\r
129 if ((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL)) {
\r
135 if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {
\r
136 return EFI_UNSUPPORTED;
\r
139 Private->ConsoleOutputMode = Mode;
\r
141 TextAndGop = &Private->TextOutList[0];
\r
142 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
\r
144 TextAndGop->TextOutEnabled = TRUE;
\r
146 // If we are going into Graphics mode disable ConOut to any UGA device
\r
148 if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) {
\r
149 TextAndGop->TextOutEnabled = FALSE;
\r
150 if (FeaturePcdGet (PcdConOutGopSupport)) {
\r
151 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
\r
152 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {
\r
153 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
\r
157 if (Mode == EfiConsoleControlScreenText) {
\r
158 DevNullSyncGopStdOut (Private);
\r
160 return EFI_SUCCESS;
\r
165 ConSpliterGraphicsOutputQueryMode (
\r
166 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
\r
167 IN UINT32 ModeNumber,
\r
168 OUT UINTN *SizeOfInfo,
\r
169 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
\r
173 Routine Description:
\r
174 Return the current video mode information.
\r
177 This - Protocol instance pointer.
\r
178 ModeNumber - The mode number to return information on.
\r
179 Info - Caller allocated buffer that returns information about ModeNumber.
\r
180 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
\r
183 EFI_SUCCESS - Mode information returned.
\r
184 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
\r
185 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
\r
186 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
\r
187 EFI_INVALID_PARAMETER - One of the input args was NULL.
\r
191 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
192 TEXT_OUT_GOP_MODE *Mode;
\r
194 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
\r
195 return EFI_INVALID_PARAMETER;
\r
199 // retrieve private data
\r
201 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
203 if (Private->HardwareNeedsStarting) {
\r
204 return EFI_NOT_STARTED;
\r
207 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
\r
209 if (*Info == NULL) {
\r
210 return EFI_OUT_OF_RESOURCES;
\r
213 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
\r
215 CopyMem (*Info, Private->GraphicsOutput.Mode->Info, *SizeOfInfo);
\r
216 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
\r
217 (*Info)->HorizontalResolution = Mode->HorizontalResolution;
\r
218 (*Info)->VerticalResolution = Mode->VerticalResolution;
\r
219 (*Info)->PixelsPerScanLine = Mode->HorizontalResolution;
\r
221 return EFI_SUCCESS;
\r
226 ConSpliterGraphicsOutputSetMode (
\r
227 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
\r
228 IN UINT32 ModeNumber
\r
232 Routine Description:
\r
234 Graphics output protocol interface to set video mode
\r
237 This - Protocol instance pointer.
\r
238 ModeNumber - The mode number to be set.
\r
241 EFI_SUCCESS - Graphics mode was changed.
\r
242 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
\r
243 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
\r
248 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
250 EFI_STATUS ReturnStatus;
\r
251 TEXT_OUT_GOP_MODE *Mode;
\r
253 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
\r
256 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
\r
257 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
\r
259 if (ModeNumber >= This->Mode->MaxMode) {
\r
260 return EFI_UNSUPPORTED;
\r
263 if (ModeNumber == This->Mode->Mode) {
\r
264 return EFI_SUCCESS;
\r
267 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
270 // GopDevNullSetMode ()
\r
272 ReturnStatus = EFI_SUCCESS;
\r
275 // Free the old version
\r
277 if (Private->GraphicsOutputBlt != NULL) {
\r
278 FreePool (Private->GraphicsOutputBlt);
\r
282 // Allocate the virtual Blt buffer
\r
284 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
\r
285 Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
\r
286 Private->GraphicsOutputBlt = AllocateZeroPool (Size);
\r
288 if (Private->GraphicsOutputBlt == NULL) {
\r
289 return EFI_OUT_OF_RESOURCES;
\r
292 if (!Private->HardwareNeedsStarting) {
\r
293 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
\r
294 return EFI_UNSUPPORTED;
\r
298 // return the worst status met
\r
300 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
\r
301 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
\r
302 if (GraphicsOutput != NULL) {
\r
304 // Find corresponding ModeNumber of this GraphicsOutput instance
\r
306 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
\r
307 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
\r
308 if (EFI_ERROR (Status)) {
\r
311 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
\r
318 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
\r
319 if (EFI_ERROR (Status)) {
\r
320 ReturnStatus = Status;
\r
324 if (EFI_ERROR (ReturnStatus)) {
\r
325 UgaDraw = Private->TextOutList[Index].UgaDraw;
\r
326 if (UgaDraw != NULL) {
\r
327 Status = UgaDraw->SetMode (
\r
329 Mode->HorizontalResolution,
\r
330 Mode->VerticalResolution,
\r
334 if (EFI_ERROR (Status)) {
\r
335 ReturnStatus = Status;
\r
341 This->Mode->Mode = ModeNumber;
\r
343 Info = This->Mode->Info;
\r
344 Info->HorizontalResolution = Mode->HorizontalResolution;
\r
345 Info->VerticalResolution = Mode->VerticalResolution;
\r
346 Info->PixelsPerScanLine = Mode->HorizontalResolution;
\r
349 // Information is not enough here, so the following items remain unchanged:
\r
350 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
\r
351 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
\r
352 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
\r
355 Private->HardwareNeedsStarting = FALSE;
\r
357 return ReturnStatus;
\r
362 DevNullGraphicsOutputBlt (
\r
363 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
364 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
\r
365 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
\r
368 IN UINTN DestinationX,
\r
369 IN UINTN DestinationY,
\r
372 IN UINTN Delta OPTIONAL
\r
378 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
\r
379 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;
\r
380 UINTN HorizontalResolution;
\r
381 UINTN VerticalResolution;
\r
383 if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
\r
384 return EFI_INVALID_PARAMETER;
\r
387 if (Width == 0 || Height == 0) {
\r
388 return EFI_INVALID_PARAMETER;
\r
392 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
\r
395 HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
\r
396 VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution;
\r
399 // We need to fill the Virtual Screen buffer with the blt data.
\r
401 if (BltOperation == EfiBltVideoToBltBuffer) {
\r
403 // Video to BltBuffer: Source is Video, destination is BltBuffer
\r
405 if ((SourceY + Height) > VerticalResolution) {
\r
406 return EFI_INVALID_PARAMETER;
\r
409 if ((SourceX + Width) > HorizontalResolution) {
\r
410 return EFI_INVALID_PARAMETER;
\r
413 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
\r
414 ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];
\r
416 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
\r
417 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta);
\r
418 ScreenPtr += HorizontalResolution;
\r
423 // BltBuffer to Video: Source is BltBuffer, destination is Video
\r
425 if (DestinationY + Height > VerticalResolution) {
\r
426 return EFI_INVALID_PARAMETER;
\r
429 if (DestinationX + Width > HorizontalResolution) {
\r
430 return EFI_INVALID_PARAMETER;
\r
433 if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {
\r
435 // Copy backwards, only care the Video to Video Blt
\r
437 ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
\r
438 SrcY = SourceY + Height - 1;
\r
442 // Copy forwards, for other cases
\r
444 ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];
\r
449 while (Height != 0) {
\r
450 if (BltOperation == EfiBltVideoFill) {
\r
451 for (Index = 0; Index < Width; Index++) {
\r
452 ScreenPtr[Index] = *BltBuffer;
\r
455 if (BltOperation == EfiBltBufferToVideo) {
\r
456 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
\r
458 BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];
\r
461 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
\r
465 ScreenPtr += HorizontalResolution;
\r
468 ScreenPtr -= HorizontalResolution;
\r
475 return EFI_SUCCESS;
\r
480 ConSpliterGraphicsOutputBlt (
\r
481 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
\r
482 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
\r
483 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
\r
486 IN UINTN DestinationX,
\r
487 IN UINTN DestinationY,
\r
490 IN UINTN Delta OPTIONAL
\r
494 Routine Description:
\r
495 The following table defines actions for BltOperations:
\r
496 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
\r
497 directly to every pixel of the video display rectangle
\r
498 (DestinationX, DestinationY)
\r
499 (DestinationX + Width, DestinationY + Height).
\r
500 Only one pixel will be used from the BltBuffer. Delta is NOT used.
\r
501 EfiBltVideoToBltBuffer - Read data from the video display rectangle
\r
502 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
\r
503 the BltBuffer rectangle (DestinationX, DestinationY )
\r
504 (DestinationX + Width, DestinationY + Height). If DestinationX or
\r
505 DestinationY is not zero then Delta must be set to the length in bytes
\r
506 of a row in the BltBuffer.
\r
507 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
\r
508 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
\r
509 video display rectangle (DestinationX, DestinationY)
\r
510 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
\r
511 not zero then Delta must be set to the length in bytes of a row in the
\r
513 EfiBltVideoToVideo - Copy from the video display rectangle
\r
514 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
\r
515 to the video display rectangle (DestinationX, DestinationY)
\r
516 (DestinationX + Width, DestinationY + Height).
\r
517 The BltBuffer and Delta are not used in this mode.
\r
520 This - Protocol instance pointer.
\r
521 BltBuffer - Buffer containing data to blit into video buffer. This
\r
522 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
\r
523 BltOperation - Operation to perform on BlitBuffer and video memory
\r
524 SourceX - X coordinate of source for the BltBuffer.
\r
525 SourceY - Y coordinate of source for the BltBuffer.
\r
526 DestinationX - X coordinate of destination for the BltBuffer.
\r
527 DestinationY - Y coordinate of destination for the BltBuffer.
\r
528 Width - Width of rectangle in BltBuffer in pixels.
\r
529 Height - Hight of rectangle in BltBuffer in pixels.
\r
533 EFI_SUCCESS - The Blt operation completed.
\r
534 EFI_INVALID_PARAMETER - BltOperation is not valid.
\r
535 EFI_DEVICE_ERROR - A hardware error occured writting to the video
\r
541 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
543 EFI_STATUS ReturnStatus;
\r
544 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
\r
545 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
\r
547 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
550 // Sync up DevNull GOP device
\r
552 ReturnStatus = DevNullGraphicsOutputBlt (
\r
565 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
\r
566 return ReturnStatus;
\r
569 // return the worst status met
\r
571 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
\r
572 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
\r
573 if (GraphicsOutput != NULL) {
\r
574 Status = GraphicsOutput->Blt (
\r
586 if (EFI_ERROR (Status)) {
\r
587 ReturnStatus = Status;
\r
588 } else if (BltOperation == EfiBltVideoToBltBuffer) {
\r
590 // Only need to read the data into buffer one time
\r
592 return EFI_SUCCESS;
\r
596 UgaDraw = Private->TextOutList[Index].UgaDraw;
\r
597 if (UgaDraw != NULL) {
\r
598 Status = UgaDraw->Blt (
\r
600 (EFI_UGA_PIXEL *) BltBuffer,
\r
601 (EFI_UGA_BLT_OPERATION) BltOperation,
\r
610 if (EFI_ERROR (Status)) {
\r
611 ReturnStatus = Status;
\r
612 } else if (BltOperation == EfiBltVideoToBltBuffer) {
\r
614 // Only need to read the data into buffer one time
\r
616 return EFI_SUCCESS;
\r
621 return ReturnStatus;
\r
626 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
627 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
\r
628 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
\r
631 if (GraphicsOutput != NULL) {
\r
632 return GraphicsOutput->Blt (
\r
634 Private->GraphicsOutputBlt,
\r
635 EfiBltBufferToVideo,
\r
640 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
\r
641 Private->GraphicsOutput.Mode->Info->VerticalResolution,
\r
645 return UgaDraw->Blt (
\r
647 (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,
\r
648 EfiUgaBltBufferToVideo,
\r
653 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
\r
654 Private->GraphicsOutput.Mode->Info->VerticalResolution,
\r
662 ConSpliterUgaDrawGetMode (
\r
663 IN EFI_UGA_DRAW_PROTOCOL *This,
\r
664 OUT UINT32 *HorizontalResolution,
\r
665 OUT UINT32 *VerticalResolution,
\r
666 OUT UINT32 *ColorDepth,
\r
667 OUT UINT32 *RefreshRate
\r
671 Routine Description:
\r
672 Return the current video mode information.
\r
675 This - Protocol instance pointer.
\r
676 HorizontalResolution - Current video horizontal resolution in pixels
\r
677 VerticalResolution - Current video vertical resolution in pixels
\r
678 ColorDepth - Current video color depth in bits per pixel
\r
679 RefreshRate - Current video refresh rate in Hz.
\r
682 EFI_SUCCESS - Mode information returned.
\r
683 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
\r
684 EFI_INVALID_PARAMETER - One of the input args was NULL.
\r
688 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
690 if (!(HorizontalResolution && VerticalResolution && RefreshRate && ColorDepth)) {
\r
691 return EFI_INVALID_PARAMETER;
\r
694 // retrieve private data
\r
696 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
698 *HorizontalResolution = Private->UgaHorizontalResolution;
\r
699 *VerticalResolution = Private->UgaVerticalResolution;
\r
700 *ColorDepth = Private->UgaColorDepth;
\r
701 *RefreshRate = Private->UgaRefreshRate;
\r
703 return EFI_SUCCESS;
\r
708 ConSpliterUgaDrawSetMode (
\r
709 IN EFI_UGA_DRAW_PROTOCOL *This,
\r
710 IN UINT32 HorizontalResolution,
\r
711 IN UINT32 VerticalResolution,
\r
712 IN UINT32 ColorDepth,
\r
713 IN UINT32 RefreshRate
\r
717 Routine Description:
\r
718 Return the current video mode information.
\r
721 This - Protocol instance pointer.
\r
722 HorizontalResolution - Current video horizontal resolution in pixels
\r
723 VerticalResolution - Current video vertical resolution in pixels
\r
724 ColorDepth - Current video color depth in bits per pixel
\r
725 RefreshRate - Current video refresh rate in Hz.
\r
728 EFI_SUCCESS - Mode information returned.
\r
729 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
\r
730 EFI_OUT_OF_RESOURCES - Out of resources.
\r
735 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
737 EFI_STATUS ReturnStatus;
\r
739 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
\r
742 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
\r
743 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
\r
745 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
748 // UgaDevNullSetMode ()
\r
750 ReturnStatus = EFI_SUCCESS;
\r
753 // Free the old version
\r
755 if (Private->UgaBlt != NULL) {
\r
756 FreePool (Private->UgaBlt);
\r
760 // Allocate the virtual Blt buffer
\r
762 Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);
\r
763 Private->UgaBlt = AllocateZeroPool (Size);
\r
764 if (Private->UgaBlt == NULL) {
\r
765 return EFI_OUT_OF_RESOURCES;
\r
769 // Update the Mode data
\r
771 Private->UgaHorizontalResolution = HorizontalResolution;
\r
772 Private->UgaVerticalResolution = VerticalResolution;
\r
773 Private->UgaColorDepth = ColorDepth;
\r
774 Private->UgaRefreshRate = RefreshRate;
\r
776 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
\r
777 return ReturnStatus;
\r
780 // return the worst status met
\r
782 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
\r
783 UgaDraw = Private->TextOutList[Index].UgaDraw;
\r
784 if (UgaDraw != NULL) {
\r
785 Status = UgaDraw->SetMode (
\r
787 HorizontalResolution,
\r
788 VerticalResolution,
\r
792 if (EFI_ERROR (Status)) {
\r
793 ReturnStatus = Status;
\r
797 if (EFI_ERROR (ReturnStatus)) {
\r
798 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
\r
799 if (GraphicsOutput != NULL) {
\r
801 // Find corresponding ModeNumber of this GraphicsOutput instance
\r
803 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
\r
804 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
\r
805 if (EFI_ERROR (Status)) {
\r
808 if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
\r
815 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
\r
816 if (EFI_ERROR (Status)) {
\r
817 ReturnStatus = Status;
\r
823 return ReturnStatus;
\r
828 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
829 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
\r
830 IN EFI_UGA_BLT_OPERATION BltOperation,
\r
833 IN UINTN DestinationX,
\r
834 IN UINTN DestinationY,
\r
837 IN UINTN Delta OPTIONAL
\r
843 EFI_UGA_PIXEL *BltPtr;
\r
844 EFI_UGA_PIXEL *ScreenPtr;
\r
845 UINT32 HorizontalResolution;
\r
846 UINT32 VerticalResolution;
\r
848 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
\r
849 return EFI_INVALID_PARAMETER;
\r
852 if (Width == 0 || Height == 0) {
\r
853 return EFI_INVALID_PARAMETER;
\r
857 Delta = Width * sizeof (EFI_UGA_PIXEL);
\r
860 HorizontalResolution = Private->UgaHorizontalResolution;
\r
861 VerticalResolution = Private->UgaVerticalResolution;
\r
864 // We need to fill the Virtual Screen buffer with the blt data.
\r
866 if (BltOperation == EfiUgaVideoToBltBuffer) {
\r
868 // Video to BltBuffer: Source is Video, destination is BltBuffer
\r
870 if ((SourceY + Height) > VerticalResolution) {
\r
871 return EFI_INVALID_PARAMETER;
\r
874 if ((SourceX + Width) > HorizontalResolution) {
\r
875 return EFI_INVALID_PARAMETER;
\r
878 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));
\r
879 ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];
\r
881 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));
\r
882 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);
\r
883 ScreenPtr += HorizontalResolution;
\r
888 // BltBuffer to Video: Source is BltBuffer, destination is Video
\r
890 if (DestinationY + Height > VerticalResolution) {
\r
891 return EFI_INVALID_PARAMETER;
\r
894 if (DestinationX + Width > HorizontalResolution) {
\r
895 return EFI_INVALID_PARAMETER;
\r
898 if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {
\r
900 // Copy backwards, only care the Video to Video Blt
\r
902 ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
\r
903 SrcY = SourceY + Height - 1;
\r
907 // Copy forwards, for other cases
\r
909 ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
\r
914 while (Height != 0) {
\r
915 if (BltOperation == EfiUgaVideoFill) {
\r
916 for (Index = 0; Index < Width; Index++) {
\r
917 ScreenPtr[Index] = *BltBuffer;
\r
920 if (BltOperation == EfiUgaBltBufferToVideo) {
\r
921 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));
\r
923 BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];
\r
926 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));
\r
930 ScreenPtr += HorizontalResolution;
\r
933 ScreenPtr -= HorizontalResolution;
\r
940 return EFI_SUCCESS;
\r
945 ConSpliterUgaDrawBlt (
\r
946 IN EFI_UGA_DRAW_PROTOCOL *This,
\r
947 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
\r
948 IN EFI_UGA_BLT_OPERATION BltOperation,
\r
951 IN UINTN DestinationX,
\r
952 IN UINTN DestinationY,
\r
955 IN UINTN Delta OPTIONAL
\r
959 Routine Description:
\r
960 The following table defines actions for BltOperations:
\r
961 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
\r
962 directly to every pixel of the video display rectangle
\r
963 (DestinationX, DestinationY)
\r
964 (DestinationX + Width, DestinationY + Height).
\r
965 Only one pixel will be used from the BltBuffer. Delta is NOT used.
\r
966 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
\r
967 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
\r
968 the BltBuffer rectangle (DestinationX, DestinationY )
\r
969 (DestinationX + Width, DestinationY + Height). If DestinationX or
\r
970 DestinationY is not zero then Delta must be set to the length in bytes
\r
971 of a row in the BltBuffer.
\r
972 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
\r
973 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
\r
974 video display rectangle (DestinationX, DestinationY)
\r
975 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
\r
976 not zero then Delta must be set to the length in bytes of a row in the
\r
978 EfiUgaVideoToVideo - Copy from the video display rectangle
\r
979 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
\r
980 to the video display rectangle (DestinationX, DestinationY)
\r
981 (DestinationX + Width, DestinationY + Height).
\r
982 The BltBuffer and Delta are not used in this mode.
\r
985 This - Protocol instance pointer.
\r
986 BltBuffer - Buffer containing data to blit into video buffer. This
\r
987 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
\r
988 BltOperation - Operation to perform on BlitBuffer and video memory
\r
989 SourceX - X coordinate of source for the BltBuffer.
\r
990 SourceY - Y coordinate of source for the BltBuffer.
\r
991 DestinationX - X coordinate of destination for the BltBuffer.
\r
992 DestinationY - Y coordinate of destination for the BltBuffer.
\r
993 Width - Width of rectangle in BltBuffer in pixels.
\r
994 Height - Hight of rectangle in BltBuffer in pixels.
\r
998 EFI_SUCCESS - The Blt operation completed.
\r
999 EFI_INVALID_PARAMETER - BltOperation is not valid.
\r
1000 EFI_DEVICE_ERROR - A hardware error occured writting to the video
\r
1005 EFI_STATUS Status;
\r
1006 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
\r
1008 EFI_STATUS ReturnStatus;
\r
1009 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
\r
1011 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
\r
1014 // Sync up DevNull UGA device
\r
1016 ReturnStatus = DevNullUgaBlt (
\r
1028 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
\r
1029 return ReturnStatus;
\r
1032 // return the worst status met
\r
1034 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
\r
1035 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
\r
1036 if (GraphicsOutput != NULL) {
\r
1037 Status = GraphicsOutput->Blt (
\r
1039 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,
\r
1040 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,
\r
1049 if (EFI_ERROR (Status)) {
\r
1050 ReturnStatus = Status;
\r
1051 } else if (BltOperation == EfiBltVideoToBltBuffer) {
\r
1053 // Only need to read the data into buffer one time
\r
1055 return EFI_SUCCESS;
\r
1059 if (Private->TextOutList[Index].UgaDraw != NULL) {
\r
1060 Status = Private->TextOutList[Index].UgaDraw->Blt (
\r
1061 Private->TextOutList[Index].UgaDraw,
\r
1072 if (EFI_ERROR (Status)) {
\r
1073 ReturnStatus = Status;
\r
1074 } else if (BltOperation == EfiUgaVideoToBltBuffer) {
\r
1076 // Only need to read the data into buffer one time
\r
1078 return EFI_SUCCESS;
\r
1083 return ReturnStatus;
\r
1088 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
1089 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
\r
1090 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
\r
1093 if (UgaDraw != NULL) {
\r
1094 return UgaDraw->Blt (
\r
1097 EfiUgaBltBufferToVideo,
\r
1102 Private->UgaHorizontalResolution,
\r
1103 Private->UgaVerticalResolution,
\r
1104 Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
\r
1107 return GraphicsOutput->Blt (
\r
1109 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,
\r
1110 EfiBltBufferToVideo,
\r
1115 Private->UgaHorizontalResolution,
\r
1116 Private->UgaVerticalResolution,
\r
1123 DevNullTextOutOutputString (
\r
1124 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
1125 IN CHAR16 *WString
\r
1129 Routine Description:
\r
1130 Write a Unicode string to the output device.
\r
1133 Private - Pointer to the console output splitter's private data. It
\r
1134 indicates the calling context.
\r
1135 WString - The NULL-terminated Unicode string to be displayed on the output
\r
1136 device(s). All output devices must also support the Unicode
\r
1137 drawing defined in this file.
\r
1140 EFI_SUCCESS - The string was output to the device.
\r
1141 EFI_DEVICE_ERROR - The device reported an error while attempting to
\r
1143 EFI_UNSUPPORTED - The output device's mode is not currently in a
\r
1144 defined text mode.
\r
1145 EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
\r
1146 characters in the Unicode string could not be
\r
1147 rendered and were skipped.
\r
1152 UINTN SizeAttribute;
\r
1154 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
\r
1156 CHAR16 *NullScreen;
\r
1157 CHAR16 InsertChar;
\r
1161 INT32 *NullAttributes;
\r
1162 INT32 CurrentWidth;
\r
1166 Mode = &Private->TextOutMode;
\r
1167 NullScreen = Private->DevNullScreen;
\r
1168 NullAttributes = Private->DevNullAttributes;
\r
1169 LastRow = Private->DevNullRows - 1;
\r
1170 MaxColumn = Private->DevNullColumns;
\r
1172 if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
\r
1178 while (*WString) {
\r
1180 if (*WString == CHAR_BACKSPACE) {
\r
1182 // If the cursor is at the left edge of the display, then move the cursor
\r
1185 if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) {
\r
1186 Mode->CursorRow--;
\r
1187 Mode->CursorColumn = (INT32) MaxColumn;
\r
1191 // If the cursor is not at the left edge of the display,
\r
1192 // then move the cursor left one column.
\r
1194 if (Mode->CursorColumn > 0) {
\r
1195 Mode->CursorColumn--;
\r
1196 if (Mode->CursorColumn > 0 &&
\r
1197 NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE
\r
1199 Mode->CursorColumn--;
\r
1202 // Insert an extra backspace
\r
1204 InsertChar = CHAR_BACKSPACE;
\r
1205 PStr = WString + 1;
\r
1208 *PStr = InsertChar;
\r
1209 InsertChar = TempChar;
\r
1213 *PStr = InsertChar;
\r
1222 } else if (*WString == CHAR_LINEFEED) {
\r
1224 // If the cursor is at the bottom of the display,
\r
1225 // then scroll the display one row, and do not update
\r
1226 // the cursor position. Otherwise, move the cursor down one row.
\r
1228 if (Mode->CursorRow == (INT32) (LastRow)) {
\r
1230 // Scroll Screen Up One Row
\r
1232 SizeAttribute = LastRow * MaxColumn;
\r
1235 NullAttributes + MaxColumn,
\r
1236 SizeAttribute * sizeof (INT32)
\r
1240 // Each row has an ending CHAR_NULL. So one more character each line
\r
1241 // for DevNullScreen than DevNullAttributes
\r
1243 SizeScreen = SizeAttribute + LastRow;
\r
1246 NullScreen + (MaxColumn + 1),
\r
1247 SizeScreen * sizeof (CHAR16)
\r
1251 // Print Blank Line at last line
\r
1253 Screen = NullScreen + SizeScreen;
\r
1254 Attribute = NullAttributes + SizeAttribute;
\r
1256 for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) {
\r
1258 *Attribute = Mode->Attribute;
\r
1261 Mode->CursorRow++;
\r
1265 } else if (*WString == CHAR_CARRIAGE_RETURN) {
\r
1267 // Move the cursor to the beginning of the current row.
\r
1269 Mode->CursorColumn = 0;
\r
1273 // Print the character at the current cursor position and
\r
1274 // move the cursor right one column. If this moves the cursor
\r
1275 // past the right edge of the display, then the line should wrap to
\r
1276 // the beginning of the next line. This is equivalent to inserting
\r
1277 // a CR and an LF. Note that if the cursor is at the bottom of the
\r
1278 // display, and the line wraps, then the display will be scrolled
\r
1281 Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn;
\r
1283 while (Mode->CursorColumn < (INT32) MaxColumn) {
\r
1284 if (*WString == CHAR_NULL) {
\r
1288 if (*WString == CHAR_BACKSPACE) {
\r
1292 if (*WString == CHAR_LINEFEED) {
\r
1296 if (*WString == CHAR_CARRIAGE_RETURN) {
\r
1300 if (*WString == UNICODE_WIDE_CHAR || *WString == UNICODE_NARROW_CHAR) {
\r
1301 CurrentWidth = (*WString == UNICODE_WIDE_CHAR) ? 2 : 1;
\r
1306 if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) {
\r
1308 // If a wide char is at the rightmost column, then move the char
\r
1309 // to the beginning of the next row
\r
1311 NullScreen[Index + Mode->CursorRow] = L' ';
\r
1312 NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE;
\r
1314 Mode->CursorColumn++;
\r
1316 NullScreen[Index + Mode->CursorRow] = *WString;
\r
1317 NullAttributes[Index] = Mode->Attribute;
\r
1318 if (CurrentWidth == 1) {
\r
1319 NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
\r
1321 NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE;
\r
1322 NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
\r
1325 Index += CurrentWidth;
\r
1327 Mode->CursorColumn += CurrentWidth;
\r
1331 // At the end of line, output carriage return and line feed
\r
1333 if (Mode->CursorColumn >= (INT32) MaxColumn) {
\r
1334 DevNullTextOutOutputString (Private, mCrLfString);
\r
1339 return EFI_SUCCESS;
\r
1343 DevNullTextOutSetMode (
\r
1344 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
1345 IN UINTN ModeNumber
\r
1349 Routine Description:
\r
1350 Sets the output device(s) to a specified mode.
\r
1353 Private - Private data structure pointer.
\r
1354 ModeNumber - The mode number to set.
\r
1357 EFI_SUCCESS - The requested text mode was set.
\r
1358 EFI_DEVICE_ERROR - The device had an error and
\r
1359 could not complete the request.
\r
1360 EFI_UNSUPPORTED - The mode number was not valid.
\r
1361 EFI_OUT_OF_RESOURCES - Out of resources.
\r
1368 TEXT_OUT_SPLITTER_QUERY_DATA *Mode;
\r
1371 // No extra check for ModeNumber here, as it has been checked in
\r
1372 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
\r
1374 Mode = &(Private->TextOutQueryData[ModeNumber]);
\r
1376 Column = Mode->Columns;
\r
1378 if (Row <= 0 && Column <= 0) {
\r
1379 return EFI_UNSUPPORTED;
\r
1382 if (Private->DevNullColumns != Column || Private->DevNullRows != Row) {
\r
1384 Private->TextOutMode.Mode = (INT32) ModeNumber;
\r
1385 Private->DevNullColumns = Column;
\r
1386 Private->DevNullRows = Row;
\r
1388 if (Private->DevNullScreen != NULL) {
\r
1389 FreePool (Private->DevNullScreen);
\r
1392 Size = (Row * (Column + 1)) * sizeof (CHAR16);
\r
1393 Private->DevNullScreen = AllocateZeroPool (Size);
\r
1394 if (Private->DevNullScreen == NULL) {
\r
1395 return EFI_OUT_OF_RESOURCES;
\r
1398 if (Private->DevNullAttributes != NULL) {
\r
1399 FreePool (Private->DevNullAttributes);
\r
1402 Size = Row * Column * sizeof (INT32);
\r
1403 Private->DevNullAttributes = AllocateZeroPool (Size);
\r
1404 if (Private->DevNullAttributes == NULL) {
\r
1405 return EFI_OUT_OF_RESOURCES;
\r
1409 DevNullTextOutClearScreen (Private);
\r
1411 return EFI_SUCCESS;
\r
1415 DevNullTextOutClearScreen (
\r
1416 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
\r
1420 Routine Description:
\r
1421 Clears the output device(s) display to the currently selected background
\r
1425 Private - Protocol instance pointer.
\r
1428 EFI_SUCCESS - The operation completed successfully.
\r
1429 EFI_DEVICE_ERROR - The device had an error and
\r
1430 could not complete the request.
\r
1431 EFI_UNSUPPORTED - The output device is not in a valid text mode.
\r
1438 INT32 *Attributes;
\r
1439 INT32 CurrentAttribute;
\r
1442 // Clear the DevNull Text Out Buffers.
\r
1443 // The screen is filled with spaces.
\r
1444 // The attributes are all synced with the current Simple Text Out Attribute
\r
1446 Screen = Private->DevNullScreen;
\r
1447 Attributes = Private->DevNullAttributes;
\r
1448 CurrentAttribute = Private->TextOutMode.Attribute;
\r
1450 for (Row = 0; Row < Private->DevNullRows; Row++) {
\r
1451 for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {
\r
1453 *Attributes = CurrentAttribute;
\r
1456 // Each line of the screen has a NULL on the end so we must skip over it
\r
1461 DevNullTextOutSetCursorPosition (Private, 0, 0);
\r
1463 return DevNullTextOutEnableCursor (Private, TRUE);
\r
1467 DevNullTextOutSetCursorPosition (
\r
1468 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
1474 Routine Description:
\r
1475 Sets the current coordinates of the cursor position
\r
1478 Private - Protocol instance pointer.
\r
1479 Column, Row - the position to set the cursor to. Must be greater than or
\r
1480 equal to zero and less than the number of columns and rows
\r
1484 EFI_SUCCESS - The operation completed successfully.
\r
1485 EFI_DEVICE_ERROR - The device had an error and
\r
1486 could not complete the request.
\r
1487 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
\r
1488 cursor position is invalid for the current mode.
\r
1493 // No need to do extra check here as whether (Column, Row) is valid has
\r
1494 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
\r
1495 // always be supported.
\r
1497 Private->TextOutMode.CursorColumn = (INT32) Column;
\r
1498 Private->TextOutMode.CursorRow = (INT32) Row;
\r
1500 return EFI_SUCCESS;
\r
1504 DevNullTextOutEnableCursor (
\r
1505 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
\r
1506 IN BOOLEAN Visible
\r
1509 Routine Description:
\r
1511 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
\r
1512 In this driver, the cursor cannot be hidden.
\r
1516 Private - Indicates the calling context.
\r
1518 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
\r
1519 is set to be invisible.
\r
1523 EFI_SUCCESS - The request is valid.
\r
1528 Private->TextOutMode.CursorVisible = Visible;
\r
1530 return EFI_SUCCESS;
\r
1534 DevNullSyncGopStdOut (
\r
1535 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
\r
1538 Routine Description:
\r
1539 Take the DevNull TextOut device and update the Simple Text Out on every
\r
1543 Private - Indicates the calling context.
\r
1546 EFI_SUCCESS - The request is valid.
\r
1547 other - Return status of TextOut->OutputString ()
\r
1551 EFI_STATUS Status;
\r
1552 EFI_STATUS ReturnStatus;
\r
1557 UINTN CurrentColumn;
\r
1559 UINTN StartColumn;
\r
1560 INT32 StartAttribute;
\r
1561 BOOLEAN StartCursorState;
\r
1565 CHAR16 *BufferTail;
\r
1566 CHAR16 *ScreenStart;
\r
1567 INT32 CurrentAttribute;
\r
1568 INT32 *Attributes;
\r
1569 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
\r
1572 // Save the devices Attributes, Cursor enable state and location
\r
1574 StartColumn = Private->TextOutMode.CursorColumn;
\r
1575 StartRow = Private->TextOutMode.CursorRow;
\r
1576 StartAttribute = Private->TextOutMode.Attribute;
\r
1577 StartCursorState = Private->TextOutMode.CursorVisible;
\r
1579 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
\r
1581 Sto = Private->TextOutList[List].TextOut;
\r
1584 // Skip non GOP/UGA devices
\r
1586 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
\r
1587 Sto->EnableCursor (Sto, FALSE);
\r
1588 Sto->ClearScreen (Sto);
\r
1592 ReturnStatus = EFI_SUCCESS;
\r
1593 Screen = Private->DevNullScreen;
\r
1594 Attributes = Private->DevNullAttributes;
\r
1595 MaxColumn = Private->DevNullColumns;
\r
1597 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
\r
1598 if (Buffer == NULL) {
\r
1599 return ReturnStatus;
\r
1602 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
\r
1604 if (Row == (Private->DevNullRows - 1)) {
\r
1606 // Don't ever sync the last character as it will scroll the screen
\r
1608 Screen[MaxColumn - 1] = 0x00;
\r
1612 while (Column < MaxColumn) {
\r
1613 if (Screen[Column]) {
\r
1614 CurrentAttribute = Attributes[Column];
\r
1615 CurrentColumn = Column;
\r
1616 ScreenStart = &Screen[Column];
\r
1619 // the line end is alway 0x0. So Column should be less than MaxColumn
\r
1620 // It should be still in the same row
\r
1622 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
\r
1624 if (Attributes[Column] != CurrentAttribute) {
\r
1629 *BufferTail = *Str;
\r
1631 if (Attributes[Column] & EFI_WIDE_ATTRIBUTE) {
\r
1639 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
\r
1641 Sto = Private->TextOutList[List].TextOut;
\r
1644 // Skip non GOP/UGA devices
\r
1646 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
\r
1647 Sto->SetAttribute (Sto, CurrentAttribute);
\r
1648 Sto->SetCursorPosition (Sto, CurrentColumn, Row);
\r
1649 Status = Sto->OutputString (Sto, Buffer);
\r
1650 if (EFI_ERROR (Status)) {
\r
1651 ReturnStatus = Status;
\r
1662 // Restore the devices Attributes, Cursor enable state and location
\r
1664 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
\r
1665 Sto = Private->TextOutList[List].TextOut;
\r
1668 // Skip non GOP/UGA devices
\r
1670 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
\r
1671 Sto->SetAttribute (Sto, StartAttribute);
\r
1672 Sto->SetCursorPosition (Sto, StartColumn, StartRow);
\r
1673 Status = Sto->EnableCursor (Sto, StartCursorState);
\r
1674 if (EFI_ERROR (Status)) {
\r
1675 ReturnStatus = Status;
\r
1680 FreePool (Buffer);
\r
1682 return ReturnStatus;
\r