Status should be initialzied to be EFI_SUCCESS.
[edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitterGraphics.c
blobd8b7c403f5f0faf7b883457fa80a4512b8f3f295
1 /** @file
2 Support for ConsoleControl protocol. Support for Graphics output spliter.
3 Support for DevNull Console Out. This console uses memory buffers
4 to represnt the console. It allows a console to start very early and
5 when a new console is added it is synced up with the current console.
7 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 **/
19 #include "ConSplitter.h"
22 CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
25 /**
26 Return the current video mode information. Also returns info about existence
27 of Graphics Output devices or UGA Draw devices in system, and whether the Std
28 In device is locked. GopUgaExists and StdInLocked parameters are optional, and
29 only returned if a non NULL pointer is passed in.
31 @param This Protocol instance pointer.
32 @param Mode Current video mode.
33 @param GopUgaExists TRUE if GOP Spliter has found a GOP/UGA device
34 @param StdInLocked TRUE if StdIn device is keyboard locked
36 @retval EFI_SUCCESS Video mode information is returned.
37 @retval EFI_INVALID_PARAMETER Invalid parameters if Mode == NULL.
39 **/
40 EFI_STATUS
41 EFIAPI
42 ConSpliterConsoleControlGetMode (
43 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
44 OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
45 OUT BOOLEAN *GopUgaExists,
46 OUT BOOLEAN *StdInLocked
49 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
50 UINTN Index;
52 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
54 if (Mode == NULL) {
55 return EFI_INVALID_PARAMETER;
58 *Mode = Private->ConsoleOutputMode;
60 if (GopUgaExists != NULL) {
61 *GopUgaExists = FALSE;
62 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
63 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {
64 *GopUgaExists = TRUE;
65 break;
70 if (StdInLocked != NULL) {
71 *StdInLocked = ConSpliterConssoleControlStdInLocked ();
74 return EFI_SUCCESS;
78 /**
79 Set the current video mode to either text or graphics. Graphics is
80 for Quiet Boot.
82 @param This Console Control Protocol instance pointer.
83 @param Mode Video mode is to be set.
85 @retval EFI_SUCCESS Mode is set successfully.
86 @retval EFI_INVALID_PARAMETER Mode is not the valid mode value.
87 @retval EFI_UNSUPPORTED Mode is unsupported by console device.
89 **/
90 EFI_STATUS
91 EFIAPI
92 ConSpliterConsoleControlSetMode (
93 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
94 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
97 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
98 UINTN Index;
99 TEXT_OUT_AND_GOP_DATA *TextAndGop;
100 BOOLEAN Supported;
102 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
104 if (Mode >= EfiConsoleControlScreenMaxValue) {
105 return EFI_INVALID_PARAMETER;
109 // Judge current mode with wanted mode at first.
111 if (Private->ConsoleOutputMode == Mode) {
112 return EFI_SUCCESS;
115 Supported = FALSE;
116 TextAndGop = &Private->TextOutList[0];
117 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
118 if ((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL)) {
119 Supported = TRUE;
120 break;
124 if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {
125 return EFI_UNSUPPORTED;
128 Private->ConsoleOutputMode = Mode;
130 TextAndGop = &Private->TextOutList[0];
131 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
133 TextAndGop->TextOutEnabled = TRUE;
135 // If we are going into Graphics mode disable ConOut to any UGA device
137 if ((Mode == EfiConsoleControlScreenGraphics) &&((TextAndGop->GraphicsOutput != NULL) || (TextAndGop->UgaDraw != NULL))) {
138 TextAndGop->TextOutEnabled = FALSE;
139 if (FeaturePcdGet (PcdConOutGopSupport)) {
140 DevNullGopSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
141 } else if (FeaturePcdGet (PcdConOutUgaSupport)) {
142 DevNullUgaSync (Private, TextAndGop->GraphicsOutput, TextAndGop->UgaDraw);
146 if (Mode == EfiConsoleControlScreenText) {
147 DevNullSyncStdOut (Private);
149 return EFI_SUCCESS;
154 Returns information for an available graphics mode that the graphics device
155 and the set of active video output devices supports.
157 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
158 @param ModeNumber The mode number to return information on.
159 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
160 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
162 @retval EFI_SUCCESS Mode information returned.
163 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
164 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
165 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
166 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
167 @retval EFI_OUT_OF_RESOURCES No resource available.
170 EFI_STATUS
171 EFIAPI
172 ConSpliterGraphicsOutputQueryMode (
173 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
174 IN UINT32 ModeNumber,
175 OUT UINTN *SizeOfInfo,
176 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
179 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
181 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
182 return EFI_INVALID_PARAMETER;
186 // retrieve private data
188 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
190 if (Private->HardwareNeedsStarting) {
191 return EFI_NOT_STARTED;
194 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
195 if (*Info == NULL) {
196 return EFI_OUT_OF_RESOURCES;
199 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
201 CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);
203 return EFI_SUCCESS;
208 Set the video device into the specified mode and clears the visible portions of
209 the output display to black.
211 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
212 @param ModeNumber Abstraction that defines the current video mode.
214 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
215 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
216 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
217 @retval EFI_OUT_OF_RESOURCES No resource available.
220 EFI_STATUS
221 EFIAPI
222 ConSpliterGraphicsOutputSetMode (
223 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
224 IN UINT32 ModeNumber
227 EFI_STATUS Status;
228 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
229 UINTN Index;
230 EFI_STATUS ReturnStatus;
231 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
232 UINTN Size;
233 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
234 UINTN NumberIndex;
235 UINTN SizeOfInfo;
236 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
237 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
239 if (ModeNumber >= This->Mode->MaxMode) {
240 return EFI_UNSUPPORTED;
243 if (ModeNumber == This->Mode->Mode) {
244 return EFI_SUCCESS;
247 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
249 ReturnStatus = EFI_SUCCESS;
252 // Free the old version
254 if (Private->GraphicsOutputBlt != NULL) {
255 FreePool (Private->GraphicsOutputBlt);
259 // Allocate the virtual Blt buffer
261 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
262 Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
263 Private->GraphicsOutputBlt = AllocateZeroPool (Size);
265 if (Private->GraphicsOutputBlt == NULL) {
266 return EFI_OUT_OF_RESOURCES;
270 // return the worst status met
272 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
273 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
274 if (GraphicsOutput != NULL) {
276 // Find corresponding ModeNumber of this GraphicsOutput instance
278 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
279 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
280 if (EFI_ERROR (Status)) {
281 return Status;
283 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
284 FreePool (Info);
285 break;
287 FreePool (Info);
290 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
291 if (EFI_ERROR (Status)) {
292 ReturnStatus = Status;
294 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
295 UgaDraw = Private->TextOutList[Index].UgaDraw;
296 if (UgaDraw != NULL) {
297 Status = UgaDraw->SetMode (
298 UgaDraw,
299 Mode->HorizontalResolution,
300 Mode->VerticalResolution,
304 if (EFI_ERROR (Status)) {
305 ReturnStatus = Status;
311 This->Mode->Mode = ModeNumber;
313 CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);
316 // Information is not enough here, so the following items remain unchanged:
317 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
318 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
319 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
322 Private->HardwareNeedsStarting = FALSE;
324 return ReturnStatus;
328 The following table defines actions for BltOperations.
330 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
331 directly to every pixel of the video display rectangle
332 (DestinationX, DestinationY)
333 (DestinationX + Width, DestinationY + Height).
334 Only one pixel will be used from the BltBuffer. Delta is NOT used.
335 EfiBltVideoToBltBuffer - Read data from the video display rectangle
336 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
337 the BltBuffer rectangle (DestinationX, DestinationY )
338 (DestinationX + Width, DestinationY + Height). If DestinationX or
339 DestinationY is not zero then Delta must be set to the length in bytes
340 of a row in the BltBuffer.
341 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
342 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
343 video display rectangle (DestinationX, DestinationY)
344 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
345 not zero then Delta must be set to the length in bytes of a row in the
346 BltBuffer.
347 EfiBltVideoToVideo - Copy from the video display rectangle
348 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
349 to the video display rectangle (DestinationX, DestinationY)
350 (DestinationX + Width, DestinationY + Height).
351 The BltBuffer and Delta are not used in this mode.
353 @param Private Protocol instance pointer.
354 @param BltBuffer Buffer containing data to blit into video buffer.
355 This buffer has a size of
356 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
357 @param BltOperation Operation to perform on BlitBuffer and video
358 memory
359 @param SourceX X coordinate of source for the BltBuffer.
360 @param SourceY Y coordinate of source for the BltBuffer.
361 @param DestinationX X coordinate of destination for the BltBuffer.
362 @param DestinationY Y coordinate of destination for the BltBuffer.
363 @param Width Width of rectangle in BltBuffer in pixels.
364 @param Height Hight of rectangle in BltBuffer in pixels.
365 @param Delta OPTIONAL.
367 @retval EFI_SUCCESS The Blt operation completed.
368 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
369 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
370 buffer.
373 EFI_STATUS
374 DevNullGraphicsOutputBlt (
375 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
376 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
377 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
378 IN UINTN SourceX,
379 IN UINTN SourceY,
380 IN UINTN DestinationX,
381 IN UINTN DestinationY,
382 IN UINTN Width,
383 IN UINTN Height,
384 IN UINTN Delta OPTIONAL
387 UINTN SrcY;
388 BOOLEAN Forward;
389 UINTN Index;
390 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
391 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;
392 UINTN HorizontalResolution;
393 UINTN VerticalResolution;
395 if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
396 return EFI_INVALID_PARAMETER;
399 if (Width == 0 || Height == 0) {
400 return EFI_INVALID_PARAMETER;
403 if (Delta == 0) {
404 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
407 HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
408 VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution;
411 // We need to fill the Virtual Screen buffer with the blt data.
413 if (BltOperation == EfiBltVideoToBltBuffer) {
415 // Video to BltBuffer: Source is Video, destination is BltBuffer
417 if ((SourceY + Height) > VerticalResolution) {
418 return EFI_INVALID_PARAMETER;
421 if ((SourceX + Width) > HorizontalResolution) {
422 return EFI_INVALID_PARAMETER;
425 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
426 ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];
427 while (Height > 0) {
428 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
429 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta);
430 ScreenPtr += HorizontalResolution;
431 Height--;
433 } else {
435 // BltBuffer to Video: Source is BltBuffer, destination is Video
437 if (DestinationY + Height > VerticalResolution) {
438 return EFI_INVALID_PARAMETER;
441 if (DestinationX + Width > HorizontalResolution) {
442 return EFI_INVALID_PARAMETER;
445 if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {
447 // Copy backwards, only care the Video to Video Blt
449 ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
450 SrcY = SourceY + Height - 1;
451 Forward = FALSE;
452 } else {
454 // Copy forwards, for other cases
456 ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];
457 SrcY = SourceY;
458 Forward = TRUE;
461 while (Height != 0) {
462 if (BltOperation == EfiBltVideoFill) {
463 for (Index = 0; Index < Width; Index++) {
464 ScreenPtr[Index] = *BltBuffer;
466 } else {
467 if (BltOperation == EfiBltBufferToVideo) {
468 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
469 } else {
470 BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];
473 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
476 if (Forward) {
477 ScreenPtr += HorizontalResolution;
478 SrcY ++;
479 } else {
480 ScreenPtr -= HorizontalResolution;
481 SrcY --;
483 Height--;
487 return EFI_SUCCESS;
492 The following table defines actions for BltOperations.
494 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
495 directly to every pixel of the video display rectangle
496 (DestinationX, DestinationY)
497 (DestinationX + Width, DestinationY + Height).
498 Only one pixel will be used from the BltBuffer. Delta is NOT used.
499 EfiBltVideoToBltBuffer - Read data from the video display rectangle
500 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
501 the BltBuffer rectangle (DestinationX, DestinationY )
502 (DestinationX + Width, DestinationY + Height). If DestinationX or
503 DestinationY is not zero then Delta must be set to the length in bytes
504 of a row in the BltBuffer.
505 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
506 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
507 video display rectangle (DestinationX, DestinationY)
508 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
509 not zero then Delta must be set to the length in bytes of a row in the
510 BltBuffer.
511 EfiBltVideoToVideo - Copy from the video display rectangle
512 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
513 to the video display rectangle (DestinationX, DestinationY)
514 (DestinationX + Width, DestinationY + Height).
515 The BltBuffer and Delta are not used in this mode.
517 @param This Protocol instance pointer.
518 @param BltBuffer Buffer containing data to blit into video buffer.
519 This buffer has a size of
520 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
521 @param BltOperation Operation to perform on BlitBuffer and video
522 memory
523 @param SourceX X coordinate of source for the BltBuffer.
524 @param SourceY Y coordinate of source for the BltBuffer.
525 @param DestinationX X coordinate of destination for the BltBuffer.
526 @param DestinationY Y coordinate of destination for the BltBuffer.
527 @param Width Width of rectangle in BltBuffer in pixels.
528 @param Height Hight of rectangle in BltBuffer in pixels.
529 @param Delta OPTIONAL.
531 @retval EFI_SUCCESS The Blt operation completed.
532 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
533 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
534 buffer.
537 EFI_STATUS
538 EFIAPI
539 ConSpliterGraphicsOutputBlt (
540 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
541 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
542 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
543 IN UINTN SourceX,
544 IN UINTN SourceY,
545 IN UINTN DestinationX,
546 IN UINTN DestinationY,
547 IN UINTN Width,
548 IN UINTN Height,
549 IN UINTN Delta OPTIONAL
552 EFI_STATUS Status;
553 EFI_STATUS ReturnStatus;
554 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
555 UINTN Index;
556 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
557 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
559 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
561 ReturnStatus = EFI_SUCCESS;
563 // return the worst status met
565 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
566 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
567 if (GraphicsOutput != NULL) {
568 Status = GraphicsOutput->Blt (
569 GraphicsOutput,
570 BltBuffer,
571 BltOperation,
572 SourceX,
573 SourceY,
574 DestinationX,
575 DestinationY,
576 Width,
577 Height,
578 Delta
580 if (EFI_ERROR (Status)) {
581 ReturnStatus = Status;
582 } else if (BltOperation == EfiBltVideoToBltBuffer) {
584 // Only need to read the data into buffer one time
586 return EFI_SUCCESS;
590 UgaDraw = Private->TextOutList[Index].UgaDraw;
591 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
592 Status = UgaDraw->Blt (
593 UgaDraw,
594 (EFI_UGA_PIXEL *) BltBuffer,
595 (EFI_UGA_BLT_OPERATION) BltOperation,
596 SourceX,
597 SourceY,
598 DestinationX,
599 DestinationY,
600 Width,
601 Height,
602 Delta
604 if (EFI_ERROR (Status)) {
605 ReturnStatus = Status;
606 } else if (BltOperation == EfiBltVideoToBltBuffer) {
608 // Only need to read the data into buffer one time
610 return EFI_SUCCESS;
615 return ReturnStatus;
619 Write data from the buffer to video display based on Graphics Output setting.
621 @param Private Consplitter Text Out pointer.
622 @param GraphicsOutput Graphics Output protocol pointer.
623 @param UgaDraw UGA Draw protocol pointer.
625 @retval EFI_UNSUPPORTED No graphics devcie available .
626 @retval EFI_SUCCESS The Blt operation completed.
627 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
628 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
632 EFI_STATUS
633 DevNullGopSync (
634 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
635 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
636 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
639 if (GraphicsOutput != NULL) {
640 return GraphicsOutput->Blt (
641 GraphicsOutput,
642 Private->GraphicsOutputBlt,
643 EfiBltBufferToVideo,
648 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
649 Private->GraphicsOutput.Mode->Info->VerticalResolution,
652 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
653 return UgaDraw->Blt (
654 UgaDraw,
655 (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,
656 EfiUgaBltBufferToVideo,
661 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
662 Private->GraphicsOutput.Mode->Info->VerticalResolution,
665 } else {
666 return EFI_UNSUPPORTED;
671 Return the current video mode information.
673 @param This The EFI_UGA_DRAW_PROTOCOL instance.
674 @param HorizontalResolution The size of video screen in pixels in the X dimension.
675 @param VerticalResolution The size of video screen in pixels in the Y dimension.
676 @param ColorDepth Number of bits per pixel, currently defined to be 32.
677 @param RefreshRate The refresh rate of the monitor in Hertz.
679 @retval EFI_SUCCESS Mode information returned.
680 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
681 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
684 EFI_STATUS
685 EFIAPI
686 ConSpliterUgaDrawGetMode (
687 IN EFI_UGA_DRAW_PROTOCOL *This,
688 OUT UINT32 *HorizontalResolution,
689 OUT UINT32 *VerticalResolution,
690 OUT UINT32 *ColorDepth,
691 OUT UINT32 *RefreshRate
694 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
696 if ((HorizontalResolution == NULL) ||
697 (VerticalResolution == NULL) ||
698 (RefreshRate == NULL) ||
699 (ColorDepth == NULL)) {
700 return EFI_INVALID_PARAMETER;
703 // retrieve private data
705 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
707 *HorizontalResolution = Private->UgaHorizontalResolution;
708 *VerticalResolution = Private->UgaVerticalResolution;
709 *ColorDepth = Private->UgaColorDepth;
710 *RefreshRate = Private->UgaRefreshRate;
712 return EFI_SUCCESS;
717 Set the current video mode information.
719 @param This The EFI_UGA_DRAW_PROTOCOL instance.
720 @param HorizontalResolution The size of video screen in pixels in the X dimension.
721 @param VerticalResolution The size of video screen in pixels in the Y dimension.
722 @param ColorDepth Number of bits per pixel, currently defined to be 32.
723 @param RefreshRate The refresh rate of the monitor in Hertz.
725 @retval EFI_SUCCESS Mode information returned.
726 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
727 @retval EFI_OUT_OF_RESOURCES Out of resources.
730 EFI_STATUS
731 EFIAPI
732 ConSpliterUgaDrawSetMode (
733 IN EFI_UGA_DRAW_PROTOCOL *This,
734 IN UINT32 HorizontalResolution,
735 IN UINT32 VerticalResolution,
736 IN UINT32 ColorDepth,
737 IN UINT32 RefreshRate
740 EFI_STATUS Status;
741 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
742 UINTN Index;
743 EFI_STATUS ReturnStatus;
744 UINTN Size;
745 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
746 UINTN NumberIndex;
747 UINTN SizeOfInfo;
748 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
749 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
751 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
754 // UgaDevNullSetMode ()
756 ReturnStatus = EFI_SUCCESS;
759 // Free the old version
761 if (Private->UgaBlt != NULL) {
762 FreePool (Private->UgaBlt);
766 // Allocate the virtual Blt buffer
768 Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);
769 Private->UgaBlt = AllocateZeroPool (Size);
770 if (Private->UgaBlt == NULL) {
771 return EFI_OUT_OF_RESOURCES;
775 // Update the Mode data
777 Private->UgaHorizontalResolution = HorizontalResolution;
778 Private->UgaVerticalResolution = VerticalResolution;
779 Private->UgaColorDepth = ColorDepth;
780 Private->UgaRefreshRate = RefreshRate;
782 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
783 return ReturnStatus;
786 // return the worst status met
788 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
790 ReturnStatus = EFI_UNSUPPORTED;
792 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
793 if (GraphicsOutput != NULL) {
795 // Find corresponding ModeNumber of this GraphicsOutput instance
797 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
798 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
799 if (EFI_ERROR (Status)) {
800 return Status;
802 if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
803 FreePool (Info);
804 break;
806 FreePool (Info);
809 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
810 if (EFI_ERROR (Status)) {
811 ReturnStatus = Status;
813 } else if (FeaturePcdGet (PcdUgaConsumeSupport)){
814 UgaDraw = Private->TextOutList[Index].UgaDraw;
815 if (UgaDraw != NULL) {
816 Status = UgaDraw->SetMode (
817 UgaDraw,
818 HorizontalResolution,
819 VerticalResolution,
820 ColorDepth,
821 RefreshRate
823 if (EFI_ERROR (Status)) {
824 ReturnStatus = Status;
830 return ReturnStatus;
834 Blt a rectangle of pixels on the graphics screen.
836 The following table defines actions for BltOperations.
838 EfiUgaVideoFill:
839 Write data from the BltBuffer pixel (SourceX, SourceY)
840 directly to every pixel of the video display rectangle
841 (DestinationX, DestinationY)
842 (DestinationX + Width, DestinationY + Height).
843 Only one pixel will be used from the BltBuffer. Delta is NOT used.
844 EfiUgaVideoToBltBuffer:
845 Read data from the video display rectangle
846 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
847 the BltBuffer rectangle (DestinationX, DestinationY )
848 (DestinationX + Width, DestinationY + Height). If DestinationX or
849 DestinationY is not zero then Delta must be set to the length in bytes
850 of a row in the BltBuffer.
851 EfiUgaBltBufferToVideo:
852 Write data from the BltBuffer rectangle
853 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
854 video display rectangle (DestinationX, DestinationY)
855 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
856 not zero then Delta must be set to the length in bytes of a row in the
857 BltBuffer.
858 EfiUgaVideoToVideo:
859 Copy from the video display rectangle
860 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
861 to the video display rectangle (DestinationX, DestinationY)
862 (DestinationX + Width, DestinationY + Height).
863 The BltBuffer and Delta are not used in this mode.
865 @param Private Text Out Splitter pointer.
866 @param BltBuffer Buffer containing data to blit into video buffer.
867 This buffer has a size of
868 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
869 @param BltOperation Operation to perform on BlitBuffer and video
870 memory
871 @param SourceX X coordinate of source for the BltBuffer.
872 @param SourceY Y coordinate of source for the BltBuffer.
873 @param DestinationX X coordinate of destination for the BltBuffer.
874 @param DestinationY Y coordinate of destination for the BltBuffer.
875 @param Width Width of rectangle in BltBuffer in pixels.
876 @param Height Hight of rectangle in BltBuffer in pixels.
877 @param Delta OPTIONAL.
879 @retval EFI_SUCCESS The Blt operation completed.
880 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
881 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
882 buffer.
885 EFI_STATUS
886 DevNullUgaBlt (
887 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
888 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
889 IN EFI_UGA_BLT_OPERATION BltOperation,
890 IN UINTN SourceX,
891 IN UINTN SourceY,
892 IN UINTN DestinationX,
893 IN UINTN DestinationY,
894 IN UINTN Width,
895 IN UINTN Height,
896 IN UINTN Delta OPTIONAL
899 UINTN SrcY;
900 BOOLEAN Forward;
901 UINTN Index;
902 EFI_UGA_PIXEL *BltPtr;
903 EFI_UGA_PIXEL *ScreenPtr;
904 UINT32 HorizontalResolution;
905 UINT32 VerticalResolution;
907 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
908 return EFI_INVALID_PARAMETER;
911 if (Width == 0 || Height == 0) {
912 return EFI_INVALID_PARAMETER;
915 if (Delta == 0) {
916 Delta = Width * sizeof (EFI_UGA_PIXEL);
919 HorizontalResolution = Private->UgaHorizontalResolution;
920 VerticalResolution = Private->UgaVerticalResolution;
923 // We need to fill the Virtual Screen buffer with the blt data.
925 if (BltOperation == EfiUgaVideoToBltBuffer) {
927 // Video to BltBuffer: Source is Video, destination is BltBuffer
929 if ((SourceY + Height) > VerticalResolution) {
930 return EFI_INVALID_PARAMETER;
933 if ((SourceX + Width) > HorizontalResolution) {
934 return EFI_INVALID_PARAMETER;
937 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));
938 ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];
939 while (Height > 0) {
940 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));
941 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);
942 ScreenPtr += HorizontalResolution;
943 Height--;
945 } else {
947 // BltBuffer to Video: Source is BltBuffer, destination is Video
949 if (DestinationY + Height > VerticalResolution) {
950 return EFI_INVALID_PARAMETER;
953 if (DestinationX + Width > HorizontalResolution) {
954 return EFI_INVALID_PARAMETER;
957 if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {
959 // Copy backwards, only care the Video to Video Blt
961 ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
962 SrcY = SourceY + Height - 1;
963 Forward = FALSE;
964 } else {
966 // Copy forwards, for other cases
968 ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
969 SrcY = SourceY;
970 Forward = TRUE;
973 while (Height != 0) {
974 if (BltOperation == EfiUgaVideoFill) {
975 for (Index = 0; Index < Width; Index++) {
976 ScreenPtr[Index] = *BltBuffer;
978 } else {
979 if (BltOperation == EfiUgaBltBufferToVideo) {
980 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));
981 } else {
982 BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];
985 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));
988 if (Forward) {
989 ScreenPtr += HorizontalResolution;
990 SrcY ++;
991 } else {
992 ScreenPtr -= HorizontalResolution;
993 SrcY --;
995 Height--;
999 return EFI_SUCCESS;
1003 Blt a rectangle of pixels on the graphics screen.
1005 The following table defines actions for BltOperations.
1007 EfiUgaVideoFill:
1008 Write data from the BltBuffer pixel (SourceX, SourceY)
1009 directly to every pixel of the video display rectangle
1010 (DestinationX, DestinationY)
1011 (DestinationX + Width, DestinationY + Height).
1012 Only one pixel will be used from the BltBuffer. Delta is NOT used.
1013 EfiUgaVideoToBltBuffer:
1014 Read data from the video display rectangle
1015 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
1016 the BltBuffer rectangle (DestinationX, DestinationY )
1017 (DestinationX + Width, DestinationY + Height). If DestinationX or
1018 DestinationY is not zero then Delta must be set to the length in bytes
1019 of a row in the BltBuffer.
1020 EfiUgaBltBufferToVideo:
1021 Write data from the BltBuffer rectangle
1022 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
1023 video display rectangle (DestinationX, DestinationY)
1024 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
1025 not zero then Delta must be set to the length in bytes of a row in the
1026 BltBuffer.
1027 EfiUgaVideoToVideo:
1028 Copy from the video display rectangle
1029 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
1030 to the video display rectangle (DestinationX, DestinationY)
1031 (DestinationX + Width, DestinationY + Height).
1032 The BltBuffer and Delta are not used in this mode.
1034 @param This Protocol instance pointer.
1035 @param BltBuffer Buffer containing data to blit into video buffer. This
1036 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
1037 @param BltOperation Operation to perform on BlitBuffer and video memory
1038 @param SourceX X coordinate of source for the BltBuffer.
1039 @param SourceY Y coordinate of source for the BltBuffer.
1040 @param DestinationX X coordinate of destination for the BltBuffer.
1041 @param DestinationY Y coordinate of destination for the BltBuffer.
1042 @param Width Width of rectangle in BltBuffer in pixels.
1043 @param Height Hight of rectangle in BltBuffer in pixels.
1044 @param Delta OPTIONAL
1046 @retval EFI_SUCCESS The Blt operation completed.
1047 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
1048 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
1051 EFI_STATUS
1052 EFIAPI
1053 ConSpliterUgaDrawBlt (
1054 IN EFI_UGA_DRAW_PROTOCOL *This,
1055 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
1056 IN EFI_UGA_BLT_OPERATION BltOperation,
1057 IN UINTN SourceX,
1058 IN UINTN SourceY,
1059 IN UINTN DestinationX,
1060 IN UINTN DestinationY,
1061 IN UINTN Width,
1062 IN UINTN Height,
1063 IN UINTN Delta OPTIONAL
1066 EFI_STATUS Status;
1067 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
1068 UINTN Index;
1069 EFI_STATUS ReturnStatus;
1070 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1072 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
1075 // Sync up DevNull UGA device
1077 ReturnStatus = DevNullUgaBlt (
1078 Private,
1079 BltBuffer,
1080 BltOperation,
1081 SourceX,
1082 SourceY,
1083 DestinationX,
1084 DestinationY,
1085 Width,
1086 Height,
1087 Delta
1089 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
1090 return ReturnStatus;
1093 // return the worst status met
1095 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
1096 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
1097 if (GraphicsOutput != NULL) {
1098 Status = GraphicsOutput->Blt (
1099 GraphicsOutput,
1100 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,
1101 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,
1102 SourceX,
1103 SourceY,
1104 DestinationX,
1105 DestinationY,
1106 Width,
1107 Height,
1108 Delta
1110 if (EFI_ERROR (Status)) {
1111 ReturnStatus = Status;
1112 } else if (BltOperation == EfiBltVideoToBltBuffer) {
1114 // Only need to read the data into buffer one time
1116 return EFI_SUCCESS;
1120 if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1121 Status = Private->TextOutList[Index].UgaDraw->Blt (
1122 Private->TextOutList[Index].UgaDraw,
1123 BltBuffer,
1124 BltOperation,
1125 SourceX,
1126 SourceY,
1127 DestinationX,
1128 DestinationY,
1129 Width,
1130 Height,
1131 Delta
1133 if (EFI_ERROR (Status)) {
1134 ReturnStatus = Status;
1135 } else if (BltOperation == EfiUgaVideoToBltBuffer) {
1137 // Only need to read the data into buffer one time
1139 return EFI_SUCCESS;
1144 return ReturnStatus;
1148 Write data from the buffer to video display based on UGA Draw setting.
1150 @param Private Consplitter Text Out pointer.
1151 @param GraphicsOutput Graphics Output protocol pointer.
1152 @param UgaDraw UGA Draw protocol pointer.
1154 @retval EFI_UNSUPPORTED No graphics devcie available .
1155 @retval EFI_SUCCESS The Blt operation completed.
1156 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
1157 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
1160 EFI_STATUS
1161 DevNullUgaSync (
1162 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1163 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
1164 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
1167 if (GraphicsOutput != NULL) {
1168 return GraphicsOutput->Blt (
1169 GraphicsOutput,
1170 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,
1171 EfiBltBufferToVideo,
1176 Private->UgaHorizontalResolution,
1177 Private->UgaVerticalResolution,
1180 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1181 return UgaDraw->Blt (
1182 UgaDraw,
1183 Private->UgaBlt,
1184 EfiUgaBltBufferToVideo,
1189 Private->UgaHorizontalResolution,
1190 Private->UgaVerticalResolution,
1191 Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
1193 } else {
1194 return EFI_UNSUPPORTED;
1200 Write a Unicode string to the output device.
1202 @param Private Pointer to the console output splitter's private
1203 data. It indicates the calling context.
1204 @param WString The NULL-terminated Unicode string to be
1205 displayed on the output device(s). All output
1206 devices must also support the Unicode drawing
1207 defined in this file.
1209 @retval EFI_SUCCESS The string was output to the device.
1210 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
1211 output the text.
1212 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
1213 defined text mode.
1214 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
1215 characters in the Unicode string could not be
1216 rendered and were skipped.
1219 EFI_STATUS
1220 DevNullTextOutOutputString (
1221 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1222 IN CHAR16 *WString
1225 UINTN SizeScreen;
1226 UINTN SizeAttribute;
1227 UINTN Index;
1228 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
1229 CHAR16 *Screen;
1230 CHAR16 *NullScreen;
1231 CHAR16 InsertChar;
1232 CHAR16 TempChar;
1233 CHAR16 *PStr;
1234 INT32 *Attribute;
1235 INT32 *NullAttributes;
1236 INT32 CurrentWidth;
1237 UINTN LastRow;
1238 UINTN MaxColumn;
1240 Mode = &Private->TextOutMode;
1241 NullScreen = Private->DevNullScreen;
1242 NullAttributes = Private->DevNullAttributes;
1243 LastRow = Private->DevNullRows - 1;
1244 MaxColumn = Private->DevNullColumns;
1246 if ((Mode->Attribute & EFI_WIDE_ATTRIBUTE) != 0) {
1247 CurrentWidth = 2;
1248 } else {
1249 CurrentWidth = 1;
1252 while (*WString != L'\0') {
1254 if (*WString == CHAR_BACKSPACE) {
1256 // If the cursor is at the left edge of the display, then move the cursor
1257 // one row up.
1259 if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) {
1260 Mode->CursorRow--;
1261 Mode->CursorColumn = (INT32) MaxColumn;
1265 // If the cursor is not at the left edge of the display,
1266 // then move the cursor left one column.
1268 if (Mode->CursorColumn > 0) {
1269 Mode->CursorColumn--;
1270 if (Mode->CursorColumn > 0 &&
1271 NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE
1273 Mode->CursorColumn--;
1276 // Insert an extra backspace
1278 InsertChar = CHAR_BACKSPACE;
1279 PStr = WString + 1;
1280 while (*PStr != L'\0') {
1281 TempChar = *PStr;
1282 *PStr = InsertChar;
1283 InsertChar = TempChar;
1284 PStr++;
1287 *PStr = InsertChar;
1288 *(++PStr) = 0;
1290 WString++;
1294 WString++;
1296 } else if (*WString == CHAR_LINEFEED) {
1298 // If the cursor is at the bottom of the display,
1299 // then scroll the display one row, and do not update
1300 // the cursor position. Otherwise, move the cursor down one row.
1302 if (Mode->CursorRow == (INT32) (LastRow)) {
1304 // Scroll Screen Up One Row
1306 SizeAttribute = LastRow * MaxColumn;
1307 CopyMem (
1308 NullAttributes,
1309 NullAttributes + MaxColumn,
1310 SizeAttribute * sizeof (INT32)
1314 // Each row has an ending CHAR_NULL. So one more character each line
1315 // for DevNullScreen than DevNullAttributes
1317 SizeScreen = SizeAttribute + LastRow;
1318 CopyMem (
1319 NullScreen,
1320 NullScreen + (MaxColumn + 1),
1321 SizeScreen * sizeof (CHAR16)
1325 // Print Blank Line at last line
1327 Screen = NullScreen + SizeScreen;
1328 Attribute = NullAttributes + SizeAttribute;
1330 for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) {
1331 *Screen = L' ';
1332 *Attribute = Mode->Attribute;
1334 } else {
1335 Mode->CursorRow++;
1338 WString++;
1339 } else if (*WString == CHAR_CARRIAGE_RETURN) {
1341 // Move the cursor to the beginning of the current row.
1343 Mode->CursorColumn = 0;
1344 WString++;
1345 } else {
1347 // Print the character at the current cursor position and
1348 // move the cursor right one column. If this moves the cursor
1349 // past the right edge of the display, then the line should wrap to
1350 // the beginning of the next line. This is equivalent to inserting
1351 // a CR and an LF. Note that if the cursor is at the bottom of the
1352 // display, and the line wraps, then the display will be scrolled
1353 // one line.
1355 Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn;
1357 while (Mode->CursorColumn < (INT32) MaxColumn) {
1358 if (*WString == CHAR_NULL) {
1359 break;
1362 if (*WString == CHAR_BACKSPACE) {
1363 break;
1366 if (*WString == CHAR_LINEFEED) {
1367 break;
1370 if (*WString == CHAR_CARRIAGE_RETURN) {
1371 break;
1374 if (*WString == UNICODE_WIDE_CHAR || *WString == UNICODE_NARROW_CHAR) {
1375 CurrentWidth = (*WString == UNICODE_WIDE_CHAR) ? 2 : 1;
1376 WString++;
1377 continue;
1380 if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) {
1382 // If a wide char is at the rightmost column, then move the char
1383 // to the beginning of the next row
1385 NullScreen[Index + Mode->CursorRow] = L' ';
1386 NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE;
1387 Index++;
1388 Mode->CursorColumn++;
1389 } else {
1390 NullScreen[Index + Mode->CursorRow] = *WString;
1391 NullAttributes[Index] = Mode->Attribute;
1392 if (CurrentWidth == 1) {
1393 NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1394 } else {
1395 NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE;
1396 NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1399 Index += CurrentWidth;
1400 WString++;
1401 Mode->CursorColumn += CurrentWidth;
1405 // At the end of line, output carriage return and line feed
1407 if (Mode->CursorColumn >= (INT32) MaxColumn) {
1408 DevNullTextOutOutputString (Private, mCrLfString);
1413 return EFI_SUCCESS;
1418 Sets the output device(s) to a specified mode.
1420 @param Private Text Out Splitter pointer.
1421 @param ModeNumber The mode number to set.
1423 @retval EFI_SUCCESS The requested text mode was set.
1424 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1425 the request.
1426 @retval EFI_UNSUPPORTED The mode number was not valid.
1427 @retval EFI_OUT_OF_RESOURCES Out of resources.
1430 EFI_STATUS
1431 DevNullTextOutSetMode (
1432 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1433 IN UINTN ModeNumber
1436 UINTN Size;
1437 INT32 CurrentMode;
1438 UINTN Row;
1439 UINTN Column;
1440 TEXT_OUT_SPLITTER_QUERY_DATA *Mode;
1443 // No extra check for ModeNumber here, as it has been checked in
1444 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1445 // Row and Column should be fetched from intersection map.
1447 if (Private->TextOutModeMap != NULL) {
1448 CurrentMode = *(Private->TextOutModeMap + Private->TextOutListCount * ModeNumber);
1449 } else {
1450 CurrentMode = (INT32) (ModeNumber);
1452 Mode = &(Private->TextOutQueryData[CurrentMode]);
1453 Row = Mode->Rows;
1454 Column = Mode->Columns;
1456 if (Row == 0 || Column == 0) {
1457 return EFI_UNSUPPORTED;
1460 if (Private->TextOutMode.Mode != (INT32) ModeNumber) {
1462 Private->TextOutMode.Mode = (INT32) ModeNumber;
1463 Private->DevNullColumns = Column;
1464 Private->DevNullRows = Row;
1466 if (Private->DevNullScreen != NULL) {
1467 FreePool (Private->DevNullScreen);
1470 Size = (Row * (Column + 1)) * sizeof (CHAR16);
1471 Private->DevNullScreen = AllocateZeroPool (Size);
1472 if (Private->DevNullScreen == NULL) {
1473 return EFI_OUT_OF_RESOURCES;
1476 if (Private->DevNullAttributes != NULL) {
1477 FreePool (Private->DevNullAttributes);
1480 Size = Row * Column * sizeof (INT32);
1481 Private->DevNullAttributes = AllocateZeroPool (Size);
1482 if (Private->DevNullAttributes == NULL) {
1483 return EFI_OUT_OF_RESOURCES;
1487 DevNullTextOutClearScreen (Private);
1489 return EFI_SUCCESS;
1494 Clears the output device(s) display to the currently selected background
1495 color.
1497 @param Private Text Out Splitter pointer.
1499 @retval EFI_SUCCESS The operation completed successfully.
1500 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1501 the request.
1502 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1505 EFI_STATUS
1506 DevNullTextOutClearScreen (
1507 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1510 UINTN Row;
1511 UINTN Column;
1512 CHAR16 *Screen;
1513 INT32 *Attributes;
1514 INT32 CurrentAttribute;
1517 // Clear the DevNull Text Out Buffers.
1518 // The screen is filled with spaces.
1519 // The attributes are all synced with the current Simple Text Out Attribute
1521 Screen = Private->DevNullScreen;
1522 Attributes = Private->DevNullAttributes;
1523 CurrentAttribute = Private->TextOutMode.Attribute;
1525 for (Row = 0; Row < Private->DevNullRows; Row++) {
1526 for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {
1527 *Screen = L' ';
1528 *Attributes = CurrentAttribute;
1531 // Each line of the screen has a NULL on the end so we must skip over it
1533 Screen++;
1536 DevNullTextOutSetCursorPosition (Private, 0, 0);
1538 return DevNullTextOutEnableCursor (Private, TRUE);
1543 Sets the current coordinates of the cursor position on NULL device.
1545 @param Private Text Out Splitter pointer.
1546 @param Column The column position to set the cursor to. Must be
1547 greater than or equal to zero and less than the
1548 number of columns by QueryMode ().
1549 @param Row The row position to set the cursor to. Must be
1550 greater than or equal to zero and less than the
1551 number of rows by QueryMode ().
1553 @retval EFI_SUCCESS Always returned.
1556 EFI_STATUS
1557 DevNullTextOutSetCursorPosition (
1558 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1559 IN UINTN Column,
1560 IN UINTN Row
1564 // No need to do extra check here as whether (Column, Row) is valid has
1565 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1566 // always be supported.
1568 Private->TextOutMode.CursorColumn = (INT32) Column;
1569 Private->TextOutMode.CursorRow = (INT32) Row;
1571 return EFI_SUCCESS;
1576 Set cursor visibility property on NULL device.
1578 @param Private Text Out Splitter pointer.
1579 @param Visible If TRUE, the cursor is set to be visible, If
1580 FALSE, the cursor is set to be invisible.
1582 @retval EFI_SUCCESS Always returned.
1585 EFI_STATUS
1586 DevNullTextOutEnableCursor (
1587 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1588 IN BOOLEAN Visible
1591 Private->TextOutMode.CursorVisible = Visible;
1593 return EFI_SUCCESS;
1598 Take the DevNull TextOut device and update the Simple Text Out on every
1599 UGA device.
1601 @param Private Text Out Splitter pointer.
1603 @retval EFI_SUCCESS The request is valid.
1604 @retval other Return status of TextOut->OutputString ()
1607 EFI_STATUS
1608 DevNullSyncStdOut (
1609 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1612 EFI_STATUS Status;
1613 EFI_STATUS ReturnStatus;
1614 UINTN Row;
1615 UINTN Column;
1616 UINTN List;
1617 UINTN MaxColumn;
1618 UINTN CurrentColumn;
1619 UINTN StartRow;
1620 UINTN StartColumn;
1621 INT32 StartAttribute;
1622 BOOLEAN StartCursorState;
1623 CHAR16 *Screen;
1624 CHAR16 *Str;
1625 CHAR16 *Buffer;
1626 CHAR16 *BufferTail;
1627 CHAR16 *ScreenStart;
1628 INT32 CurrentAttribute;
1629 INT32 *Attributes;
1630 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
1633 // Save the devices Attributes, Cursor enable state and location
1635 StartColumn = Private->TextOutMode.CursorColumn;
1636 StartRow = Private->TextOutMode.CursorRow;
1637 StartAttribute = Private->TextOutMode.Attribute;
1638 StartCursorState = Private->TextOutMode.CursorVisible;
1640 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1642 Sto = Private->TextOutList[List].TextOut;
1645 // Skip non GOP/UGA devices
1647 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1648 Sto->EnableCursor (Sto, FALSE);
1649 Sto->ClearScreen (Sto);
1653 ReturnStatus = EFI_SUCCESS;
1654 Screen = Private->DevNullScreen;
1655 Attributes = Private->DevNullAttributes;
1656 MaxColumn = Private->DevNullColumns;
1658 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
1659 if (Buffer == NULL) {
1660 return ReturnStatus;
1663 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
1665 if (Row == (Private->DevNullRows - 1)) {
1667 // Don't ever sync the last character as it will scroll the screen
1669 Screen[MaxColumn - 1] = 0x00;
1672 Column = 0;
1673 while (Column < MaxColumn) {
1674 if (Screen[Column] > 0) {
1675 CurrentAttribute = Attributes[Column];
1676 CurrentColumn = Column;
1677 ScreenStart = &Screen[Column];
1680 // the line end is alway 0x0. So Column should be less than MaxColumn
1681 // It should be still in the same row
1683 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
1685 if (Attributes[Column] != CurrentAttribute) {
1686 Column--;
1687 break;
1690 *BufferTail = *Str;
1691 BufferTail++;
1692 if ((Attributes[Column] & EFI_WIDE_ATTRIBUTE) != 0) {
1693 Str++;
1694 Column++;
1698 *BufferTail = 0;
1700 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1702 Sto = Private->TextOutList[List].TextOut;
1705 // Skip non GOP/UGA devices
1707 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1708 Sto->SetAttribute (Sto, CurrentAttribute);
1709 Sto->SetCursorPosition (Sto, CurrentColumn, Row);
1710 Status = Sto->OutputString (Sto, Buffer);
1711 if (EFI_ERROR (Status)) {
1712 ReturnStatus = Status;
1719 Column++;
1723 // Restore the devices Attributes, Cursor enable state and location
1725 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1726 Sto = Private->TextOutList[List].TextOut;
1729 // Skip non GOP/UGA devices
1731 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1732 Sto->SetAttribute (Sto, StartAttribute);
1733 Sto->SetCursorPosition (Sto, StartColumn, StartRow);
1734 Status = Sto->EnableCursor (Sto, StartCursorState);
1735 if (EFI_ERROR (Status)) {
1736 ReturnStatus = Status;
1741 FreePool (Buffer);
1743 return ReturnStatus;