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