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