1 /** @file
2   Support for Graphics output spliter.
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 
8 **/
9 
10 #include "ConSplitter.h"
11 
12 
13 CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
14 
15 /**
16   Returns information for an available graphics mode that the graphics device
17   and the set of active video output devices supports.
18 
19   @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
20   @param  ModeNumber            The mode number to return information on.
21   @param  SizeOfInfo            A pointer to the size, in bytes, of the Info buffer.
22   @param  Info                  A pointer to callee allocated buffer that returns information about ModeNumber.
23 
24   @retval EFI_SUCCESS           Mode information returned.
25   @retval EFI_BUFFER_TOO_SMALL  The Info buffer was too small.
26   @retval EFI_DEVICE_ERROR      A hardware error occurred trying to retrieve the video mode.
27   @retval EFI_INVALID_PARAMETER One of the input args was NULL.
28   @retval EFI_OUT_OF_RESOURCES  No resource available.
29 
30 **/
31 EFI_STATUS
32 EFIAPI
ConSplitterGraphicsOutputQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber,OUT UINTN * SizeOfInfo,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ** Info)33 ConSplitterGraphicsOutputQueryMode (
34   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
35   IN  UINT32                                ModeNumber,
36   OUT UINTN                                 *SizeOfInfo,
37   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
38   )
39 {
40   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
41   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
42   EFI_STATUS                      Status;
43   UINTN                           Index;
44 
45   if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
46     return EFI_INVALID_PARAMETER;
47   }
48 
49   //
50   // retrieve private data
51   //
52   Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
53 
54   GraphicsOutput = NULL;
55 
56   if (Private->CurrentNumberOfGraphicsOutput == 1) {
57     //
58     // Find the only one GraphicsOutput.
59     //
60     for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
61       GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
62       if (GraphicsOutput != NULL) {
63         break;
64       }
65     }
66   }
67 
68   if (GraphicsOutput != NULL) {
69     //
70     // If only one physical GOP device exist, return its information.
71     //
72     Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) ModeNumber, SizeOfInfo, Info);
73     return Status;
74   } else {
75     //
76     // If 2 more phyiscal GOP device exist or GOP protocol does not exist,
77     // return GOP information (PixelFormat is PixelBltOnly) created in ConSplitterAddGraphicsOutputMode ().
78     //
79     *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
80     if (*Info == NULL) {
81       return EFI_OUT_OF_RESOURCES;
82     }
83     *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
84     CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo);
85   }
86 
87   return EFI_SUCCESS;
88 }
89 
90 
91 /**
92   Set the video device into the specified mode and clears the visible portions of
93   the output display to black.
94 
95   @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
96   @param  ModeNumber            Abstraction that defines the current video mode.
97 
98   @retval EFI_SUCCESS           The graphics mode specified by ModeNumber was selected.
99   @retval EFI_DEVICE_ERROR      The device had an error and could not complete the request.
100   @retval EFI_UNSUPPORTED       ModeNumber is not supported by this device.
101   @retval EFI_OUT_OF_RESOURCES  No resource available.
102 
103 **/
104 EFI_STATUS
105 EFIAPI
ConSplitterGraphicsOutputSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber)106 ConSplitterGraphicsOutputSetMode (
107   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
108   IN  UINT32                       ModeNumber
109   )
110 {
111   EFI_STATUS                             Status;
112   TEXT_OUT_SPLITTER_PRIVATE_DATA         *Private;
113   UINTN                                  Index;
114   EFI_STATUS                             ReturnStatus;
115   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Mode;
116   EFI_GRAPHICS_OUTPUT_PROTOCOL           *GraphicsOutput;
117   EFI_GRAPHICS_OUTPUT_PROTOCOL           *PhysicalGraphicsOutput;
118   UINTN                                  NumberIndex;
119   UINTN                                  SizeOfInfo;
120   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Info;
121   EFI_UGA_DRAW_PROTOCOL                  *UgaDraw;
122 
123   if (ModeNumber >= This->Mode->MaxMode) {
124     return EFI_UNSUPPORTED;
125   }
126 
127   Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
128   Mode = &Private->GraphicsOutputModeBuffer[ModeNumber];
129 
130   ReturnStatus = EFI_SUCCESS;
131   GraphicsOutput = NULL;
132   PhysicalGraphicsOutput = NULL;
133   //
134   // return the worst status met
135   //
136   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
137     GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
138     if (GraphicsOutput != NULL) {
139       PhysicalGraphicsOutput = GraphicsOutput;
140       //
141       // Find corresponding ModeNumber of this GraphicsOutput instance
142       //
143       for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
144         Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
145         if (EFI_ERROR (Status)) {
146           return Status;
147         }
148         if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) {
149           FreePool (Info);
150           break;
151         }
152         FreePool (Info);
153       }
154 
155       Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
156       if (EFI_ERROR (Status)) {
157         ReturnStatus = Status;
158       }
159     } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
160       UgaDraw = Private->TextOutList[Index].UgaDraw;
161       if (UgaDraw != NULL) {
162         Status = UgaDraw->SetMode (
163                             UgaDraw,
164                             Mode->HorizontalResolution,
165                             Mode->VerticalResolution,
166                             32,
167                             60
168                             );
169         if (EFI_ERROR (Status)) {
170           ReturnStatus = Status;
171         }
172       }
173     }
174   }
175 
176   This->Mode->Mode = ModeNumber;
177 
178   if ((Private->CurrentNumberOfGraphicsOutput == 1) && (PhysicalGraphicsOutput != NULL)) {
179     //
180     // If only one physical GOP device exist, copy physical information to consplitter.
181     //
182     CopyMem (This->Mode->Info, PhysicalGraphicsOutput->Mode->Info, PhysicalGraphicsOutput->Mode->SizeOfInfo);
183     This->Mode->SizeOfInfo = PhysicalGraphicsOutput->Mode->SizeOfInfo;
184     This->Mode->FrameBufferBase = PhysicalGraphicsOutput->Mode->FrameBufferBase;
185     This->Mode->FrameBufferSize = PhysicalGraphicsOutput->Mode->FrameBufferSize;
186   } else {
187     //
188     // If 2 more phyiscal GOP device exist or GOP protocol does not exist,
189     // return GOP information (PixelFormat is PixelBltOnly) created in ConSplitterAddGraphicsOutputMode ().
190     //
191     CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo);
192   }
193 
194   return ReturnStatus;
195 }
196 
197 
198 
199 /**
200   The following table defines actions for BltOperations.
201 
202   EfiBltVideoFill - Write data from the  BltBuffer pixel (SourceX, SourceY)
203   directly to every pixel of the video display rectangle
204   (DestinationX, DestinationY)
205   (DestinationX + Width, DestinationY + Height).
206   Only one pixel will be used from the BltBuffer. Delta is NOT used.
207   EfiBltVideoToBltBuffer - Read data from the video display rectangle
208   (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
209   the BltBuffer rectangle (DestinationX, DestinationY )
210   (DestinationX + Width, DestinationY + Height). If DestinationX or
211   DestinationY is not zero then Delta must be set to the length in bytes
212   of a row in the BltBuffer.
213   EfiBltBufferToVideo - Write data from the  BltBuffer rectangle
214   (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
215   video display rectangle (DestinationX, DestinationY)
216   (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
217   not zero then Delta must be set to the length in bytes of a row in the
218   BltBuffer.
219   EfiBltVideoToVideo - Copy from the video display rectangle
220   (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
221   to the video display rectangle (DestinationX, DestinationY)
222   (DestinationX + Width, DestinationY + Height).
223   The BltBuffer and Delta  are not used in this mode.
224 
225   @param  This                    Protocol instance pointer.
226   @param  BltBuffer               Buffer containing data to blit into video buffer.
227                                   This buffer has a size of
228                                   Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
229   @param  BltOperation            Operation to perform on BlitBuffer and video
230                                   memory
231   @param  SourceX                 X coordinate of source for the BltBuffer.
232   @param  SourceY                 Y coordinate of source for the BltBuffer.
233   @param  DestinationX            X coordinate of destination for the BltBuffer.
234   @param  DestinationY            Y coordinate of destination for the BltBuffer.
235   @param  Width                   Width of rectangle in BltBuffer in pixels.
236   @param  Height                  Hight of rectangle in BltBuffer in pixels.
237   @param  Delta                   OPTIONAL.
238 
239   @retval EFI_SUCCESS             The Blt operation completed.
240   @retval EFI_INVALID_PARAMETER   BltOperation is not valid.
241   @retval EFI_DEVICE_ERROR        A hardware error occurred writting to the video
242                                   buffer.
243 
244 **/
245 EFI_STATUS
246 EFIAPI
ConSplitterGraphicsOutputBlt(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)247 ConSplitterGraphicsOutputBlt (
248   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *This,
249   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                 *BltBuffer, OPTIONAL
250   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION             BltOperation,
251   IN  UINTN                                         SourceX,
252   IN  UINTN                                         SourceY,
253   IN  UINTN                                         DestinationX,
254   IN  UINTN                                         DestinationY,
255   IN  UINTN                                         Width,
256   IN  UINTN                                         Height,
257   IN  UINTN                                         Delta         OPTIONAL
258   )
259 {
260   EFI_STATUS                      Status;
261   EFI_STATUS                      ReturnStatus;
262   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
263   UINTN                           Index;
264   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
265   EFI_UGA_DRAW_PROTOCOL           *UgaDraw;
266 
267   if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
268     return EFI_INVALID_PARAMETER;
269   }
270 
271   Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
272 
273   ReturnStatus = EFI_SUCCESS;
274 
275   //
276   // return the worst status met
277   //
278   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
279     GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
280     if (GraphicsOutput != NULL) {
281       Status = GraphicsOutput->Blt (
282                               GraphicsOutput,
283                               BltBuffer,
284                               BltOperation,
285                               SourceX,
286                               SourceY,
287                               DestinationX,
288                               DestinationY,
289                               Width,
290                               Height,
291                               Delta
292                               );
293       if (EFI_ERROR (Status)) {
294         ReturnStatus = Status;
295       } else if (BltOperation == EfiBltVideoToBltBuffer) {
296         //
297         // Only need to read the data into buffer one time
298         //
299         return EFI_SUCCESS;
300       }
301     }
302 
303     UgaDraw = Private->TextOutList[Index].UgaDraw;
304     if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
305       Status = UgaDraw->Blt (
306                               UgaDraw,
307                               (EFI_UGA_PIXEL *) BltBuffer,
308                               (EFI_UGA_BLT_OPERATION) BltOperation,
309                               SourceX,
310                               SourceY,
311                               DestinationX,
312                               DestinationY,
313                               Width,
314                               Height,
315                               Delta
316                               );
317       if (EFI_ERROR (Status)) {
318         ReturnStatus = Status;
319       } else if (BltOperation == EfiBltVideoToBltBuffer) {
320         //
321         // Only need to read the data into buffer one time
322         //
323         return EFI_SUCCESS;
324       }
325     }
326   }
327 
328   return ReturnStatus;
329 }
330 
331 /**
332   Return the current video mode information.
333 
334   @param  This                  The EFI_UGA_DRAW_PROTOCOL instance.
335   @param  HorizontalResolution  The size of video screen in pixels in the X dimension.
336   @param  VerticalResolution    The size of video screen in pixels in the Y dimension.
337   @param  ColorDepth            Number of bits per pixel, currently defined to be 32.
338   @param  RefreshRate           The refresh rate of the monitor in Hertz.
339 
340   @retval EFI_SUCCESS           Mode information returned.
341   @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
342   @retval EFI_INVALID_PARAMETER One of the input args was NULL.
343 
344 **/
345 EFI_STATUS
346 EFIAPI
ConSplitterUgaDrawGetMode(IN EFI_UGA_DRAW_PROTOCOL * This,OUT UINT32 * HorizontalResolution,OUT UINT32 * VerticalResolution,OUT UINT32 * ColorDepth,OUT UINT32 * RefreshRate)347 ConSplitterUgaDrawGetMode (
348   IN  EFI_UGA_DRAW_PROTOCOL           *This,
349   OUT UINT32                          *HorizontalResolution,
350   OUT UINT32                          *VerticalResolution,
351   OUT UINT32                          *ColorDepth,
352   OUT UINT32                          *RefreshRate
353   )
354 {
355   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
356 
357   if ((HorizontalResolution == NULL) ||
358       (VerticalResolution   == NULL) ||
359       (RefreshRate          == NULL) ||
360       (ColorDepth           == NULL)) {
361     return EFI_INVALID_PARAMETER;
362   }
363   //
364   // retrieve private data
365   //
366   Private               = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
367 
368   *HorizontalResolution = Private->UgaHorizontalResolution;
369   *VerticalResolution   = Private->UgaVerticalResolution;
370   *ColorDepth           = Private->UgaColorDepth;
371   *RefreshRate          = Private->UgaRefreshRate;
372 
373   return EFI_SUCCESS;
374 }
375 
376 
377 /**
378   Set the current video mode information.
379 
380   @param  This                 The EFI_UGA_DRAW_PROTOCOL instance.
381   @param  HorizontalResolution The size of video screen in pixels in the X dimension.
382   @param  VerticalResolution   The size of video screen in pixels in the Y dimension.
383   @param  ColorDepth           Number of bits per pixel, currently defined to be 32.
384   @param  RefreshRate          The refresh rate of the monitor in Hertz.
385 
386   @retval EFI_SUCCESS          Mode information returned.
387   @retval EFI_NOT_STARTED      Video display is not initialized. Call SetMode ()
388   @retval EFI_OUT_OF_RESOURCES Out of resources.
389 
390 **/
391 EFI_STATUS
392 EFIAPI
ConSplitterUgaDrawSetMode(IN EFI_UGA_DRAW_PROTOCOL * This,IN UINT32 HorizontalResolution,IN UINT32 VerticalResolution,IN UINT32 ColorDepth,IN UINT32 RefreshRate)393 ConSplitterUgaDrawSetMode (
394   IN  EFI_UGA_DRAW_PROTOCOL           *This,
395   IN UINT32                           HorizontalResolution,
396   IN UINT32                           VerticalResolution,
397   IN UINT32                           ColorDepth,
398   IN UINT32                           RefreshRate
399   )
400 {
401   EFI_STATUS                             Status;
402   TEXT_OUT_SPLITTER_PRIVATE_DATA         *Private;
403   UINTN                                  Index;
404   EFI_STATUS                             ReturnStatus;
405   EFI_GRAPHICS_OUTPUT_PROTOCOL           *GraphicsOutput;
406   UINTN                                  NumberIndex;
407   UINTN                                  SizeOfInfo;
408   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   *Info;
409   EFI_UGA_DRAW_PROTOCOL                  *UgaDraw;
410 
411   Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
412 
413   ReturnStatus = EFI_SUCCESS;
414 
415   //
416   // Update the Mode data
417   //
418   Private->UgaHorizontalResolution  = HorizontalResolution;
419   Private->UgaVerticalResolution    = VerticalResolution;
420   Private->UgaColorDepth            = ColorDepth;
421   Private->UgaRefreshRate           = RefreshRate;
422 
423   //
424   // return the worst status met
425   //
426   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
427 
428     GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
429     if (GraphicsOutput != NULL) {
430       //
431       // Find corresponding ModeNumber of this GraphicsOutput instance
432       //
433       for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) {
434         Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info);
435         if (EFI_ERROR (Status)) {
436           return Status;
437         }
438         if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
439           FreePool (Info);
440           break;
441         }
442         FreePool (Info);
443       }
444 
445       Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex);
446       if (EFI_ERROR (Status)) {
447         ReturnStatus = Status;
448       }
449     } else if (FeaturePcdGet (PcdUgaConsumeSupport)){
450       UgaDraw = Private->TextOutList[Index].UgaDraw;
451       if (UgaDraw != NULL) {
452         Status = UgaDraw->SetMode (
453                           UgaDraw,
454                           HorizontalResolution,
455                           VerticalResolution,
456                           ColorDepth,
457                           RefreshRate
458                           );
459         if (EFI_ERROR (Status)) {
460           ReturnStatus = Status;
461         }
462       }
463     }
464   }
465 
466   return ReturnStatus;
467 }
468 
469 
470 /**
471   Blt a rectangle of pixels on the graphics screen.
472 
473   The following table defines actions for BltOperations.
474 
475   EfiUgaVideoFill:
476     Write data from the  BltBuffer pixel (SourceX, SourceY)
477     directly to every pixel of the video display rectangle
478     (DestinationX, DestinationY)
479     (DestinationX + Width, DestinationY + Height).
480     Only one pixel will be used from the BltBuffer. Delta is NOT used.
481   EfiUgaVideoToBltBuffer:
482     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   EfiUgaBltBufferToVideo:
489     Write data from the  BltBuffer rectangle
490     (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
491     video display rectangle (DestinationX, DestinationY)
492     (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
493     not zero then Delta must be set to the length in bytes of a row in the
494     BltBuffer.
495   EfiUgaVideoToVideo:
496     Copy from the video display rectangle
497     (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
498     to the video display rectangle (DestinationX, DestinationY)
499     (DestinationX + Width, DestinationY + Height).
500     The BltBuffer and Delta  are not used in this mode.
501 
502   @param  This           Protocol instance pointer.
503   @param  BltBuffer      Buffer containing data to blit into video buffer. This
504                          buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
505   @param  BltOperation   Operation to perform on BlitBuffer and video memory
506   @param  SourceX        X coordinate of source for the BltBuffer.
507   @param  SourceY        Y coordinate of source for the BltBuffer.
508   @param  DestinationX   X coordinate of destination for the BltBuffer.
509   @param  DestinationY   Y coordinate of destination for the BltBuffer.
510   @param  Width          Width of rectangle in BltBuffer in pixels.
511   @param  Height         Hight of rectangle in BltBuffer in pixels.
512   @param  Delta          OPTIONAL
513 
514   @retval EFI_SUCCESS            The Blt operation completed.
515   @retval EFI_INVALID_PARAMETER  BltOperation is not valid.
516   @retval EFI_DEVICE_ERROR       A hardware error occurred writting to the video buffer.
517 
518 **/
519 EFI_STATUS
520 EFIAPI
ConSplitterUgaDrawBlt(IN EFI_UGA_DRAW_PROTOCOL * This,IN EFI_UGA_PIXEL * BltBuffer,OPTIONAL IN EFI_UGA_BLT_OPERATION BltOperation,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)521 ConSplitterUgaDrawBlt (
522   IN  EFI_UGA_DRAW_PROTOCOL                         *This,
523   IN  EFI_UGA_PIXEL                                 *BltBuffer, OPTIONAL
524   IN  EFI_UGA_BLT_OPERATION                         BltOperation,
525   IN  UINTN                                         SourceX,
526   IN  UINTN                                         SourceY,
527   IN  UINTN                                         DestinationX,
528   IN  UINTN                                         DestinationY,
529   IN  UINTN                                         Width,
530   IN  UINTN                                         Height,
531   IN  UINTN                                         Delta         OPTIONAL
532   )
533 {
534   EFI_STATUS                      Status;
535   TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private;
536   UINTN                           Index;
537   EFI_STATUS                      ReturnStatus;
538   EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
539 
540   Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
541 
542   ReturnStatus = EFI_SUCCESS;
543   //
544   // return the worst status met
545   //
546   for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
547     GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
548     if (GraphicsOutput != NULL) {
549       Status = GraphicsOutput->Blt (
550                               GraphicsOutput,
551                               (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer,
552                               (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation,
553                               SourceX,
554                               SourceY,
555                               DestinationX,
556                               DestinationY,
557                               Width,
558                               Height,
559                               Delta
560                               );
561       if (EFI_ERROR (Status)) {
562         ReturnStatus = Status;
563       } else if (BltOperation == EfiUgaVideoToBltBuffer) {
564         //
565         // Only need to read the data into buffer one time
566         //
567         return EFI_SUCCESS;
568       }
569     }
570 
571     if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
572       Status = Private->TextOutList[Index].UgaDraw->Blt (
573                                                       Private->TextOutList[Index].UgaDraw,
574                                                       BltBuffer,
575                                                       BltOperation,
576                                                       SourceX,
577                                                       SourceY,
578                                                       DestinationX,
579                                                       DestinationY,
580                                                       Width,
581                                                       Height,
582                                                       Delta
583                                                       );
584       if (EFI_ERROR (Status)) {
585         ReturnStatus = Status;
586       } else if (BltOperation == EfiUgaVideoToBltBuffer) {
587         //
588         // Only need to read the data into buffer one time
589         //
590         return EFI_SUCCESS;
591       }
592     }
593   }
594 
595   return ReturnStatus;
596 }
597 
598 /**
599   Sets the output device(s) to a specified mode.
600 
601   @param  Private                 Text Out Splitter pointer.
602   @param  ModeNumber              The mode number to set.
603 
604 **/
605 VOID
TextOutSetMode(IN TEXT_OUT_SPLITTER_PRIVATE_DATA * Private,IN UINTN ModeNumber)606 TextOutSetMode (
607   IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private,
608   IN  UINTN                           ModeNumber
609   )
610 {
611   //
612   // No need to do extra check here as whether (Column, Row) is valid has
613   // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should
614   // always be supported.
615   //
616   Private->TextOutMode.Mode          = (INT32) ModeNumber;
617   Private->TextOutMode.CursorColumn  = 0;
618   Private->TextOutMode.CursorRow     = 0;
619   Private->TextOutMode.CursorVisible = TRUE;
620 
621   return;
622 }
623