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