]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitterGraphics.c
2f60e11c40bb67eb431529a2f40ad485d8a77845
[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 if (Private->DevNullScreen != NULL) {
1319 FreePool (Private->DevNullScreen);
1320 }
1321
1322 Size = (Row * (Column + 1)) * sizeof (CHAR16);
1323 Private->DevNullScreen = AllocateZeroPool (Size);
1324 if (Private->DevNullScreen == NULL) {
1325 return EFI_OUT_OF_RESOURCES;
1326 }
1327
1328 if (Private->DevNullAttributes != NULL) {
1329 FreePool (Private->DevNullAttributes);
1330 }
1331
1332 Size = Row * Column * sizeof (INT32);
1333 Private->DevNullAttributes = AllocateZeroPool (Size);
1334 if (Private->DevNullAttributes == NULL) {
1335 return EFI_OUT_OF_RESOURCES;
1336 }
1337 }
1338
1339 DevNullTextOutClearScreen (Private);
1340
1341 return EFI_SUCCESS;
1342 }
1343
1344 EFI_STATUS
1345 DevNullTextOutClearScreen (
1346 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1347 )
1348 /*++
1349
1350 Routine Description:
1351 Clears the output device(s) display to the currently selected background
1352 color.
1353
1354 Arguments:
1355 Private - Protocol instance pointer.
1356
1357 Returns:
1358 EFI_SUCCESS - The operation completed successfully.
1359 EFI_DEVICE_ERROR - The device had an error and
1360 could not complete the request.
1361 EFI_UNSUPPORTED - The output device is not in a valid text mode.
1362
1363 --*/
1364 {
1365 UINTN Row;
1366 UINTN Column;
1367 CHAR16 *Screen;
1368 INT32 *Attributes;
1369 INT32 CurrentAttribute;
1370
1371 //
1372 // Clear the DevNull Text Out Buffers.
1373 // The screen is filled with spaces.
1374 // The attributes are all synced with the current Simple Text Out Attribute
1375 //
1376 Screen = Private->DevNullScreen;
1377 Attributes = Private->DevNullAttributes;
1378 CurrentAttribute = Private->TextOutMode.Attribute;
1379
1380 for (Row = 0; Row < Private->DevNullRows; Row++) {
1381 for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) {
1382 *Screen = ' ';
1383 *Attributes = CurrentAttribute;
1384 }
1385 //
1386 // Each line of the screen has a NULL on the end so we must skip over it
1387 //
1388 Screen++;
1389 }
1390
1391 DevNullTextOutSetCursorPosition (Private, 0, 0);
1392
1393 return DevNullTextOutEnableCursor (Private, TRUE);
1394 }
1395
1396 EFI_STATUS
1397 DevNullTextOutSetCursorPosition (
1398 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1399 IN UINTN Column,
1400 IN UINTN Row
1401 )
1402 /*++
1403
1404 Routine Description:
1405 Sets the current coordinates of the cursor position
1406
1407 Arguments:
1408 Private - Protocol instance pointer.
1409 Column, Row - the position to set the cursor to. Must be greater than or
1410 equal to zero and less than the number of columns and rows
1411 by QueryMode ().
1412
1413 Returns:
1414 EFI_SUCCESS - The operation completed successfully.
1415 EFI_DEVICE_ERROR - The device had an error and
1416 could not complete the request.
1417 EFI_UNSUPPORTED - The output device is not in a valid text mode, or the
1418 cursor position is invalid for the current mode.
1419
1420 --*/
1421 {
1422 //
1423 // No need to do extra check here as whether (Column, Row) is valid has
1424 // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
1425 // always be supported.
1426 //
1427 Private->TextOutMode.CursorColumn = (INT32) Column;
1428 Private->TextOutMode.CursorRow = (INT32) Row;
1429
1430 return EFI_SUCCESS;
1431 }
1432
1433 EFI_STATUS
1434 DevNullTextOutEnableCursor (
1435 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
1436 IN BOOLEAN Visible
1437 )
1438 /*++
1439 Routine Description:
1440
1441 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1442 In this driver, the cursor cannot be hidden.
1443
1444 Arguments:
1445
1446 Private - Indicates the calling context.
1447
1448 Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor
1449 is set to be invisible.
1450
1451 Returns:
1452
1453 EFI_SUCCESS - The request is valid.
1454
1455
1456 --*/
1457 {
1458 Private->TextOutMode.CursorVisible = Visible;
1459
1460 return EFI_SUCCESS;
1461 }
1462
1463 EFI_STATUS
1464 DevNullSyncGopStdOut (
1465 IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private
1466 )
1467 /*++
1468 Routine Description:
1469 Take the DevNull TextOut device and update the Simple Text Out on every
1470 UGA device.
1471
1472 Arguments:
1473 Private - Indicates the calling context.
1474
1475 Returns:
1476 EFI_SUCCESS - The request is valid.
1477 other - Return status of TextOut->OutputString ()
1478
1479 --*/
1480 {
1481 EFI_STATUS Status;
1482 EFI_STATUS ReturnStatus;
1483 UINTN Row;
1484 UINTN Column;
1485 UINTN List;
1486 UINTN MaxColumn;
1487 UINTN CurrentColumn;
1488 UINTN StartRow;
1489 UINTN StartColumn;
1490 INT32 StartAttribute;
1491 BOOLEAN StartCursorState;
1492 CHAR16 *Screen;
1493 CHAR16 *Str;
1494 CHAR16 *Buffer;
1495 CHAR16 *BufferTail;
1496 CHAR16 *ScreenStart;
1497 INT32 CurrentAttribute;
1498 INT32 *Attributes;
1499 EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto;
1500
1501 //
1502 // Save the devices Attributes, Cursor enable state and location
1503 //
1504 StartColumn = Private->TextOutMode.CursorColumn;
1505 StartRow = Private->TextOutMode.CursorRow;
1506 StartAttribute = Private->TextOutMode.Attribute;
1507 StartCursorState = Private->TextOutMode.CursorVisible;
1508
1509 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1510
1511 Sto = Private->TextOutList[List].TextOut;
1512
1513 //
1514 // Skip non GOP/UGA devices
1515 //
1516 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1517 Sto->EnableCursor (Sto, FALSE);
1518 Sto->ClearScreen (Sto);
1519 }
1520 }
1521
1522 ReturnStatus = EFI_SUCCESS;
1523 Screen = Private->DevNullScreen;
1524 Attributes = Private->DevNullAttributes;
1525 MaxColumn = Private->DevNullColumns;
1526
1527 Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16));
1528
1529 for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) {
1530
1531 if (Row == (Private->DevNullRows - 1)) {
1532 //
1533 // Don't ever sync the last character as it will scroll the screen
1534 //
1535 Screen[MaxColumn - 1] = 0x00;
1536 }
1537
1538 Column = 0;
1539 while (Column < MaxColumn) {
1540 if (Screen[Column]) {
1541 CurrentAttribute = Attributes[Column];
1542 CurrentColumn = Column;
1543 ScreenStart = &Screen[Column];
1544
1545 //
1546 // the line end is alway 0x0. So Column should be less than MaxColumn
1547 // It should be still in the same row
1548 //
1549 for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) {
1550
1551 if (Attributes[Column] != CurrentAttribute) {
1552 Column--;
1553 break;
1554 }
1555
1556 *BufferTail = *Str;
1557 BufferTail++;
1558 if (Attributes[Column] & EFI_WIDE_ATTRIBUTE) {
1559 Str++;
1560 Column++;
1561 }
1562 }
1563
1564 *BufferTail = 0;
1565
1566 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1567
1568 Sto = Private->TextOutList[List].TextOut;
1569
1570 //
1571 // Skip non GOP/UGA devices
1572 //
1573 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1574 Sto->SetAttribute (Sto, CurrentAttribute);
1575 Sto->SetCursorPosition (Sto, CurrentColumn, Row);
1576 Status = Sto->OutputString (Sto, Buffer);
1577 if (EFI_ERROR (Status)) {
1578 ReturnStatus = Status;
1579 }
1580 }
1581 }
1582
1583 }
1584
1585 Column++;
1586 }
1587 }
1588 //
1589 // Restore the devices Attributes, Cursor enable state and location
1590 //
1591 for (List = 0; List < Private->CurrentNumberOfConsoles; List++) {
1592 Sto = Private->TextOutList[List].TextOut;
1593
1594 //
1595 // Skip non GOP/UGA devices
1596 //
1597 if ((Private->TextOutList[List].GraphicsOutput != NULL) || (Private->TextOutList[List].UgaDraw != NULL)) {
1598 Sto->SetAttribute (Sto, StartAttribute);
1599 Sto->SetCursorPosition (Sto, StartColumn, StartRow);
1600 Status = Sto->EnableCursor (Sto, StartCursorState);
1601 if (EFI_ERROR (Status)) {
1602 ReturnStatus = Status;
1603 }
1604 }
1605 }
1606
1607 FreePool (Buffer);
1608
1609 return ReturnStatus;
1610 }