]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
ECC clean up.
[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 #include "ConSplitter.h"
20
21
22 CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
23
24
25 /**
26 Return the current video mode information. Also returns info about existence
27 of Graphics Output devices or UGA Draw devices in system, and whether the Std
28 In device is locked. GopUgaExists and StdInLocked parameters are optional, and
29 only returned if a non NULL pointer is passed in.
30
31 @param This Protocol instance pointer.
32 @param Mode Current video mode.
33 @param GopUgaExists TRUE if GOP Spliter has found a GOP/UGA device
34 @param StdInLocked TRUE if StdIn device is keyboard locked
35
36 @retval EFI_SUCCESS Video mode information is returned.
37 @retval EFI_INVALID_PARAMETER Invalid parameters if Mode == NULL.
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 video mode to either text or graphics. Graphics is
80 for Quiet Boot.
81
82 @param This Console Control Protocol instance pointer.
83 @param Mode Video mode is to be set.
84
85 @retval EFI_SUCCESS Mode is set successfully.
86 @retval EFI_INVALID_PARAMETER Mode is not the valid mode value.
87 @retval EFI_UNSUPPORTED Mode is unsupported by console device.
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 Returns information for an available graphics mode that the graphics device
155 and the set of active video output devices supports.
156
157 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
158 @param ModeNumber The mode number to return information on.
159 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
160 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
161
162 @retval EFI_SUCCESS Mode information returned.
163 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
164 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
165 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
166 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
167 @retval EFI_OUT_OF_RESOURCES No resource available.
168
169 **/
170 EFI_STATUS
171 EFIAPI
172 ConSpliterGraphicsOutputQueryMode (
173 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
174 IN UINT32 ModeNumber,
175 OUT UINTN *SizeOfInfo,
176 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
177 )
178 {
179 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
180
181 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
182 return EFI_INVALID_PARAMETER;
183 }
184
185 //
186 // retrieve private data
187 //
188 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
189
190 if (Private->HardwareNeedsStarting) {
191 return EFI_NOT_STARTED;
192 }
193
194 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
195 if (*Info == NULL) {
196 return EFI_OUT_OF_RESOURCES;
197 }
198
199 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
200
201 CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);
202
203 return EFI_SUCCESS;
204 }
205
206
207 /**
208 Set the video device into the specified mode and clears the visible portions of
209 the output display to black.
210
211 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
212 @param ModeNumber Abstraction that defines the current video mode.
213
214 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
215 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
216 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
217 @retval EFI_OUT_OF_RESOURCES No resource available.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 ConSpliterGraphicsOutputSetMode (
223 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
224 IN UINT32 ModeNumber
225 )
226 {
227 EFI_STATUS Status;
228 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
229 UINTN Index;
230 EFI_STATUS ReturnStatus;
231 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode;
232 UINTN Size;
233 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
234 UINTN NumberIndex;
235 UINTN SizeOfInfo;
236 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
237 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
238
239 if (ModeNumber >= This->Mode->MaxMode) {
240 return EFI_UNSUPPORTED;
241 }
242
243 if (ModeNumber == This->Mode->Mode) {
244 return EFI_SUCCESS;
245 }
246
247 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
248
249 ReturnStatus = EFI_SUCCESS;
250
251 //
252 // Free the old version
253 //
254 if (Private->GraphicsOutputBlt != NULL) {
255 FreePool (Private->GraphicsOutputBlt);
256 }
257
258 //
259 // Allocate the virtual Blt buffer
260 //
261 Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
262 Size = Mode->HorizontalResolution * Mode->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
263 Private->GraphicsOutputBlt = AllocateZeroPool (Size);
264
265 if (Private->GraphicsOutputBlt == NULL) {
266 return EFI_OUT_OF_RESOURCES;
267 }
268
269 //
270 // return the worst status met
271 //
272 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
273 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
274 if (GraphicsOutput != NULL) {
275 //
276 // Find corresponding ModeNumber of this GraphicsOutput instance
277 //
278 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
279 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
280 if (EFI_ERROR (Status)) {
281 return Status;
282 }
283 if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
284 FreePool (Info);
285 break;
286 }
287 FreePool (Info);
288 }
289
290 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
291 if (EFI_ERROR (Status)) {
292 ReturnStatus = Status;
293 }
294 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
295 UgaDraw = Private->TextOutList[Index].UgaDraw;
296 if (UgaDraw != NULL) {
297 Status = UgaDraw->SetMode (
298 UgaDraw,
299 Mode->HorizontalResolution,
300 Mode->VerticalResolution,
301 32,
302 60
303 );
304 if (EFI_ERROR (Status)) {
305 ReturnStatus = Status;
306 }
307 }
308 }
309 }
310
311 This->Mode->Mode = ModeNumber;
312
313 CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);
314
315 //
316 // Information is not enough here, so the following items remain unchanged:
317 // GraphicsOutputMode->Info->Version, GraphicsOutputMode->Info->PixelFormat
318 // GraphicsOutputMode->SizeOfInfo, GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize
319 // These items will be initialized/updated when a new GOP device is added into ConsoleSplitter.
320 //
321
322 Private->HardwareNeedsStarting = FALSE;
323
324 return ReturnStatus;
325 }
326
327 /**
328 The following table defines actions for BltOperations.
329
330 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
331 directly to every pixel of the video display rectangle
332 (DestinationX, DestinationY)
333 (DestinationX + Width, DestinationY + Height).
334 Only one pixel will be used from the BltBuffer. Delta is NOT used.
335 EfiBltVideoToBltBuffer - Read data from the video display rectangle
336 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
337 the BltBuffer rectangle (DestinationX, DestinationY )
338 (DestinationX + Width, DestinationY + Height). If DestinationX or
339 DestinationY is not zero then Delta must be set to the length in bytes
340 of a row in the BltBuffer.
341 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
342 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
343 video display rectangle (DestinationX, DestinationY)
344 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
345 not zero then Delta must be set to the length in bytes of a row in the
346 BltBuffer.
347 EfiBltVideoToVideo - Copy from the video display rectangle
348 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
349 to the video display rectangle (DestinationX, DestinationY)
350 (DestinationX + Width, DestinationY + Height).
351 The BltBuffer and Delta are not used in this mode.
352
353 @param Private Protocol instance pointer.
354 @param BltBuffer Buffer containing data to blit into video buffer.
355 This buffer has a size of
356 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
357 @param BltOperation Operation to perform on BlitBuffer and video
358 memory
359 @param SourceX X coordinate of source for the BltBuffer.
360 @param SourceY Y coordinate of source for the BltBuffer.
361 @param DestinationX X coordinate of destination for the BltBuffer.
362 @param DestinationY Y coordinate of destination for the BltBuffer.
363 @param Width Width of rectangle in BltBuffer in pixels.
364 @param Height Hight of rectangle in BltBuffer in pixels.
365 @param Delta OPTIONAL.
366
367 @retval EFI_SUCCESS The Blt operation completed.
368 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
369 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
370 buffer.
371
372 **/
373 EFI_STATUS
374 DevNullGraphicsOutputBlt (
375 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
376 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
377 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
378 IN UINTN SourceX,
379 IN UINTN SourceY,
380 IN UINTN DestinationX,
381 IN UINTN DestinationY,
382 IN UINTN Width,
383 IN UINTN Height,
384 IN UINTN Delta OPTIONAL
385 )
386 {
387 UINTN SrcY;
388 BOOLEAN Forward;
389 UINTN Index;
390 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPtr;
391 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenPtr;
392 UINTN HorizontalResolution;
393 UINTN VerticalResolution;
394
395 if ((BltOperation < EfiBltVideoFill) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
396 return EFI_INVALID_PARAMETER;
397 }
398
399 if (Width == 0 || Height == 0) {
400 return EFI_INVALID_PARAMETER;
401 }
402
403 if (Delta == 0) {
404 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
405 }
406
407 HorizontalResolution = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
408 VerticalResolution = Private->GraphicsOutput.Mode->Info->VerticalResolution;
409
410 //
411 // We need to fill the Virtual Screen buffer with the blt data.
412 //
413 if (BltOperation == EfiBltVideoToBltBuffer) {
414 //
415 // Video to BltBuffer: Source is Video, destination is BltBuffer
416 //
417 if ((SourceY + Height) > VerticalResolution) {
418 return EFI_INVALID_PARAMETER;
419 }
420
421 if ((SourceX + Width) > HorizontalResolution) {
422 return EFI_INVALID_PARAMETER;
423 }
424
425 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
426 ScreenPtr = &Private->GraphicsOutputBlt[SourceY * HorizontalResolution + SourceX];
427 while (Height > 0) {
428 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
429 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltPtr + Delta);
430 ScreenPtr += HorizontalResolution;
431 Height--;
432 }
433 } else {
434 //
435 // BltBuffer to Video: Source is BltBuffer, destination is Video
436 //
437 if (DestinationY + Height > VerticalResolution) {
438 return EFI_INVALID_PARAMETER;
439 }
440
441 if (DestinationX + Width > HorizontalResolution) {
442 return EFI_INVALID_PARAMETER;
443 }
444
445 if ((BltOperation == EfiBltVideoToVideo) && (DestinationY > SourceY)) {
446 //
447 // Copy backwards, only care the Video to Video Blt
448 //
449 ScreenPtr = &Private->GraphicsOutputBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
450 SrcY = SourceY + Height - 1;
451 Forward = FALSE;
452 } else {
453 //
454 // Copy forwards, for other cases
455 //
456 ScreenPtr = &Private->GraphicsOutputBlt[DestinationY * HorizontalResolution + DestinationX];
457 SrcY = SourceY;
458 Forward = TRUE;
459 }
460
461 while (Height != 0) {
462 if (BltOperation == EfiBltVideoFill) {
463 for (Index = 0; Index < Width; Index++) {
464 ScreenPtr[Index] = *BltBuffer;
465 }
466 } else {
467 if (BltOperation == EfiBltBufferToVideo) {
468 BltPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
469 } else {
470 BltPtr = &Private->GraphicsOutputBlt[SrcY * HorizontalResolution + SourceX];
471 }
472
473 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
474 }
475
476 if (Forward) {
477 ScreenPtr += HorizontalResolution;
478 SrcY ++;
479 } else {
480 ScreenPtr -= HorizontalResolution;
481 SrcY --;
482 }
483 Height--;
484 }
485 }
486
487 return EFI_SUCCESS;
488 }
489
490
491 /**
492 The following table defines actions for BltOperations.
493
494 EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY)
495 directly to every pixel of the video display rectangle
496 (DestinationX, DestinationY)
497 (DestinationX + Width, DestinationY + Height).
498 Only one pixel will be used from the BltBuffer. Delta is NOT used.
499 EfiBltVideoToBltBuffer - Read data from the video display rectangle
500 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
501 the BltBuffer rectangle (DestinationX, DestinationY )
502 (DestinationX + Width, DestinationY + Height). If DestinationX or
503 DestinationY is not zero then Delta must be set to the length in bytes
504 of a row in the BltBuffer.
505 EfiBltBufferToVideo - Write data from the BltBuffer rectangle
506 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
507 video display rectangle (DestinationX, DestinationY)
508 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
509 not zero then Delta must be set to the length in bytes of a row in the
510 BltBuffer.
511 EfiBltVideoToVideo - Copy from the video display rectangle
512 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
513 to the video display rectangle (DestinationX, DestinationY)
514 (DestinationX + Width, DestinationY + Height).
515 The BltBuffer and Delta are not used in this mode.
516
517 @param This Protocol instance pointer.
518 @param BltBuffer Buffer containing data to blit into video buffer.
519 This buffer has a size of
520 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
521 @param BltOperation Operation to perform on BlitBuffer and video
522 memory
523 @param SourceX X coordinate of source for the BltBuffer.
524 @param SourceY Y coordinate of source for the BltBuffer.
525 @param DestinationX X coordinate of destination for the BltBuffer.
526 @param DestinationY Y coordinate of destination for the BltBuffer.
527 @param Width Width of rectangle in BltBuffer in pixels.
528 @param Height Hight of rectangle in BltBuffer in pixels.
529 @param Delta OPTIONAL.
530
531 @retval EFI_SUCCESS The Blt operation completed.
532 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
533 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
534 buffer.
535
536 **/
537 EFI_STATUS
538 EFIAPI
539 ConSpliterGraphicsOutputBlt (
540 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
541 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
542 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
543 IN UINTN SourceX,
544 IN UINTN SourceY,
545 IN UINTN DestinationX,
546 IN UINTN DestinationY,
547 IN UINTN Width,
548 IN UINTN Height,
549 IN UINTN Delta OPTIONAL
550 )
551 {
552 EFI_STATUS Status;
553 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
554 UINTN Index;
555 EFI_STATUS ReturnStatus;
556 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
557 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
558
559 Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
560
561 //
562 // Sync up DevNull GOP device
563 //
564 ReturnStatus = DevNullGraphicsOutputBlt (
565 Private,
566 BltBuffer,
567 BltOperation,
568 SourceX,
569 SourceY,
570 DestinationX,
571 DestinationY,
572 Width,
573 Height,
574 Delta
575 );
576
577 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
578 return ReturnStatus;
579 }
580 //
581 // return the worst status met
582 //
583 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
584 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
585 if (GraphicsOutput != NULL) {
586 Status = GraphicsOutput->Blt (
587 GraphicsOutput,
588 BltBuffer,
589 BltOperation,
590 SourceX,
591 SourceY,
592 DestinationX,
593 DestinationY,
594 Width,
595 Height,
596 Delta
597 );
598 if (EFI_ERROR (Status)) {
599 ReturnStatus = Status;
600 } else if (BltOperation == EfiBltVideoToBltBuffer) {
601 //
602 // Only need to read the data into buffer one time
603 //
604 return EFI_SUCCESS;
605 }
606 }
607
608 UgaDraw = Private->TextOutList[Index].UgaDraw;
609 if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
610 Status = UgaDraw->Blt (
611 UgaDraw,
612 (EFI_UGA_PIXEL *) BltBuffer,
613 (EFI_UGA_BLT_OPERATION) BltOperation,
614 SourceX,
615 SourceY,
616 DestinationX,
617 DestinationY,
618 Width,
619 Height,
620 Delta
621 );
622 if (EFI_ERROR (Status)) {
623 ReturnStatus = Status;
624 } else if (BltOperation == EfiBltVideoToBltBuffer) {
625 //
626 // Only need to read the data into buffer one time
627 //
628 return EFI_SUCCESS;
629 }
630 }
631 }
632
633 return ReturnStatus;
634 }
635
636 /**
637 Write data from the buffer to video display based on Graphics Output setting.
638
639 @param Private Consplitter Text Out pointer.
640 @param GraphicsOutput Graphics Output protocol pointer.
641 @param UgaDraw UGA Draw protocol pointer.
642
643 @retval EFI_UNSUPPORTED No graphics devcie available .
644 @retval EFI_SUCCESS The Blt operation completed.
645 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
646 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
647
648
649 **/
650 EFI_STATUS
651 DevNullGopSync (
652 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
653 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
654 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
655 )
656 {
657 if (GraphicsOutput != NULL) {
658 return GraphicsOutput->Blt (
659 GraphicsOutput,
660 Private->GraphicsOutputBlt,
661 EfiBltBufferToVideo,
662 0,
663 0,
664 0,
665 0,
666 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
667 Private->GraphicsOutput.Mode->Info->VerticalResolution,
668 0
669 );
670 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
671 return UgaDraw->Blt (
672 UgaDraw,
673 (EFI_UGA_PIXEL *) Private->GraphicsOutputBlt,
674 EfiUgaBltBufferToVideo,
675 0,
676 0,
677 0,
678 0,
679 Private->GraphicsOutput.Mode->Info->HorizontalResolution,
680 Private->GraphicsOutput.Mode->Info->VerticalResolution,
681 0
682 );
683 } else {
684 return EFI_UNSUPPORTED;
685 }
686 }
687
688 /**
689 Return the current video mode information.
690
691 @param This The EFI_UGA_DRAW_PROTOCOL instance.
692 @param HorizontalResolution The size of video screen in pixels in the X dimension.
693 @param VerticalResolution The size of video screen in pixels in the Y dimension.
694 @param ColorDepth Number of bits per pixel, currently defined to be 32.
695 @param RefreshRate The refresh rate of the monitor in Hertz.
696
697 @retval EFI_SUCCESS Mode information returned.
698 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
699 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
700
701 **/
702 EFI_STATUS
703 EFIAPI
704 ConSpliterUgaDrawGetMode (
705 IN EFI_UGA_DRAW_PROTOCOL *This,
706 OUT UINT32 *HorizontalResolution,
707 OUT UINT32 *VerticalResolution,
708 OUT UINT32 *ColorDepth,
709 OUT UINT32 *RefreshRate
710 )
711 {
712 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
713
714 if ((HorizontalResolution == NULL) ||
715 (VerticalResolution == NULL) ||
716 (RefreshRate == NULL) ||
717 (ColorDepth == NULL)) {
718 return EFI_INVALID_PARAMETER;
719 }
720 //
721 // retrieve private data
722 //
723 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
724
725 *HorizontalResolution = Private->UgaHorizontalResolution;
726 *VerticalResolution = Private->UgaVerticalResolution;
727 *ColorDepth = Private->UgaColorDepth;
728 *RefreshRate = Private->UgaRefreshRate;
729
730 return EFI_SUCCESS;
731 }
732
733
734 /**
735 Set the current video mode information.
736
737 @param This The EFI_UGA_DRAW_PROTOCOL instance.
738 @param HorizontalResolution The size of video screen in pixels in the X dimension.
739 @param VerticalResolution The size of video screen in pixels in the Y dimension.
740 @param ColorDepth Number of bits per pixel, currently defined to be 32.
741 @param RefreshRate The refresh rate of the monitor in Hertz.
742
743 @retval EFI_SUCCESS Mode information returned.
744 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
745 @retval EFI_OUT_OF_RESOURCES Out of resources.
746
747 **/
748 EFI_STATUS
749 EFIAPI
750 ConSpliterUgaDrawSetMode (
751 IN EFI_UGA_DRAW_PROTOCOL *This,
752 IN UINT32 HorizontalResolution,
753 IN UINT32 VerticalResolution,
754 IN UINT32 ColorDepth,
755 IN UINT32 RefreshRate
756 )
757 {
758 EFI_STATUS Status;
759 TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
760 UINTN Index;
761 EFI_STATUS ReturnStatus;
762 UINTN Size;
763 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
764 UINTN NumberIndex;
765 UINTN SizeOfInfo;
766 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
767 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
768
769 Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
770
771 //
772 // UgaDevNullSetMode ()
773 //
774 ReturnStatus = EFI_SUCCESS;
775
776 //
777 // Free the old version
778 //
779 if (Private->UgaBlt != NULL) {
780 FreePool (Private->UgaBlt);
781 }
782
783 //
784 // Allocate the virtual Blt buffer
785 //
786 Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL);
787 Private->UgaBlt = AllocateZeroPool (Size);
788 if (Private->UgaBlt == NULL) {
789 return EFI_OUT_OF_RESOURCES;
790 }
791
792 //
793 // Update the Mode data
794 //
795 Private->UgaHorizontalResolution = HorizontalResolution;
796 Private->UgaVerticalResolution = VerticalResolution;
797 Private->UgaColorDepth = ColorDepth;
798 Private->UgaRefreshRate = RefreshRate;
799
800 if (Private->ConsoleOutputMode != EfiConsoleControlScreenGraphics) {
801 return ReturnStatus;
802 }
803 //
804 // return the worst status met
805 //
806 for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
807
808 ReturnStatus = EFI_UNSUPPORTED;
809
810 GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
811 if (GraphicsOutput != NULL) {
812 //
813 // Find corresponding ModeNumber of this GraphicsOutput instance
814 //
815 for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
816 Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
817 if (EFI_ERROR (Status)) {
818 return Status;
819 }
820 if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
821 FreePool (Info);
822 break;
823 }
824 FreePool (Info);
825 }
826
827 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
828 if (EFI_ERROR (Status)) {
829 ReturnStatus = Status;
830 }
831 } else if (FeaturePcdGet (PcdUgaConsumeSupport)){
832 UgaDraw = Private->TextOutList[Index].UgaDraw;
833 if (UgaDraw != NULL) {
834 Status = UgaDraw->SetMode (
835 UgaDraw,
836 HorizontalResolution,
837 VerticalResolution,
838 ColorDepth,
839 RefreshRate
840 );
841 if (EFI_ERROR (Status)) {
842 ReturnStatus = Status;
843 }
844 }
845 }
846 }
847
848 return ReturnStatus;
849 }
850
851 /**
852 Blt a rectangle of pixels on the graphics screen.
853
854 The following table defines actions for BltOperations.
855
856 EfiUgaVideoFill:
857 Write data from the BltBuffer pixel (SourceX, SourceY)
858 directly to every pixel of the video display rectangle
859 (DestinationX, DestinationY)
860 (DestinationX + Width, DestinationY + Height).
861 Only one pixel will be used from the BltBuffer. Delta is NOT used.
862 EfiUgaVideoToBltBuffer:
863 Read data from the video display rectangle
864 (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
865 the BltBuffer rectangle (DestinationX, DestinationY )
866 (DestinationX + Width, DestinationY + Height). If DestinationX or
867 DestinationY is not zero then Delta must be set to the length in bytes
868 of a row in the BltBuffer.
869 EfiUgaBltBufferToVideo:
870 Write data from the BltBuffer rectangle
871 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
872 video display rectangle (DestinationX, DestinationY)
873 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
874 not zero then Delta must be set to the length in bytes of a row in the
875 BltBuffer.
876 EfiUgaVideoToVideo:
877 Copy from the video display rectangle
878 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
879 to the video display rectangle (DestinationX, DestinationY)
880 (DestinationX + Width, DestinationY + Height).
881 The BltBuffer and Delta are not used in this mode.
882
883 @param Private Text Out Splitter pointer.
884 @param BltBuffer Buffer containing data to blit into video buffer.
885 This buffer has a size of
886 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
887 @param BltOperation Operation to perform on BlitBuffer and video
888 memory
889 @param SourceX X coordinate of source for the BltBuffer.
890 @param SourceY Y coordinate of source for the BltBuffer.
891 @param DestinationX X coordinate of destination for the BltBuffer.
892 @param DestinationY Y coordinate of destination for the BltBuffer.
893 @param Width Width of rectangle in BltBuffer in pixels.
894 @param Height Hight of rectangle in BltBuffer in pixels.
895 @param Delta OPTIONAL.
896
897 @retval EFI_SUCCESS The Blt operation completed.
898 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
899 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
900 buffer.
901
902 **/
903 EFI_STATUS
904 DevNullUgaBlt (
905 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
906 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
907 IN EFI_UGA_BLT_OPERATION BltOperation,
908 IN UINTN SourceX,
909 IN UINTN SourceY,
910 IN UINTN DestinationX,
911 IN UINTN DestinationY,
912 IN UINTN Width,
913 IN UINTN Height,
914 IN UINTN Delta OPTIONAL
915 )
916 {
917 UINTN SrcY;
918 BOOLEAN Forward;
919 UINTN Index;
920 EFI_UGA_PIXEL *BltPtr;
921 EFI_UGA_PIXEL *ScreenPtr;
922 UINT32 HorizontalResolution;
923 UINT32 VerticalResolution;
924
925 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
926 return EFI_INVALID_PARAMETER;
927 }
928
929 if (Width == 0 || Height == 0) {
930 return EFI_INVALID_PARAMETER;
931 }
932
933 if (Delta == 0) {
934 Delta = Width * sizeof (EFI_UGA_PIXEL);
935 }
936
937 HorizontalResolution = Private->UgaHorizontalResolution;
938 VerticalResolution = Private->UgaVerticalResolution;
939
940 //
941 // We need to fill the Virtual Screen buffer with the blt data.
942 //
943 if (BltOperation == EfiUgaVideoToBltBuffer) {
944 //
945 // Video to BltBuffer: Source is Video, destination is BltBuffer
946 //
947 if ((SourceY + Height) > VerticalResolution) {
948 return EFI_INVALID_PARAMETER;
949 }
950
951 if ((SourceX + Width) > HorizontalResolution) {
952 return EFI_INVALID_PARAMETER;
953 }
954
955 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL));
956 ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX];
957 while (Height > 0) {
958 CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL));
959 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta);
960 ScreenPtr += HorizontalResolution;
961 Height--;
962 }
963 } else {
964 //
965 // BltBuffer to Video: Source is BltBuffer, destination is Video
966 //
967 if (DestinationY + Height > VerticalResolution) {
968 return EFI_INVALID_PARAMETER;
969 }
970
971 if (DestinationX + Width > HorizontalResolution) {
972 return EFI_INVALID_PARAMETER;
973 }
974
975 if ((BltOperation == EfiUgaVideoToVideo) && (DestinationY > SourceY)) {
976 //
977 // Copy backwards, only care the Video to Video Blt
978 //
979 ScreenPtr = &Private->UgaBlt[(DestinationY + Height - 1) * HorizontalResolution + DestinationX];
980 SrcY = SourceY + Height - 1;
981 Forward = FALSE;
982 } else {
983 //
984 // Copy forwards, for other cases
985 //
986 ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX];
987 SrcY = SourceY;
988 Forward = TRUE;
989 }
990
991 while (Height != 0) {
992 if (BltOperation == EfiUgaVideoFill) {
993 for (Index = 0; Index < Width; Index++) {
994 ScreenPtr[Index] = *BltBuffer;
995 }
996 } else {
997 if (BltOperation == EfiUgaBltBufferToVideo) {
998 BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL));
999 } else {
1000 BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX];
1001 }
1002
1003 CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL));
1004 }
1005
1006 if (Forward) {
1007 ScreenPtr += HorizontalResolution;
1008 SrcY ++;
1009 } else {
1010 ScreenPtr -= HorizontalResolution;
1011 SrcY --;
1012 }
1013 Height--;
1014 }
1015 }
1016
1017 return EFI_SUCCESS;
1018 }
1019
1020 /**
1021 Blt a rectangle of pixels on the graphics screen.
1022
1023 The following table defines actions for BltOperations.
1024
1025 EfiUgaVideoFill:
1026 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:
1032 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:
1039 Write data from the BltBuffer rectangle
1040 (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
1041 video display rectangle (DestinationX, DestinationY)
1042 (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
1043 not zero then Delta must be set to the length in bytes of a row in the
1044 BltBuffer.
1045 EfiUgaVideoToVideo:
1046 Copy from the video display rectangle
1047 (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
1048 to the video display rectangle (DestinationX, DestinationY)
1049 (DestinationX + Width, DestinationY + Height).
1050 The BltBuffer and Delta are not used in this mode.
1051
1052 @param This Protocol instance pointer.
1053 @param BltBuffer Buffer containing data to blit into video buffer. This
1054 buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
1055 @param BltOperation Operation to perform on BlitBuffer and video 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 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 (GraphicsOutput != NULL) {
1186 return GraphicsOutput->Blt (
1187 GraphicsOutput,
1188 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) Private->UgaBlt,
1189 EfiBltBufferToVideo,
1190 0,
1191 0,
1192 0,
1193 0,
1194 Private->UgaHorizontalResolution,
1195 Private->UgaVerticalResolution,
1196 0
1197 );
1198 } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
1199 return UgaDraw->Blt (
1200 UgaDraw,
1201 Private->UgaBlt,
1202 EfiUgaBltBufferToVideo,
1203 0,
1204 0,
1205 0,
1206 0,
1207 Private->UgaHorizontalResolution,
1208 Private->UgaVerticalResolution,
1209 Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL)
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) != 0) {
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 Text Out Splitter 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 Text Out Splitter 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 Text Out Splitter 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 Set cursor visibility property.
1598
1599 @param Private Text Out Splitter pointer.
1600 @param Visible If TRUE, the cursor is set to be visible, If
1601 FALSE, the cursor is set to be invisible.
1602
1603 @retval EFI_SUCCESS Returns always.
1604
1605 **/
1606 EFI_STATUS
1607 DevNullTextOutEnableCursor (
1608 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1609 IN BOOLEAN Visible
1610 )
1611 {
1612 Private->TextOutMode.CursorVisible = Visible;
1613
1614 return EFI_SUCCESS;
1615 }
1616
1617
1618 /**
1619 Take the DevNull TextOut device and update the Simple Text Out on every
1620 UGA device.
1621
1622 @param Private Text Out Splitter pointer.
1623
1624 @retval EFI_SUCCESS The request is valid.
1625 @retval other Return status of TextOut->OutputString ()
1626
1627 **/
1628 EFI_STATUS
1629 DevNullSyncStdOut (
1630 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1631 )
1632 {
1633 EFI_STATUS Status;
1634 EFI_STATUS ReturnStatus;
1635 UINTN Row;
1636 UINTN Column;
1637 UINTN List;
1638 UINTN MaxColumn;
1639 UINTN CurrentColumn;
1640 UINTN StartRow;
1641 UINTN StartColumn;
1642 INT32 StartAttribute;
1643 BOOLEAN StartCursorState;
1644 CHAR16 *Screen;
1645 CHAR16 *Str;
1646 CHAR16 *Buffer;
1647 CHAR16 *BufferTail;
1648 CHAR16 *ScreenStart;
1649 INT32 CurrentAttribute;
1650 INT32 *Attributes;
1651 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
1652
1653 //
1654 // Save the devices Attributes, Cursor enable state and location
1655 //
1656 StartColumn = Private->TextOutMode.CursorColumn;
1657 StartRow = Private->TextOutMode.CursorRow;
1658 StartAttribute = Private->TextOutMode.Attribute;
1659 StartCursorState = Private->TextOutMode.CursorVisible;
1660
1661 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1662
1663 Sto = Private->TextOutList[List].TextOut;
1664
1665 //
1666 // Skip non GOP/UGA devices
1667 //
1668 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1669 Sto->EnableCursor (Sto, FALSE);
1670 Sto->ClearScreen (Sto);
1671 }
1672 }
1673
1674 ReturnStatus = EFI_SUCCESS;
1675 Screen = Private->DevNullScreen;
1676 Attributes = Private->DevNullAttributes;
1677 MaxColumn = Private->DevNullColumns;
1678
1679 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
1680 if (Buffer == NULL) {
1681 return ReturnStatus;
1682 }
1683
1684 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
1685
1686 if (Row == (Private->DevNullRows - 1)) {
1687 //
1688 // Don't ever sync the last character as it will scroll the screen
1689 //
1690 Screen[MaxColumn - 1] = 0x00;
1691 }
1692
1693 Column = 0;
1694 while (Column < MaxColumn) {
1695 if (Screen[Column] > 0) {
1696 CurrentAttribute = Attributes[Column];
1697 CurrentColumn = Column;
1698 ScreenStart = &Screen[Column];
1699
1700 //
1701 // the line end is alway 0x0. So Column should be less than MaxColumn
1702 // It should be still in the same row
1703 //
1704 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
1705
1706 if (Attributes[Column] != CurrentAttribute) {
1707 Column--;
1708 break;
1709 }
1710
1711 *BufferTail = *Str;
1712 BufferTail++;
1713 if ((Attributes[Column] & EFI_WIDE_ATTRIBUTE) != 0) {
1714 Str++;
1715 Column++;
1716 }
1717 }
1718
1719 *BufferTail = 0;
1720
1721 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1722
1723 Sto = Private->TextOutList[List].TextOut;
1724
1725 //
1726 // Skip non GOP/UGA devices
1727 //
1728 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1729 Sto->SetAttribute (Sto, CurrentAttribute);
1730 Sto->SetCursorPosition (Sto, CurrentColumn, Row);
1731 Status = Sto->OutputString (Sto, Buffer);
1732 if (EFI_ERROR (Status)) {
1733 ReturnStatus = Status;
1734 }
1735 }
1736 }
1737
1738 }
1739
1740 Column++;
1741 }
1742 }
1743 //
1744 // Restore the devices Attributes, Cursor enable state and location
1745 //
1746 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1747 Sto = Private->TextOutList[List].TextOut;
1748
1749 //
1750 // Skip non GOP/UGA devices
1751 //
1752 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1753 Sto->SetAttribute (Sto, StartAttribute);
1754 Sto->SetCursorPosition (Sto, StartColumn, StartRow);
1755 Status = Sto->EnableCursor (Sto, StartCursorState);
1756 if (EFI_ERROR (Status)) {
1757 ReturnStatus = Status;
1758 }
1759 }
1760 }
1761
1762 FreePool (Buffer);
1763
1764 return ReturnStatus;
1765 }