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