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