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