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