]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
add functions header for ConSplitterDxe module.
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConSplitterDxe / ConSplitterGraphics.c
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.
6
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
12
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.
15
16
17 **/
18
19
20 #include "ConSplitter.h"
21
22
23 STATIC CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
24
25
26 /**
27 Return the current video mode information. Also returns info about existence
28 of Graphics Output devices or UGA Draw devices in system, and if the Std In device is locked. All the
29 arguments are optional and only returned if a non NULL pointer is passed in.
30
31 @param This Protocol instance pointer.
32 @param Mode Are we in text of grahics mode.
33 @param GopExists TRUE if GOP Spliter has found a GOP/UGA device
34 @param StdInLocked TRUE if StdIn device is keyboard locked
35
36 @retval EFI_SUCCESS Mode information returned.
37 @retval EFI_INVALID_PARAMETER Invalid parameters.
38
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 *GopExists,
46 OUT BOOLEAN *StdInLocked
47 )
48 {
49 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
50 UINTN Index;
51
52 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
53
54 if (Mode == NULL) {
55 return EFI_INVALID_PARAMETER;
56 }
57
58 *Mode = Private->ConsoleOutputMode;
59
60 if (GopExists != NULL) {
61 *GopExists = FALSE;
62 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
63 if ((Private->TextOutList[Index].GraphicsOutput != NULL) || (Private->TextOutList[Index].UgaDraw != NULL)) {
64 *GopExists = TRUE;
65 break;
66 }
67 }
68 }
69
70 if (StdInLocked != NULL) {
71 *StdInLocked = ConSpliterConssoleControlStdInLocked ();
72 }
73
74 return EFI_SUCCESS;
75 }
76
77
78 /**
79 Set the current mode to either text or graphics. Graphics is
80 for Quiet Boot.
81
82 @param This Protocol instance pointer.
83 @param Mode Mode to set the
84
85 @retval EFI_SUCCESS Mode information returned.
86 @retval EFI_INVALID_PARAMETER Invalid parameter.
87 @retval EFI_UNSUPPORTED Operation unsupported.
88
89 **/
90 EFI_STATUS
91 EFIAPI
92 ConSpliterConsoleControlSetMode (
93 IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
94 IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
95 )
96 {
97 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
98 UINTN Index;
99 TEXT_OUT_AND_GOP_DATA *TextAndGop;
100 BOOLEAN Supported;
101
102 Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
103
104 if (Mode >= EfiConsoleControlScreenMaxValue) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 //
109 // Judge current mode with wanted mode at first.
110 //
111 if (Private->ConsoleOutputMode == Mode) {
112 return EFI_SUCCESS;
113 }
114
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;
121 }
122 }
123
124 if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) {
125 return EFI_UNSUPPORTED;
126 }
127
128 Private->ConsoleOutputMode = Mode;
129
130 TextAndGop = &Private->TextOutList[0];
131 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndGop++) {
132
133 TextAndGop->TextOutEnabled = TRUE;
134 //
135 // If we are going into Graphics mode disable ConOut to any UGA device
136 //
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);
143 }
144 }
145 }
146 if (Mode == EfiConsoleControlScreenText) {
147 DevNullSyncStdOut (Private);
148 }
149 return EFI_SUCCESS;
150 }
151
152
153 /**
154 Return the current video mode information.
155
156 @param This Protocol instance pointer.
157 @param ModeNumber The mode number to return information on.
158 @param SizeOfInfo A pointer to the size, in bytes, of the Info
159 buffer.
160 @param Info Caller allocated buffer that returns information
161 about ModeNumber.
162
163 @retval EFI_SUCCESS Mode information returned.
164 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
165 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
166 video mode.
167 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
168 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
169
170 **/
171 EFI_STATUS
172 EFIAPI
173 ConSpliterGraphicsOutputQueryMode (
174 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
175 IN UINT32 ModeNumber,
176 OUT UINTN *SizeOfInfo,
177 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
178 )
179 {
180 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
181
182 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
183 return EFI_INVALID_PARAMETER;
184 }
185
186 //
187 // retrieve private data
188 //
189 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
190
191 if (Private->HardwareNeedsStarting) {
192 return EFI_NOT_STARTED;
193 }
194
195 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
196
197 if (*Info == NULL) {
198 return EFI_OUT_OF_RESOURCES;
199 }
200
201 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
202
203 CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);
204
205 return EFI_SUCCESS;
206 }
207
208
209 /**
210 Graphics output protocol interface to set video mode
211
212 @param This Protocol instance pointer.
213 @param ModeNumber The mode number to be set.
214
215 @retval EFI_SUCCESS Graphics mode was changed.
216 @retval EFI_DEVICE_ERROR The device had an error and could not complete
217 the request.
218 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 ConSpliterGraphicsOutputSetMode (
224 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
225 IN UINT32 ModeNumber
226 )
227 {
228 EFI_STATUS Status;
229 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
230 UINTN Index;
231 EFI_STATUS ReturnStatus;
232 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
233 UINTN Size;
234 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
235 UINTN NumberIndex;
236 UINTN SizeOfInfo;
237 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
238 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
239
240 if (ModeNumber >= This->Mode->MaxMode) {
241 return EFI_UNSUPPORTED;
242 }
243
244 if (ModeNumber == This->Mode->Mode) {
245 return EFI_SUCCESS;
246 }
247
248 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
249
250 //
251 // GopDevNullSetMode ()
252 //
253 ReturnStatus = EFI_SUCCESS;
254
255 //
256 // Free the old version
257 //
258 if (Private->GraphicsOutputBlt != NULL) {
259 FreePool (Private->GraphicsOutputBlt);
260 }
261
262 //
263 // Allocate the virtual Blt buffer
264 //
265 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
266 Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
267 Private->GraphicsOutputBlt = AllocateZeroPool (Size);
268
269 if (Private->GraphicsOutputBlt == NULL) {
270 return EFI_OUT_OF_RESOURCES;
271 }
272
273 //
274 // return the worst status met
275 //
276 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
277 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
278 if (GraphicsOutput != NULL) {
279 //
280 // Find corresponding ModeNumber of this GraphicsOutput instance
281 //
282 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
283 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
284 if (EFI_ERROR (Status)) {
285 return Status;
286 }
287 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
288 FreePool (Info);
289 break;
290 }
291 FreePool (Info);
292 }
293
294 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
295 if (EFI_ERROR (Status)) {
296 ReturnStatus = Status;
297 }
298 }
299
300 if (EFI_ERROR (ReturnStatus) && FeaturePcdGet (PcdUgaConsumeSupport)) {
301 UgaDraw = Private->TextOutList[Index].UgaDraw;
302 if (UgaDraw != NULL) {
303 Status = UgaDraw->SetMode (
304 UgaDraw,
305 Mode->HorizontalResolution,
306 Mode->VerticalResolution,
307 32,
308 60
309 );
310 if (EFI_ERROR (Status)) {
311 ReturnStatus = Status;
312 }
313 }
314 }
315 }
316
317 This->Mode->Mode = ModeNumber;
318
319 CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);
320
321 //
322 // Information is not enough here, so the following items remain unchanged:
323 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
324 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
325 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
326 //
327
328 Private->HardwareNeedsStarting = FALSE;
329
330 return ReturnStatus;
331 }
332
333 /**
334 The following table defines actions for BltOperations.
335
336 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
337 directly to every pixel of the video display rectangle
338 (DestinationX, DestinationY)
339 (DestinationX + Width, DestinationY + Height).
340 Only one pixel will be used from the BltBuffer. Delta is NOT used.
341 EfiBltVideoToBltBuffer - Read data from the video display rectangle
342 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
343 the BltBuffer rectangle (DestinationX, DestinationY )
344 (DestinationX + Width, DestinationY + Height). If DestinationX or
345 DestinationY is not zero then Delta must be set to the length in bytes
346 of a row in the BltBuffer.
347 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
348 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
349 video display rectangle (DestinationX, DestinationY)
350 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
351 not zero then Delta must be set to the length in bytes of a row in the
352 BltBuffer.
353 EfiBltVideoToVideo - Copy from the video display rectangle
354 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
355 to the video display rectangle (DestinationX, DestinationY)
356 (DestinationX + Width, DestinationY + Height).
357 The BltBuffer and Delta are not used in this mode.
358
359 @param Private Protocol instance pointer.
360 @param BltBuffer Buffer containing data to blit into video buffer.
361 This buffer has a size of
362 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
363 @param BltOperation Operation to perform on BlitBuffer and video
364 memory
365 @param SourceX X coordinate of source for the BltBuffer.
366 @param SourceY Y coordinate of source for the BltBuffer.
367 @param DestinationX X coordinate of destination for the BltBuffer.
368 @param DestinationY Y coordinate of destination for the BltBuffer.
369 @param Width Width of rectangle in BltBuffer in pixels.
370 @param Height Hight of rectangle in BltBuffer in pixels.
371 @param Delta OPTIONAL.
372
373 @retval EFI_SUCCESS The Blt operation completed.
374 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
375 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
376 buffer.
377
378 **/
379 EFI_STATUS
380 DevNullGraphicsOutputBlt (
381 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
382 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
383 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
384 IN UINTN SourceX,
385 IN UINTN SourceY,
386 IN UINTN DestinationX,
387 IN UINTN DestinationY,
388 IN UINTN Width,
389 IN UINTN Height,
390 IN UINTN Delta OPTIONAL
391 )
392 {
393 UINTN SrcY;
394 BOOLEAN Forward;
395 UINTN Index;
396 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
397 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;
398 UINTN HorizontalResolution;
399 UINTN VerticalResolution;
400
401 if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
402 return EFI_INVALID_PARAMETER;
403 }
404
405 if (Width == 0 || Height == 0) {
406 return EFI_INVALID_PARAMETER;
407 }
408
409 if (Delta == 0) {
410 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
411 }
412
413 HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
414 VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution;
415
416 //
417 // We need to fill the Virtual Screen buffer with the blt data.
418 //
419 if (BltOperation == EfiBltVideoToBltBuffer) {
420 //
421 // Video to BltBuffer: Source is Video, destination is BltBuffer
422 //
423 if ((SourceY + Height) > VerticalResolution) {
424 return EFI_INVALID_PARAMETER;
425 }
426
427 if ((SourceX + Width) > HorizontalResolution) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
432 ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];
433 while (Height > 0) {
434 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
435 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta);
436 ScreenPtr += HorizontalResolution;
437 Height--;
438 }
439 } else {
440 //
441 // BltBuffer to Video: Source is BltBuffer, destination is Video
442 //
443 if (DestinationY + Height > VerticalResolution) {
444 return EFI_INVALID_PARAMETER;
445 }
446
447 if (DestinationX + Width > HorizontalResolution) {
448 return EFI_INVALID_PARAMETER;
449 }
450
451 if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {
452 //
453 // Copy backwards, only care the Video to Video Blt
454 //
455 ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
456 SrcY = SourceY + Height - 1;
457 Forward = FALSE;
458 } else {
459 //
460 // Copy forwards, for other cases
461 //
462 ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];
463 SrcY = SourceY;
464 Forward = TRUE;
465 }
466
467 while (Height != 0) {
468 if (BltOperation == EfiBltVideoFill) {
469 for (Index = 0; Index < Width; Index++) {
470 ScreenPtr[Index] = *BltBuffer;
471 }
472 } else {
473 if (BltOperation == EfiBltBufferToVideo) {
474 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
475 } else {
476 BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];
477 }
478
479 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
480 }
481
482 if (Forward) {
483 ScreenPtr += HorizontalResolution;
484 SrcY ++;
485 } else {
486 ScreenPtr -= HorizontalResolution;
487 SrcY --;
488 }
489 Height--;
490 }
491 }
492
493 return EFI_SUCCESS;
494 }
495
496
497 /**
498 The following table defines actions for BltOperations.
499
500 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
501 directly to every pixel of the video display rectangle
502 (DestinationX, DestinationY)
503 (DestinationX + Width, DestinationY + Height).
504 Only one pixel will be used from the BltBuffer. Delta is NOT used.
505 EfiBltVideoToBltBuffer - Read data from the video display rectangle
506 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
507 the BltBuffer rectangle (DestinationX, DestinationY )
508 (DestinationX + Width, DestinationY + Height). If DestinationX or
509 DestinationY is not zero then Delta must be set to the length in bytes
510 of a row in the BltBuffer.
511 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
512 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
513 video display rectangle (DestinationX, DestinationY)
514 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
515 not zero then Delta must be set to the length in bytes of a row in the
516 BltBuffer.
517 EfiBltVideoToVideo - Copy from the video display rectangle
518 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
519 to the video display rectangle (DestinationX, DestinationY)
520 (DestinationX + Width, DestinationY + Height).
521 The BltBuffer and Delta are not used in this mode.
522
523 @param This Protocol instance pointer.
524 @param BltBuffer Buffer containing data to blit into video buffer.
525 This buffer has a size of
526 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
527 @param BltOperation Operation to perform on BlitBuffer and video
528 memory
529 @param SourceX X coordinate of source for the BltBuffer.
530 @param SourceY Y coordinate of source for the BltBuffer.
531 @param DestinationX X coordinate of destination for the BltBuffer.
532 @param DestinationY Y coordinate of destination for the BltBuffer.
533 @param Width Width of rectangle in BltBuffer in pixels.
534 @param Height Hight of rectangle in BltBuffer in pixels.
535 @param Delta OPTIONAL.
536
537 @retval EFI_SUCCESS The Blt operation completed.
538 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
539 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
540 buffer.
541
542 **/
543 EFI_STATUS
544 EFIAPI
545 ConSpliterGraphicsOutputBlt (
546 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
547 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
548 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
549 IN UINTN SourceX,
550 IN UINTN SourceY,
551 IN UINTN DestinationX,
552 IN UINTN DestinationY,
553 IN UINTN Width,
554 IN UINTN Height,
555 IN UINTN Delta OPTIONAL
556 )
557 {
558 EFI_STATUS Status;
559 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
560 UINTN Index;
561 EFI_STATUS ReturnStatus;
562 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
563 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
564
565 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
566
567 //
568 // Sync up DevNull GOP device
569 //
570 ReturnStatus = DevNullGraphicsOutputBlt (
571 Private,
572 BltBuffer,
573 BltOperation,
574 SourceX,
575 SourceY,
576 DestinationX,
577 DestinationY,
578 Width,
579 Height,
580 Delta
581 );
582
583 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
584 return ReturnStatus;
585 }
586 //
587 // return the worst status met
588 //
589 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
590 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
591 if (GraphicsOutput != NULL) {
592 Status = GraphicsOutput->Blt (
593 GraphicsOutput,
594 BltBuffer,
595 BltOperation,
596 SourceX,
597 SourceY,
598 DestinationX,
599 DestinationY,
600 Width,
601 Height,
602 Delta
603 );
604 if (EFI_ERROR (Status)) {
605 ReturnStatus = Status;
606 } else if (BltOperation == EfiBltVideoToBltBuffer) {
607 //
608 // Only need to read the data into buffer one time
609 //
610 return EFI_SUCCESS;
611 }
612 }
613
614 UgaDraw = Private->TextOutList[Index].UgaDraw;
615 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
616 Status = UgaDraw->Blt (
617 UgaDraw,
618 (EFI_UGA_PIXEL *) BltBuffer,
619 (EFI_UGA_BLT_OPERATION) BltOperation,
620 SourceX,
621 SourceY,
622 DestinationX,
623 DestinationY,
624 Width,
625 Height,
626 Delta
627 );
628 if (EFI_ERROR (Status)) {
629 ReturnStatus = Status;
630 } else if (BltOperation == EfiBltVideoToBltBuffer) {
631 //
632 // Only need to read the data into buffer one time
633 //
634 return EFI_SUCCESS;
635 }
636 }
637 }
638
639 return ReturnStatus;
640 }
641
642 /**
643 Write data from the buffer to video display based on Graphics Output setting.
644
645 @param Private Consplitter Text Out pointer.
646 @param GraphicsOutput Graphics Output protocol pointer.
647 @param UgaDraw UGA Draw protocol pointer.
648
649 @retval EFI_UNSUPPORTED No graphics devcie available .
650 @retval EFI_SUCCESS The Blt operation completed.
651 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
652 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
653
654
655 **/
656 EFI_STATUS
657 DevNullGopSync (
658 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
659 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
660 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
661 )
662 {
663 if (GraphicsOutput != NULL) {
664 return GraphicsOutput->Blt (
665 GraphicsOutput,
666 Private->GraphicsOutputBlt,
667 EfiBltBufferToVideo,
668 0,
669 0,
670 0,
671 0,
672 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
673 Private->GraphicsOutput.Mode->Info->VerticalResolution,
674 0
675 );
676 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
677 return UgaDraw->Blt (
678 UgaDraw,
679 (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,
680 EfiUgaBltBufferToVideo,
681 0,
682 0,
683 0,
684 0,
685 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
686 Private->GraphicsOutput.Mode->Info->VerticalResolution,
687 0
688 );
689 } else {
690 return EFI_UNSUPPORTED;
691 }
692 }
693
694
695 /**
696 Return the current video mode information.
697
698 @param This Protocol instance pointer.
699 @param HorizontalResolution Current video horizontal resolution in pixels
700 @param VerticalResolution Current video vertical resolution in pixels
701 @param ColorDepth Current video color depth in bits per pixel
702 @param RefreshRate Current video refresh rate in Hz.
703
704 @retval EFI_SUCCESS Mode information returned.
705 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
706 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
707
708 **/
709 EFI_STATUS
710 EFIAPI
711 ConSpliterUgaDrawGetMode (
712 IN EFI_UGA_DRAW_PROTOCOL *This,
713 OUT UINT32 *HorizontalResolution,
714 OUT UINT32 *VerticalResolution,
715 OUT UINT32 *ColorDepth,
716 OUT UINT32 *RefreshRate
717 )
718 {
719 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
720
721 if ((HorizontalResolution == NULL) ||
722 (VerticalResolution == NULL) ||
723 (RefreshRate == NULL) ||
724 (ColorDepth == NULL)) {
725 return EFI_INVALID_PARAMETER;
726 }
727 //
728 // retrieve private data
729 //
730 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
731
732 *HorizontalResolution = Private->UgaHorizontalResolution;
733 *VerticalResolution = Private->UgaVerticalResolution;
734 *ColorDepth = Private->UgaColorDepth;
735 *RefreshRate = Private->UgaRefreshRate;
736
737 return EFI_SUCCESS;
738 }
739
740
741 /**
742 Return the current video mode information.
743
744 @param This Protocol instance pointer.
745 @param HorizontalResolution Current video horizontal resolution in pixels
746 @param VerticalResolution Current video vertical resolution in pixels
747 @param ColorDepth Current video color depth in bits per pixel
748 @param RefreshRate Current video refresh rate in Hz.
749
750 @retval EFI_SUCCESS Mode information returned.
751 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
752 @retval EFI_OUT_OF_RESOURCES Out of resources.
753
754 **/
755 EFI_STATUS
756 EFIAPI
757 ConSpliterUgaDrawSetMode (
758 IN EFI_UGA_DRAW_PROTOCOL *This,
759 IN UINT32 HorizontalResolution,
760 IN UINT32 VerticalResolution,
761 IN UINT32 ColorDepth,
762 IN UINT32 RefreshRate
763 )
764 {
765 EFI_STATUS Status;
766 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
767 UINTN Index;
768 EFI_STATUS ReturnStatus;
769 UINTN Size;
770 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
771 UINTN NumberIndex;
772 UINTN SizeOfInfo;
773 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
774 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
775
776 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
777
778 //
779 // UgaDevNullSetMode ()
780 //
781 ReturnStatus = EFI_SUCCESS;
782
783 //
784 // Free the old version
785 //
786 if (Private->UgaBlt != NULL) {
787 FreePool (Private->UgaBlt);
788 }
789
790 //
791 // Allocate the virtual Blt buffer
792 //
793 Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);
794 Private->UgaBlt = AllocateZeroPool (Size);
795 if (Private->UgaBlt == NULL) {
796 return EFI_OUT_OF_RESOURCES;
797 }
798
799 //
800 // Update the Mode data
801 //
802 Private->UgaHorizontalResolution = HorizontalResolution;
803 Private->UgaVerticalResolution = VerticalResolution;
804 Private->UgaColorDepth = ColorDepth;
805 Private->UgaRefreshRate = RefreshRate;
806
807 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
808 return ReturnStatus;
809 }
810 //
811 // return the worst status met
812 //
813 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
814
815 ReturnStatus = EFI_UNSUPPORTED;
816
817 if (FeaturePcdGet (PcdUgaConsumeSupport)) {
818 UgaDraw = Private->TextOutList[Index].UgaDraw;
819 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
820 Status = UgaDraw->SetMode (
821 UgaDraw,
822 HorizontalResolution,
823 VerticalResolution,
824 ColorDepth,
825 RefreshRate
826 );
827 if (EFI_ERROR (Status)) {
828 ReturnStatus = Status;
829 }
830 }
831 }
832
833 if (EFI_ERROR (ReturnStatus)) {
834 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
835 if (GraphicsOutput != NULL) {
836 //
837 // Find corresponding ModeNumber of this GraphicsOutput instance
838 //
839 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
840 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
841 if (EFI_ERROR (Status)) {
842 return Status;
843 }
844 if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
845 FreePool (Info);
846 break;
847 }
848 FreePool (Info);
849 }
850
851 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
852 if (EFI_ERROR (Status)) {
853 ReturnStatus = Status;
854 }
855 }
856 }
857 }
858
859 return ReturnStatus;
860 }
861
862 /**
863 The following table defines actions for BltOperations.
864
865 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
866 directly to every pixel of the video display rectangle
867 (DestinationX, DestinationY)
868 (DestinationX + Width, DestinationY + Height).
869 Only one pixel will be used from the BltBuffer. Delta is NOT used.
870 EfiBltVideoToBltBuffer - Read data from the video display rectangle
871 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
872 the BltBuffer rectangle (DestinationX, DestinationY )
873 (DestinationX + Width, DestinationY + Height). If DestinationX or
874 DestinationY is not zero then Delta must be set to the length in bytes
875 of a row in the BltBuffer.
876 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
877 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
878 video display rectangle (DestinationX, DestinationY)
879 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
880 not zero then Delta must be set to the length in bytes of a row in the
881 BltBuffer.
882 EfiBltVideoToVideo - Copy from the video display rectangle
883 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
884 to the video display rectangle (DestinationX, DestinationY)
885 (DestinationX + Width, DestinationY + Height).
886 The BltBuffer and Delta are not used in this mode.
887
888 @param Private Protocol instance pointer.
889 @param BltBuffer Buffer containing data to blit into video buffer.
890 This buffer has a size of
891 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
892 @param BltOperation Operation to perform on BlitBuffer and video
893 memory
894 @param SourceX X coordinate of source for the BltBuffer.
895 @param SourceY Y coordinate of source for the BltBuffer.
896 @param DestinationX X coordinate of destination for the BltBuffer.
897 @param DestinationY Y coordinate of destination for the BltBuffer.
898 @param Width Width of rectangle in BltBuffer in pixels.
899 @param Height Hight of rectangle in BltBuffer in pixels.
900 @param Delta OPTIONAL.
901
902 @retval EFI_SUCCESS The Blt operation completed.
903 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
904 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
905 buffer.
906
907 **/
908 EFI_STATUS
909 DevNullUgaBlt (
910 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
911 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
912 IN EFI_UGA_BLT_OPERATION BltOperation,
913 IN UINTN SourceX,
914 IN UINTN SourceY,
915 IN UINTN DestinationX,
916 IN UINTN DestinationY,
917 IN UINTN Width,
918 IN UINTN Height,
919 IN UINTN Delta OPTIONAL
920 )
921 {
922 UINTN SrcY;
923 BOOLEAN Forward;
924 UINTN Index;
925 EFI_UGA_PIXEL *BltPtr;
926 EFI_UGA_PIXEL *ScreenPtr;
927 UINT32 HorizontalResolution;
928 UINT32 VerticalResolution;
929
930 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
931 return EFI_INVALID_PARAMETER;
932 }
933
934 if (Width == 0 || Height == 0) {
935 return EFI_INVALID_PARAMETER;
936 }
937
938 if (Delta == 0) {
939 Delta = Width * sizeof (EFI_UGA_PIXEL);
940 }
941
942 HorizontalResolution = Private->UgaHorizontalResolution;
943 VerticalResolution = Private->UgaVerticalResolution;
944
945 //
946 // We need to fill the Virtual Screen buffer with the blt data.
947 //
948 if (BltOperation == EfiUgaVideoToBltBuffer) {
949 //
950 // Video to BltBuffer: Source is Video, destination is BltBuffer
951 //
952 if ((SourceY + Height) > VerticalResolution) {
953 return EFI_INVALID_PARAMETER;
954 }
955
956 if ((SourceX + Width) > HorizontalResolution) {
957 return EFI_INVALID_PARAMETER;
958 }
959
960 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));
961 ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];
962 while (Height > 0) {
963 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));
964 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);
965 ScreenPtr += HorizontalResolution;
966 Height--;
967 }
968 } else {
969 //
970 // BltBuffer to Video: Source is BltBuffer, destination is Video
971 //
972 if (DestinationY + Height > VerticalResolution) {
973 return EFI_INVALID_PARAMETER;
974 }
975
976 if (DestinationX + Width > HorizontalResolution) {
977 return EFI_INVALID_PARAMETER;
978 }
979
980 if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {
981 //
982 // Copy backwards, only care the Video to Video Blt
983 //
984 ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
985 SrcY = SourceY + Height - 1;
986 Forward = FALSE;
987 } else {
988 //
989 // Copy forwards, for other cases
990 //
991 ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
992 SrcY = SourceY;
993 Forward = TRUE;
994 }
995
996 while (Height != 0) {
997 if (BltOperation == EfiUgaVideoFill) {
998 for (Index = 0; Index < Width; Index++) {
999 ScreenPtr[Index] = *BltBuffer;
1000 }
1001 } else {
1002 if (BltOperation == EfiUgaBltBufferToVideo) {
1003 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));
1004 } else {
1005 BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];
1006 }
1007
1008 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));
1009 }
1010
1011 if (Forward) {
1012 ScreenPtr += HorizontalResolution;
1013 SrcY ++;
1014 } else {
1015 ScreenPtr -= HorizontalResolution;
1016 SrcY --;
1017 }
1018 Height--;
1019 }
1020 }
1021
1022 return EFI_SUCCESS;
1023 }
1024
1025
1026 /**
1027 The following table defines actions for BltOperations.
1028
1029 EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
1030 directly to every pixel of the video display rectangle
1031 (DestinationX, DestinationY)
1032 (DestinationX + Width, DestinationY + Height).
1033 Only one pixel will be used from the BltBuffer. Delta is NOT used.
1034 EfiUgaVideoToBltBuffer - Read data from the video display rectangle
1035 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
1036 the BltBuffer rectangle (DestinationX, DestinationY )
1037 (DestinationX + Width, DestinationY + Height). If DestinationX or
1038 DestinationY is not zero then Delta must be set to the length in bytes
1039 of a row in the BltBuffer.
1040 EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle
1041 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
1042 video display rectangle (DestinationX, DestinationY)
1043 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
1044 not zero then Delta must be set to the length in bytes of a row in the
1045 BltBuffer.
1046 EfiUgaVideoToVideo - Copy from the video display rectangle
1047 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
1048 to the video display rectangle (DestinationX, DestinationY)
1049 (DestinationX + Width, DestinationY + Height).
1050 The BltBuffer and Delta are not used in this mode.
1051
1052 @param This Protocol instance pointer.
1053 @param BltBuffer Buffer containing data to blit into video buffer.
1054 This buffer has a size of
1055 Width*Height*sizeof(EFI_UGA_PIXEL)
1056 @param BltOperation Operation to perform on BlitBuffer and video
1057 memory
1058 @param SourceX X coordinate of source for the BltBuffer.
1059 @param SourceY Y coordinate of source for the BltBuffer.
1060 @param DestinationX X coordinate of destination for the BltBuffer.
1061 @param DestinationY Y coordinate of destination for the BltBuffer.
1062 @param Width Width of rectangle in BltBuffer in pixels.
1063 @param Height Hight of rectangle in BltBuffer in pixels.
1064 @param Delta OPTIONAL.
1065
1066 @retval EFI_SUCCESS The Blt operation completed.
1067 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
1068 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
1069 buffer.
1070
1071 **/
1072 EFI_STATUS
1073 EFIAPI
1074 ConSpliterUgaDrawBlt (
1075 IN EFI_UGA_DRAW_PROTOCOL *This,
1076 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
1077 IN EFI_UGA_BLT_OPERATION BltOperation,
1078 IN UINTN SourceX,
1079 IN UINTN SourceY,
1080 IN UINTN DestinationX,
1081 IN UINTN DestinationY,
1082 IN UINTN Width,
1083 IN UINTN Height,
1084 IN UINTN Delta OPTIONAL
1085 )
1086 {
1087 EFI_STATUS Status;
1088 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
1089 UINTN Index;
1090 EFI_STATUS ReturnStatus;
1091 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1092
1093 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
1094
1095 //
1096 // Sync up DevNull UGA device
1097 //
1098 ReturnStatus = DevNullUgaBlt (
1099 Private,
1100 BltBuffer,
1101 BltOperation,
1102 SourceX,
1103 SourceY,
1104 DestinationX,
1105 DestinationY,
1106 Width,
1107 Height,
1108 Delta
1109 );
1110 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
1111 return ReturnStatus;
1112 }
1113 //
1114 // return the worst status met
1115 //
1116 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
1117 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
1118 if (GraphicsOutput != NULL) {
1119 Status = GraphicsOutput->Blt (
1120 GraphicsOutput,
1121 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,
1122 (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,
1123 SourceX,
1124 SourceY,
1125 DestinationX,
1126 DestinationY,
1127 Width,
1128 Height,
1129 Delta
1130 );
1131 if (EFI_ERROR (Status)) {
1132 ReturnStatus = Status;
1133 } else if (BltOperation == EfiBltVideoToBltBuffer) {
1134 //
1135 // Only need to read the data into buffer one time
1136 //
1137 return EFI_SUCCESS;
1138 }
1139 }
1140
1141 if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1142 Status = Private->TextOutList[Index].UgaDraw->Blt (
1143 Private->TextOutList[Index].UgaDraw,
1144 BltBuffer,
1145 BltOperation,
1146 SourceX,
1147 SourceY,
1148 DestinationX,
1149 DestinationY,
1150 Width,
1151 Height,
1152 Delta
1153 );
1154 if (EFI_ERROR (Status)) {
1155 ReturnStatus = Status;
1156 } else if (BltOperation == EfiUgaVideoToBltBuffer) {
1157 //
1158 // Only need to read the data into buffer one time
1159 //
1160 return EFI_SUCCESS;
1161 }
1162 }
1163 }
1164
1165 return ReturnStatus;
1166 }
1167
1168 /**
1169 Write data from the buffer to video display based on UGA Draw setting.
1170
1171 @param Private Consplitter Text Out pointer.
1172 @param GraphicsOutput Graphics Output protocol pointer.
1173 @param UgaDraw UGA Draw protocol pointer.
1174
1175 @retval EFI_UNSUPPORTED No graphics devcie available .
1176 @retval EFI_SUCCESS The Blt operation completed.
1177 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
1178 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
1179
1180 **/
1181 EFI_STATUS
1182 DevNullUgaSync (
1183 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1184 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
1185 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
1186 )
1187 {
1188 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1189 return UgaDraw->Blt (
1190 UgaDraw,
1191 Private->UgaBlt,
1192 EfiUgaBltBufferToVideo,
1193 0,
1194 0,
1195 0,
1196 0,
1197 Private->UgaHorizontalResolution,
1198 Private->UgaVerticalResolution,
1199 Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
1200 );
1201 } else if (GraphicsOutput != NULL) {
1202 return GraphicsOutput->Blt (
1203 GraphicsOutput,
1204 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,
1205 EfiBltBufferToVideo,
1206 0,
1207 0,
1208 0,
1209 0,
1210 Private->UgaHorizontalResolution,
1211 Private->UgaVerticalResolution,
1212 0
1213 );
1214 } else {
1215 return EFI_UNSUPPORTED;
1216 }
1217 }
1218
1219
1220 /**
1221 Write a Unicode string to the output device.
1222
1223 @param Private Pointer to the console output splitter's private
1224 data. It indicates the calling context.
1225 @param WString The NULL-terminated Unicode string to be
1226 displayed on the output device(s). All output
1227 devices must also support the Unicode drawing
1228 defined in this file.
1229
1230 @retval EFI_SUCCESS The string was output to the device.
1231 @retval EFI_DEVICE_ERROR The device reported an error while attempting to
1232 output the text.
1233 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
1234 defined text mode.
1235 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
1236 characters in the Unicode string could not be
1237 rendered and were skipped.
1238
1239 **/
1240 EFI_STATUS
1241 DevNullTextOutOutputString (
1242 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1243 IN CHAR16 *WString
1244 )
1245 {
1246 UINTN SizeScreen;
1247 UINTN SizeAttribute;
1248 UINTN Index;
1249 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
1250 CHAR16 *Screen;
1251 CHAR16 *NullScreen;
1252 CHAR16 InsertChar;
1253 CHAR16 TempChar;
1254 CHAR16 *PStr;
1255 INT32 *Attribute;
1256 INT32 *NullAttributes;
1257 INT32 CurrentWidth;
1258 UINTN LastRow;
1259 UINTN MaxColumn;
1260
1261 Mode = &Private->TextOutMode;
1262 NullScreen = Private->DevNullScreen;
1263 NullAttributes = Private->DevNullAttributes;
1264 LastRow = Private->DevNullRows - 1;
1265 MaxColumn = Private->DevNullColumns;
1266
1267 if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) {
1268 CurrentWidth = 2;
1269 } else {
1270 CurrentWidth = 1;
1271 }
1272
1273 while (*WString != L'\0') {
1274
1275 if (*WString == CHAR_BACKSPACE) {
1276 //
1277 // If the cursor is at the left edge of the display, then move the cursor
1278 // one row up.
1279 //
1280 if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) {
1281 Mode->CursorRow--;
1282 Mode->CursorColumn = (INT32) MaxColumn;
1283 }
1284
1285 //
1286 // If the cursor is not at the left edge of the display,
1287 // then move the cursor left one column.
1288 //
1289 if (Mode->CursorColumn > 0) {
1290 Mode->CursorColumn--;
1291 if (Mode->CursorColumn > 0 &&
1292 NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE
1293 ) {
1294 Mode->CursorColumn--;
1295
1296 //
1297 // Insert an extra backspace
1298 //
1299 InsertChar = CHAR_BACKSPACE;
1300 PStr = WString + 1;
1301 while (*PStr != L'\0') {
1302 TempChar = *PStr;
1303 *PStr = InsertChar;
1304 InsertChar = TempChar;
1305 PStr++;
1306 }
1307
1308 *PStr = InsertChar;
1309 *(++PStr) = 0;
1310
1311 WString++;
1312 }
1313 }
1314
1315 WString++;
1316
1317 } else if (*WString == CHAR_LINEFEED) {
1318 //
1319 // If the cursor is at the bottom of the display,
1320 // then scroll the display one row, and do not update
1321 // the cursor position. Otherwise, move the cursor down one row.
1322 //
1323 if (Mode->CursorRow == (INT32) (LastRow)) {
1324 //
1325 // Scroll Screen Up One Row
1326 //
1327 SizeAttribute = LastRow * MaxColumn;
1328 CopyMem (
1329 NullAttributes,
1330 NullAttributes + MaxColumn,
1331 SizeAttribute * sizeof (INT32)
1332 );
1333
1334 //
1335 // Each row has an ending CHAR_NULL. So one more character each line
1336 // for DevNullScreen than DevNullAttributes
1337 //
1338 SizeScreen = SizeAttribute + LastRow;
1339 CopyMem (
1340 NullScreen,
1341 NullScreen + (MaxColumn + 1),
1342 SizeScreen * sizeof (CHAR16)
1343 );
1344
1345 //
1346 // Print Blank Line at last line
1347 //
1348 Screen = NullScreen + SizeScreen;
1349 Attribute = NullAttributes + SizeAttribute;
1350
1351 for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) {
1352 *Screen = ' ';
1353 *Attribute = Mode->Attribute;
1354 }
1355 } else {
1356 Mode->CursorRow++;
1357 }
1358
1359 WString++;
1360 } else if (*WString == CHAR_CARRIAGE_RETURN) {
1361 //
1362 // Move the cursor to the beginning of the current row.
1363 //
1364 Mode->CursorColumn = 0;
1365 WString++;
1366 } else {
1367 //
1368 // Print the character at the current cursor position and
1369 // move the cursor right one column. If this moves the cursor
1370 // past the right edge of the display, then the line should wrap to
1371 // the beginning of the next line. This is equivalent to inserting
1372 // a CR and an LF. Note that if the cursor is at the bottom of the
1373 // display, and the line wraps, then the display will be scrolled
1374 // one line.
1375 //
1376 Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn;
1377
1378 while (Mode->CursorColumn < (INT32) MaxColumn) {
1379 if (*WString == CHAR_NULL) {
1380 break;
1381 }
1382
1383 if (*WString == CHAR_BACKSPACE) {
1384 break;
1385 }
1386
1387 if (*WString == CHAR_LINEFEED) {
1388 break;
1389 }
1390
1391 if (*WString == CHAR_CARRIAGE_RETURN) {
1392 break;
1393 }
1394
1395 if (*WString == UNICODE_WIDE_CHAR || *WString == UNICODE_NARROW_CHAR) {
1396 CurrentWidth = (*WString == UNICODE_WIDE_CHAR) ? 2 : 1;
1397 WString++;
1398 continue;
1399 }
1400
1401 if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) {
1402 //
1403 // If a wide char is at the rightmost column, then move the char
1404 // to the beginning of the next row
1405 //
1406 NullScreen[Index + Mode->CursorRow] = L' ';
1407 NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE;
1408 Index++;
1409 Mode->CursorColumn++;
1410 } else {
1411 NullScreen[Index + Mode->CursorRow] = *WString;
1412 NullAttributes[Index] = Mode->Attribute;
1413 if (CurrentWidth == 1) {
1414 NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1415 } else {
1416 NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE;
1417 NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE);
1418 }
1419
1420 Index += CurrentWidth;
1421 WString++;
1422 Mode->CursorColumn += CurrentWidth;
1423 }
1424 }
1425 //
1426 // At the end of line, output carriage return and line feed
1427 //
1428 if (Mode->CursorColumn >= (INT32) MaxColumn) {
1429 DevNullTextOutOutputString (Private, mCrLfString);
1430 }
1431 }
1432 }
1433
1434 return EFI_SUCCESS;
1435 }
1436
1437
1438 /**
1439 Sets the output device(s) to a specified mode.
1440
1441 @param Private Private data structure pointer.
1442 @param ModeNumber The mode number to set.
1443
1444 @retval EFI_SUCCESS The requested text mode was set.
1445 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1446 the request.
1447 @retval EFI_UNSUPPORTED The mode number was not valid.
1448 @retval EFI_OUT_OF_RESOURCES Out of resources.
1449
1450 **/
1451 EFI_STATUS
1452 DevNullTextOutSetMode (
1453 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1454 IN UINTN ModeNumber
1455 )
1456 {
1457 UINTN Size;
1458 INT32 CurrentMode;
1459 UINTN Row;
1460 UINTN Column;
1461 TEXT_OUT_SPLITTER_QUERY_DATA *Mode;
1462
1463 //
1464 // No extra check for ModeNumber here, as it has been checked in
1465 // ConSplitterTextOutSetMode. And mode 0 should always be supported.
1466 // Row and Column should be fetched from intersection map.
1467 //
1468 if (Private->TextOutModeMap != NULL) {
1469 CurrentMode = *(Private->TextOutModeMap + Private->TextOutListCount * ModeNumber);
1470 } else {
1471 CurrentMode = (INT32)(ModeNumber);
1472 }
1473 Mode = &(Private->TextOutQueryData[CurrentMode]);
1474 Row = Mode->Rows;
1475 Column = Mode->Columns;
1476
1477 if (Row <= 0 && Column <= 0) {
1478 return EFI_UNSUPPORTED;
1479 }
1480
1481 if (Private->TextOutMode.Mode != (INT32) ModeNumber) {
1482
1483 Private->TextOutMode.Mode = (INT32) ModeNumber;
1484 Private->DevNullColumns = Column;
1485 Private->DevNullRows = Row;
1486
1487 if (Private->DevNullScreen != NULL) {
1488 FreePool (Private->DevNullScreen);
1489 }
1490
1491 Size = (Row * (Column + 1)) * sizeof (CHAR16);
1492 Private->DevNullScreen = AllocateZeroPool (Size);
1493 if (Private->DevNullScreen == NULL) {
1494 return EFI_OUT_OF_RESOURCES;
1495 }
1496
1497 if (Private->DevNullAttributes != NULL) {
1498 FreePool (Private->DevNullAttributes);
1499 }
1500
1501 Size = Row * Column * sizeof (INT32);
1502 Private->DevNullAttributes = AllocateZeroPool (Size);
1503 if (Private->DevNullAttributes == NULL) {
1504 return EFI_OUT_OF_RESOURCES;
1505 }
1506 }
1507
1508 DevNullTextOutClearScreen (Private);
1509
1510 return EFI_SUCCESS;
1511 }
1512
1513
1514 /**
1515 Clears the output device(s) display to the currently selected background
1516 color.
1517
1518 @param Private Protocol instance pointer.
1519
1520 @retval EFI_SUCCESS The operation completed successfully.
1521 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1522 the request.
1523 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1524
1525 **/
1526 EFI_STATUS
1527 DevNullTextOutClearScreen (
1528 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1529 )
1530 {
1531 UINTN Row;
1532 UINTN Column;
1533 CHAR16 *Screen;
1534 INT32 *Attributes;
1535 INT32 CurrentAttribute;
1536
1537 //
1538 // Clear the DevNull Text Out Buffers.
1539 // The screen is filled with spaces.
1540 // The attributes are all synced with the current Simple Text Out Attribute
1541 //
1542 Screen = Private->DevNullScreen;
1543 Attributes = Private->DevNullAttributes;
1544 CurrentAttribute = Private->TextOutMode.Attribute;
1545
1546 for (Row = 0; Row < Private->DevNullRows; Row++) {
1547 for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {
1548 *Screen = ' ';
1549 *Attributes = CurrentAttribute;
1550 }
1551 //
1552 // Each line of the screen has a NULL on the end so we must skip over it
1553 //
1554 Screen++;
1555 }
1556
1557 DevNullTextOutSetCursorPosition (Private, 0, 0);
1558
1559 return DevNullTextOutEnableCursor (Private, TRUE);
1560 }
1561
1562
1563 /**
1564 Sets the current coordinates of the cursor position.
1565
1566 @param Private Protocol instance pointer.
1567 @param Column
1568 @param Row the position to set the cursor to. Must be
1569 greater than or equal to zero and less than the
1570 number of columns and rows by QueryMode ().
1571
1572 @retval EFI_SUCCESS The operation completed successfully.
1573 @retval EFI_DEVICE_ERROR The device had an error and could not complete
1574 the request.
1575 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or
1576 the cursor position is invalid for the current
1577 mode.
1578
1579 **/
1580 EFI_STATUS
1581 DevNullTextOutSetCursorPosition (
1582 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1583 IN UINTN Column,
1584 IN UINTN Row
1585 )
1586 {
1587 //
1588 // No need to do extra check here as whether (Column, Row) is valid has
1589 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1590 // always be supported.
1591 //
1592 Private->TextOutMode.CursorColumn = (INT32) Column;
1593 Private->TextOutMode.CursorRow = (INT32) Row;
1594
1595 return EFI_SUCCESS;
1596 }
1597
1598
1599 /**
1600 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1601 In this driver, the cursor cannot be hidden.
1602
1603 @param Private Indicates the calling context.
1604 @param Visible If TRUE, the cursor is set to be visible, If
1605 FALSE, the cursor is set to be invisible.
1606
1607 @retval EFI_SUCCESS The request is valid.
1608
1609 **/
1610 EFI_STATUS
1611 DevNullTextOutEnableCursor (
1612 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1613 IN BOOLEAN Visible
1614 )
1615 {
1616 Private->TextOutMode.CursorVisible = Visible;
1617
1618 return EFI_SUCCESS;
1619 }
1620
1621
1622 /**
1623 Take the DevNull TextOut device and update the Simple Text Out on every
1624 UGA device.
1625
1626 @param Private Indicates the calling context.
1627
1628 @retval EFI_SUCCESS The request is valid.
1629 @retval other Return status of TextOut->OutputString ()
1630
1631 **/
1632 EFI_STATUS
1633 DevNullSyncStdOut (
1634 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1635 )
1636 {
1637 EFI_STATUS Status;
1638 EFI_STATUS ReturnStatus;
1639 UINTN Row;
1640 UINTN Column;
1641 UINTN List;
1642 UINTN MaxColumn;
1643 UINTN CurrentColumn;
1644 UINTN StartRow;
1645 UINTN StartColumn;
1646 INT32 StartAttribute;
1647 BOOLEAN StartCursorState;
1648 CHAR16 *Screen;
1649 CHAR16 *Str;
1650 CHAR16 *Buffer;
1651 CHAR16 *BufferTail;
1652 CHAR16 *ScreenStart;
1653 INT32 CurrentAttribute;
1654 INT32 *Attributes;
1655 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
1656
1657 //
1658 // Save the devices Attributes, Cursor enable state and location
1659 //
1660 StartColumn = Private->TextOutMode.CursorColumn;
1661 StartRow = Private->TextOutMode.CursorRow;
1662 StartAttribute = Private->TextOutMode.Attribute;
1663 StartCursorState = Private->TextOutMode.CursorVisible;
1664
1665 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1666
1667 Sto = Private->TextOutList[List].TextOut;
1668
1669 //
1670 // Skip non GOP/UGA devices
1671 //
1672 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1673 Sto->EnableCursor (Sto, FALSE);
1674 Sto->ClearScreen (Sto);
1675 }
1676 }
1677
1678 ReturnStatus = EFI_SUCCESS;
1679 Screen = Private->DevNullScreen;
1680 Attributes = Private->DevNullAttributes;
1681 MaxColumn = Private->DevNullColumns;
1682
1683 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
1684 if (Buffer == NULL) {
1685 return ReturnStatus;
1686 }
1687
1688 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
1689
1690 if (Row == (Private->DevNullRows - 1)) {
1691 //
1692 // Don't ever sync the last character as it will scroll the screen
1693 //
1694 Screen[MaxColumn - 1] = 0x00;
1695 }
1696
1697 Column = 0;
1698 while (Column < MaxColumn) {
1699 if (Screen[Column] > 0) {
1700 CurrentAttribute = Attributes[Column];
1701 CurrentColumn = Column;
1702 ScreenStart = &Screen[Column];
1703
1704 //
1705 // the line end is alway 0x0. So Column should be less than MaxColumn
1706 // It should be still in the same row
1707 //
1708 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
1709
1710 if (Attributes[Column] != CurrentAttribute) {
1711 Column--;
1712 break;
1713 }
1714
1715 *BufferTail = *Str;
1716 BufferTail++;
1717 if ((Attributes[Column] & EFI_WIDE_ATTRIBUTE) != 0) {
1718 Str++;
1719 Column++;
1720 }
1721 }
1722
1723 *BufferTail = 0;
1724
1725 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1726
1727 Sto = Private->TextOutList[List].TextOut;
1728
1729 //
1730 // Skip non GOP/UGA devices
1731 //
1732 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1733 Sto->SetAttribute (Sto, CurrentAttribute);
1734 Sto->SetCursorPosition (Sto, CurrentColumn, Row);
1735 Status = Sto->OutputString (Sto, Buffer);
1736 if (EFI_ERROR (Status)) {
1737 ReturnStatus = Status;
1738 }
1739 }
1740 }
1741
1742 }
1743
1744 Column++;
1745 }
1746 }
1747 //
1748 // Restore the devices Attributes, Cursor enable state and location
1749 //
1750 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1751 Sto = Private->TextOutList[List].TextOut;
1752
1753 //
1754 // Skip non GOP/UGA devices
1755 //
1756 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1757 Sto->SetAttribute (Sto, StartAttribute);
1758 Sto->SetCursorPosition (Sto, StartColumn, StartRow);
1759 Status = Sto->EnableCursor (Sto, StartCursorState);
1760 if (EFI_ERROR (Status)) {
1761 ReturnStatus = Status;
1762 }
1763 }
1764 }
1765
1766 FreePool (Buffer);
1767
1768 return ReturnStatus;
1769 }