1 /** @file
2 
3  Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
4  SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6  **/
7 
8 #include <PiDxe.h>
9 #include <Library/BaseMemoryLib.h>
10 #include <Library/DevicePathLib.h>
11 #include <Library/UefiBootServicesTableLib.h>
12 #include <Library/UefiRuntimeServicesTableLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 
15 #include <Guid/GlobalVariable.h>
16 
17 #include "LcdGraphicsOutputDxe.h"
18 
19 extern BOOLEAN mDisplayInitialized;
20 
21 //
22 // Function Definitions
23 //
24 
25 STATIC
26 EFI_STATUS
VideoCopyNoHorizontalOverlap(IN UINTN BitsPerPixel,IN volatile VOID * FrameBufferBase,IN UINT32 HorizontalResolution,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height)27 VideoCopyNoHorizontalOverlap (
28   IN UINTN          BitsPerPixel,
29   IN volatile VOID  *FrameBufferBase,
30   IN UINT32         HorizontalResolution,
31   IN UINTN          SourceX,
32   IN UINTN          SourceY,
33   IN UINTN          DestinationX,
34   IN UINTN          DestinationY,
35   IN UINTN          Width,
36   IN UINTN          Height
37 )
38 {
39   EFI_STATUS    Status = EFI_SUCCESS;
40   UINTN         SourceLine;
41   UINTN         DestinationLine;
42   UINTN         WidthInBytes;
43   UINTN         LineCount;
44   INTN          Step;
45   VOID          *SourceAddr;
46   VOID          *DestinationAddr;
47 
48   if( DestinationY <= SourceY ) {
49     // scrolling up (or horizontally but without overlap)
50     SourceLine       = SourceY;
51     DestinationLine  = DestinationY;
52     Step             = 1;
53   } else {
54     // scrolling down
55     SourceLine       = SourceY + Height;
56     DestinationLine  = DestinationY + Height;
57     Step             = -1;
58   }
59 
60   switch (BitsPerPixel) {
61 
62   case LCD_BITS_PER_PIXEL_24:
63 
64     WidthInBytes = Width * 4;
65 
66     for( LineCount = 0; LineCount < Height; LineCount++ ) {
67       // Update the start addresses of source & destination using 32bit pointer arithmetic
68       SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
69       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
70 
71       // Copy the entire line Y from video ram to the temp buffer
72       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
73 
74       // Update the line numbers
75       SourceLine      += Step;
76       DestinationLine += Step;
77     }
78     break;
79 
80   case LCD_BITS_PER_PIXEL_16_555:
81   case LCD_BITS_PER_PIXEL_16_565:
82   case LCD_BITS_PER_PIXEL_12_444:
83 
84     WidthInBytes = Width * 2;
85 
86     for( LineCount = 0; LineCount < Height; LineCount++ ) {
87       // Update the start addresses of source & destination using 16bit pointer arithmetic
88       SourceAddr      = (VOID *)((UINT16 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
89       DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
90 
91       // Copy the entire line Y from video ram to the temp buffer
92       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
93 
94       // Update the line numbers
95       SourceLine      += Step;
96       DestinationLine += Step;
97     }
98     break;
99 
100   case LCD_BITS_PER_PIXEL_8:
101   case LCD_BITS_PER_PIXEL_4:
102   case LCD_BITS_PER_PIXEL_2:
103   case LCD_BITS_PER_PIXEL_1:
104   default:
105     // Can't handle this case
106     DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
107     Status = EFI_INVALID_PARAMETER;
108     goto EXIT;
109     // break;
110 
111   }
112 
113   EXIT:
114   return Status;
115 }
116 
117 STATIC
118 EFI_STATUS
VideoCopyHorizontalOverlap(IN UINTN BitsPerPixel,IN volatile VOID * FrameBufferBase,UINT32 HorizontalResolution,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height)119 VideoCopyHorizontalOverlap (
120   IN UINTN          BitsPerPixel,
121   IN volatile VOID  *FrameBufferBase,
122   UINT32            HorizontalResolution,
123   IN UINTN          SourceX,
124   IN UINTN          SourceY,
125   IN UINTN          DestinationX,
126   IN UINTN          DestinationY,
127   IN UINTN          Width,
128   IN UINTN          Height
129 )
130 {
131   EFI_STATUS      Status = EFI_SUCCESS;
132 
133   UINT32 *PixelBuffer32bit;
134   UINT32 *SourcePixel32bit;
135   UINT32 *DestinationPixel32bit;
136 
137   UINT16 *PixelBuffer16bit;
138   UINT16 *SourcePixel16bit;
139   UINT16 *DestinationPixel16bit;
140 
141   UINT32          SourcePixelY;
142   UINT32          DestinationPixelY;
143   UINTN           SizeIn32Bits;
144   UINTN           SizeIn16Bits;
145 
146   switch (BitsPerPixel) {
147 
148   case LCD_BITS_PER_PIXEL_24:
149     // Allocate a temporary buffer
150 
151     PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
152 
153     if (PixelBuffer32bit == NULL) {
154       Status = EFI_OUT_OF_RESOURCES;
155       goto EXIT;
156     }
157 
158     SizeIn32Bits = Width * 4;
159 
160     // Copy from the video ram (source region) to a temp buffer
161     for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
162          SourcePixelY < SourceY + Height;
163          SourcePixelY++, DestinationPixel32bit += Width)
164     {
165       // Update the start address of line Y (source)
166       SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
167 
168       // Copy the entire line Y from video ram to the temp buffer
169       CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
170     }
171 
172     // Copy from the temp buffer to the video ram (destination region)
173     for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
174          DestinationPixelY < DestinationY + Height;
175          DestinationPixelY++, SourcePixel32bit += Width)
176     {
177       // Update the start address of line Y (target)
178       DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
179 
180       // Copy the entire line Y from the temp buffer to video ram
181       CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
182     }
183 
184     // Free up the allocated memory
185     FreePool((VOID *) PixelBuffer32bit);
186 
187     break;
188 
189 
190   case LCD_BITS_PER_PIXEL_16_555:
191   case LCD_BITS_PER_PIXEL_16_565:
192   case LCD_BITS_PER_PIXEL_12_444:
193     // Allocate a temporary buffer
194     PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
195 
196     if (PixelBuffer16bit == NULL) {
197       Status = EFI_OUT_OF_RESOURCES;
198       goto EXIT;
199     }
200 
201     // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
202 
203     SizeIn16Bits = Width * 2;
204 
205     for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
206          SourcePixelY < SourceY + Height;
207          SourcePixelY++, DestinationPixel16bit += Width)
208     {
209       // Calculate the source address:
210       SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
211 
212       // Copy the entire line Y from Video to the temp buffer
213       CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
214     }
215 
216     // Copy from the temp buffer into the destination area of the Video Memory
217 
218     for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
219          DestinationPixelY < DestinationY + Height;
220          DestinationPixelY++, SourcePixel16bit += Width)
221     {
222       // Calculate the target address:
223       DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
224 
225       // Copy the entire line Y from the temp buffer to Video
226       CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
227     }
228 
229     // Free the allocated memory
230     FreePool((VOID *) PixelBuffer16bit);
231 
232     break;
233 
234 
235   case LCD_BITS_PER_PIXEL_8:
236   case LCD_BITS_PER_PIXEL_4:
237   case LCD_BITS_PER_PIXEL_2:
238   case LCD_BITS_PER_PIXEL_1:
239   default:
240     // Can't handle this case
241     DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
242     Status = EFI_INVALID_PARAMETER;
243     goto EXIT;
244     // break;
245 
246   }
247 
248 EXIT:
249   return Status;
250 }
251 
252 STATIC
253 EFI_STATUS
BltVideoFill(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * EfiSourcePixel,OPTIONAL IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)254 BltVideoFill (
255   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
256   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *EfiSourcePixel,     OPTIONAL
257   IN UINTN                               SourceX,
258   IN UINTN                               SourceY,
259   IN UINTN                               DestinationX,
260   IN UINTN                               DestinationY,
261   IN UINTN                               Width,
262   IN UINTN                               Height,
263   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
264   )
265 {
266   EFI_PIXEL_BITMASK*  PixelInformation;
267   EFI_STATUS         Status;
268   UINT32             HorizontalResolution;
269   LCD_BPP            BitsPerPixel;
270   VOID            *FrameBufferBase;
271   VOID            *DestinationAddr;
272   UINT16          *DestinationPixel16bit;
273   UINT16          Pixel16bit;
274   UINT32          DestinationPixelX;
275   UINT32          DestinationLine;
276   UINTN           WidthInBytes;
277 
278   Status           = EFI_SUCCESS;
279   PixelInformation = &This->Mode->Info->PixelInformation;
280   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
281   HorizontalResolution = This->Mode->Info->HorizontalResolution;
282 
283   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
284 
285   switch (BitsPerPixel) {
286   case LCD_BITS_PER_PIXEL_24:
287     WidthInBytes = Width * 4;
288 
289     // Copy the SourcePixel into every pixel inside the target rectangle
290     for (DestinationLine = DestinationY;
291          DestinationLine < DestinationY + Height;
292          DestinationLine++)
293     {
294       // Calculate the target address using 32bit pointer arithmetic:
295       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationX);
296 
297       // Fill the entire line
298       SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));
299     }
300     break;
301 
302   case LCD_BITS_PER_PIXEL_16_555:
303     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
304     Pixel16bit = (UINT16) (
305         ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
306       | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
307       | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
308 //      | ( 0                           & PixelInformation->ReservedMask )
309      );
310 
311     // Copy the SourcePixel into every pixel inside the target rectangle
312     for (DestinationLine = DestinationY;
313          DestinationLine < DestinationY + Height;
314          DestinationLine++)
315     {
316       for (DestinationPixelX = DestinationX;
317            DestinationPixelX < DestinationX + Width;
318            DestinationPixelX++)
319       {
320         // Calculate the target address:
321         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
322 
323         // Copy the pixel into the new target
324         *DestinationPixel16bit = Pixel16bit;
325       }
326     }
327     break;
328 
329   case LCD_BITS_PER_PIXEL_16_565:
330     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
331     Pixel16bit = (UINT16) (
332         ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
333       | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
334       | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
335      );
336 
337     // Copy the SourcePixel into every pixel inside the target rectangle
338     for (DestinationLine = DestinationY;
339          DestinationLine < DestinationY + Height;
340          DestinationLine++)
341     {
342       for (DestinationPixelX = DestinationX;
343            DestinationPixelX < DestinationX + Width;
344            DestinationPixelX++)
345       {
346         // Calculate the target address:
347         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
348 
349         // Copy the pixel into the new target
350         *DestinationPixel16bit = Pixel16bit;
351       }
352     }
353     break;
354 
355   case LCD_BITS_PER_PIXEL_12_444:
356     // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
357     Pixel16bit = (UINT16) (
358         ( (EfiSourcePixel->Red      >> 4) & PixelInformation->RedMask      )
359       | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
360       | ( (EfiSourcePixel->Blue     << 4) & PixelInformation->BlueMask     )
361      );
362 
363     // Copy the SourcePixel into every pixel inside the target rectangle
364     for (DestinationLine = DestinationY;
365          DestinationLine < DestinationY + Height;
366          DestinationLine++)
367     {
368       for (DestinationPixelX = DestinationX;
369            DestinationPixelX < DestinationX + Width;
370            DestinationPixelX++)
371       {
372         // Calculate the target address:
373         DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
374 
375         // Copy the pixel into the new target
376         *DestinationPixel16bit = Pixel16bit;
377       }
378     }
379     break;
380 
381   case LCD_BITS_PER_PIXEL_8:
382   case LCD_BITS_PER_PIXEL_4:
383   case LCD_BITS_PER_PIXEL_2:
384   case LCD_BITS_PER_PIXEL_1:
385   default:
386     // Can't handle this case
387     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
388     Status = EFI_INVALID_PARAMETER;
389     break;
390   }
391 
392   return Status;
393 }
394 
395 STATIC
396 EFI_STATUS
BltVideoToBltBuffer(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)397 BltVideoToBltBuffer (
398   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
399   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
400   IN UINTN                               SourceX,
401   IN UINTN                               SourceY,
402   IN UINTN                               DestinationX,
403   IN UINTN                               DestinationY,
404   IN UINTN                               Width,
405   IN UINTN                               Height,
406   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
407   )
408 {
409   EFI_STATUS         Status;
410   UINT32             HorizontalResolution;
411   LCD_BPP            BitsPerPixel;
412   EFI_PIXEL_BITMASK  *PixelInformation;
413   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
414   VOID   *FrameBufferBase;
415   VOID            *SourceAddr;
416   VOID            *DestinationAddr;
417   UINT16 *SourcePixel16bit;
418   UINT16          Pixel16bit;
419   UINT32          SourcePixelX;
420   UINT32          SourceLine;
421   UINT32          DestinationPixelX;
422   UINT32          DestinationLine;
423   UINT32          BltBufferHorizontalResolution;
424   UINTN           WidthInBytes;
425 
426   Status = EFI_SUCCESS;
427   PixelInformation = &This->Mode->Info->PixelInformation;
428   HorizontalResolution = This->Mode->Info->HorizontalResolution;
429   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
430 
431   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
432     // Delta is not zero and it is different from the width.
433     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
434     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
435   } else {
436     BltBufferHorizontalResolution = Width;
437   }
438 
439   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
440 
441   switch (BitsPerPixel) {
442   case LCD_BITS_PER_PIXEL_24:
443     WidthInBytes = Width * 4;
444 
445     // Access each line inside the Video Memory
446     for (SourceLine = SourceY, DestinationLine = DestinationY;
447          SourceLine < SourceY + Height;
448          SourceLine++, DestinationLine++)
449     {
450       // Calculate the source and target addresses using 32bit pointer arithmetic:
451       SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution          + SourceX     );
452       DestinationAddr = (VOID *)((UINT32 *)BltBuffer       + DestinationLine * BltBufferHorizontalResolution + DestinationX);
453 
454       // Copy the entire line
455       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
456     }
457     break;
458 
459   case LCD_BITS_PER_PIXEL_16_555:
460     // Access each pixel inside the Video Memory
461     for (SourceLine = SourceY, DestinationLine = DestinationY;
462          SourceLine < SourceY + Height;
463          SourceLine++, DestinationLine++)
464     {
465       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
466            SourcePixelX < SourceX + Width;
467            SourcePixelX++, DestinationPixelX++)
468       {
469         // Calculate the source and target addresses:
470         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
471         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
472 
473         // Snapshot the pixel from the video buffer once, to speed up the operation.
474         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
475         Pixel16bit = *SourcePixel16bit;
476 
477         // Copy the pixel into the new target
478         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >>  7 );
479         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >>  2);
480         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) <<  3 );
481         // EfiDestinationPixel->Reserved = (UINT8) 0;
482       }
483     }
484     break;
485 
486   case LCD_BITS_PER_PIXEL_16_565:
487     // Access each pixel inside the Video Memory
488     for (SourceLine = SourceY, DestinationLine = DestinationY;
489          SourceLine < SourceY + Height;
490          SourceLine++, DestinationLine++)
491     {
492       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
493            SourcePixelX < SourceX + Width;
494            SourcePixelX++, DestinationPixelX++)
495       {
496         // Calculate the source and target addresses:
497         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
498         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
499 
500         // Snapshot the pixel from the video buffer once, to speed up the operation.
501         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
502         Pixel16bit = *SourcePixel16bit;
503 
504         // Copy the pixel into the new target
505         // There is no info for the Reserved byte, so we set it to zero
506         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 8 );
507         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >> 3);
508         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 3 );
509         // EfiDestinationPixel->Reserved = (UINT8) 0;
510       }
511     }
512     break;
513 
514   case LCD_BITS_PER_PIXEL_12_444:
515     // Access each pixel inside the Video Memory
516     for (SourceLine = SourceY, DestinationLine = DestinationY;
517          SourceLine < SourceY + Height;
518          SourceLine++, DestinationLine++)
519     {
520       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
521            SourcePixelX < SourceX + Width;
522            SourcePixelX++, DestinationPixelX++)
523       {
524         // Calculate the source and target addresses:
525         SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
526         EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
527 
528         // Snapshot the pixel from the video buffer once, to speed up the operation.
529         // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
530         Pixel16bit = *SourcePixel16bit;
531 
532         // Copy the pixel into the new target
533         EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 4 );
534         EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   )     );
535         EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 4 );
536         // EfiDestinationPixel->Reserved = (UINT8) 0;
537       }
538     }
539     break;
540 
541   case LCD_BITS_PER_PIXEL_8:
542   case LCD_BITS_PER_PIXEL_4:
543   case LCD_BITS_PER_PIXEL_2:
544   case LCD_BITS_PER_PIXEL_1:
545   default:
546     // Can't handle this case
547     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
548     Status = EFI_INVALID_PARAMETER;
549     break;
550   }
551   return Status;
552 }
553 
554 STATIC
555 EFI_STATUS
BltBufferToVideo(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)556 BltBufferToVideo (
557   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
558   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
559   IN UINTN                               SourceX,
560   IN UINTN                               SourceY,
561   IN UINTN                               DestinationX,
562   IN UINTN                               DestinationY,
563   IN UINTN                               Width,
564   IN UINTN                               Height,
565   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
566   )
567 {
568   EFI_STATUS         Status;
569   UINT32             HorizontalResolution;
570   LCD_BPP            BitsPerPixel;
571   EFI_PIXEL_BITMASK  *PixelInformation;
572   EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
573   VOID   *FrameBufferBase;
574   VOID            *SourceAddr;
575   VOID            *DestinationAddr;
576   UINT16 *DestinationPixel16bit;
577   UINT32          SourcePixelX;
578   UINT32          SourceLine;
579   UINT32          DestinationPixelX;
580   UINT32          DestinationLine;
581   UINT32          BltBufferHorizontalResolution;
582   UINTN           WidthInBytes;
583 
584   Status = EFI_SUCCESS;
585   PixelInformation = &This->Mode->Info->PixelInformation;
586   HorizontalResolution = This->Mode->Info->HorizontalResolution;
587   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
588 
589   if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
590     // Delta is not zero and it is different from the width.
591     // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
592     BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
593   } else {
594     BltBufferHorizontalResolution = Width;
595   }
596 
597   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
598 
599   switch (BitsPerPixel) {
600   case LCD_BITS_PER_PIXEL_24:
601     WidthInBytes = Width * 4;
602 
603     // Access each pixel inside the BltBuffer Memory
604     for (SourceLine = SourceY, DestinationLine = DestinationY;
605        SourceLine < SourceY + Height;
606        SourceLine++, DestinationLine++)
607     {
608       // Calculate the source and target addresses using 32bit pointer arithmetic:
609       SourceAddr      = (VOID *)((UINT32 *)BltBuffer       + SourceLine      * BltBufferHorizontalResolution + SourceX     );
610       DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution          + DestinationX);
611 
612       // Copy the entire row Y
613       CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
614     }
615     break;
616 
617   case LCD_BITS_PER_PIXEL_16_555:
618     // Access each pixel inside the BltBuffer Memory
619     for (SourceLine = SourceY, DestinationLine = DestinationY;
620        SourceLine < SourceY + Height;
621        SourceLine++, DestinationLine++) {
622 
623       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
624            SourcePixelX < SourceX + Width;
625            SourcePixelX++, DestinationPixelX++)
626       {
627         // Calculate the source and target addresses:
628         EfiSourcePixel  = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
629         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
630 
631         // Copy the pixel into the new target
632         // Only the most significant bits will be copied across:
633         // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
634         *DestinationPixel16bit = (UINT16) (
635               ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
636             | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
637             | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
638       //            | ( 0                                & PixelInformation->ReservedMask )
639             );
640       }
641     }
642     break;
643 
644   case LCD_BITS_PER_PIXEL_16_565:
645     // Access each pixel inside the BltBuffer Memory
646     for (SourceLine = SourceY, DestinationLine = DestinationY;
647          SourceLine < SourceY + Height;
648          SourceLine++, DestinationLine++) {
649 
650       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
651            SourcePixelX < SourceX + Width;
652            SourcePixelX++, DestinationPixelX++)
653       {
654         // Calculate the source and target addresses:
655         EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
656         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
657 
658         // Copy the pixel into the new target
659         // Only the most significant bits will be copied across:
660         // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2  least significant bits
661         // There is no room for the Reserved byte so we ignore that completely
662         *DestinationPixel16bit = (UINT16) (
663               ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
664             | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
665             | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
666            );
667       }
668     }
669     break;
670 
671   case LCD_BITS_PER_PIXEL_12_444:
672     // Access each pixel inside the BltBuffer Memory
673     for (SourceLine = SourceY, DestinationLine = DestinationY;
674          SourceLine < SourceY + Height;
675          SourceLine++, DestinationLine++) {
676 
677       for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
678            SourcePixelX < SourceX + Width;
679            SourcePixelX++, DestinationPixelX++)
680       {
681         // Calculate the source and target addresses:
682         EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
683         DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
684 
685         // Copy the pixel into the new target
686         // Only the most significant bits will be copied across:
687         // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
688         *DestinationPixel16bit = (UINT16) (
689               ( (EfiSourcePixel->Red      << 4) & PixelInformation->RedMask      )
690             | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
691             | ( (EfiSourcePixel->Blue     >> 4) & PixelInformation->BlueMask     )
692   //            | ( 0                               & PixelInformation->ReservedMask )
693            );
694       }
695     }
696     break;
697 
698   case LCD_BITS_PER_PIXEL_8:
699   case LCD_BITS_PER_PIXEL_4:
700   case LCD_BITS_PER_PIXEL_2:
701   case LCD_BITS_PER_PIXEL_1:
702   default:
703     // Can't handle this case
704     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
705     Status = EFI_INVALID_PARAMETER;
706     break;
707   }
708   return Status;
709 }
710 
711 STATIC
712 EFI_STATUS
BltVideoToVideo(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta OPTIONAL)713 BltVideoToVideo (
714   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
715   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
716   IN UINTN                               SourceX,
717   IN UINTN                               SourceY,
718   IN UINTN                               DestinationX,
719   IN UINTN                               DestinationY,
720   IN UINTN                               Width,
721   IN UINTN                               Height,
722   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
723   )
724 {
725   EFI_STATUS         Status;
726   UINT32             HorizontalResolution;
727   LCD_BPP            BitsPerPixel;
728   VOID   *FrameBufferBase;
729 
730   HorizontalResolution = This->Mode->Info->HorizontalResolution;
731   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
732 
733   //
734   // BltVideo to BltVideo:
735   //
736   //  Source is the Video Memory,
737   //  Destination is the Video Memory
738 
739   LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
740   FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
741 
742   // The UEFI spec currently states:
743   // "There is no limitation on the overlapping of the source and destination rectangles"
744   // Therefore, we must be careful to avoid overwriting the source data
745   if( SourceY == DestinationY ) {
746     // Copying within the same height, e.g. horizontal shift
747     if( SourceX == DestinationX ) {
748       // Nothing to do
749       Status = EFI_SUCCESS;
750     } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
751       // There is overlap
752       Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
753     } else {
754       // No overlap
755       Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
756     }
757   } else {
758     // Copying from different heights
759     Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
760   }
761 
762   return Status;
763 }
764 
765 /***************************************
766  * GraphicsOutput Protocol function, mapping to
767  * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
768  *
769  * PRESUMES: 1 pixel = 4 bytes (32bits)
770  *  ***************************************/
771 EFI_STATUS
772 EFIAPI
LcdGraphicsBlt(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN OUT 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)773 LcdGraphicsBlt (
774   IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
775   IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
776   IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION   BltOperation,
777   IN UINTN                               SourceX,
778   IN UINTN                               SourceY,
779   IN UINTN                               DestinationX,
780   IN UINTN                               DestinationY,
781   IN UINTN                               Width,
782   IN UINTN                               Height,
783   IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
784   )
785 {
786   EFI_STATUS         Status;
787   UINT32             HorizontalResolution;
788   UINT32             VerticalResolution;
789   LCD_INSTANCE*      Instance;
790 
791   Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
792 
793   // Setup the hardware if not already done
794   if (!mDisplayInitialized) {
795     Status = InitializeDisplay (Instance);
796     if (EFI_ERROR(Status)) {
797       goto EXIT;
798     }
799   }
800 
801   HorizontalResolution = This->Mode->Info->HorizontalResolution;
802   VerticalResolution   = This->Mode->Info->VerticalResolution;
803 
804   DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
805       BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
806 
807   // Check we have reasonable parameters
808   if (Width == 0 || Height == 0) {
809     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
810     Status = EFI_INVALID_PARAMETER;
811     goto EXIT;
812   }
813 
814   if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
815     ASSERT( BltBuffer != NULL);
816   }
817 
818   /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
819     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
820     Status = EFI_INVALID_PARAMETER;
821     goto EXIT;
822   }*/
823 
824   // If we are reading data out of the video buffer, check that the source area is within the display limits
825   if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
826     if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
827       DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
828       DEBUG((DEBUG_INFO, "                      - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
829       DEBUG((DEBUG_INFO, "                      - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
830       Status = EFI_INVALID_PARAMETER;
831       goto EXIT;
832     }
833   }
834 
835   // If we are writing data into the video buffer, that the destination area is within the display limits
836   if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
837     if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
838       DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
839       DEBUG((DEBUG_INFO, "                      - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
840       DEBUG((DEBUG_INFO, "                      - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
841       Status = EFI_INVALID_PARAMETER;
842       goto EXIT;
843     }
844   }
845 
846   //
847   // Perform the Block Transfer Operation
848   //
849 
850   switch (BltOperation) {
851   case EfiBltVideoFill:
852     Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
853     break;
854 
855   case EfiBltVideoToBltBuffer:
856     Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
857     break;
858 
859   case EfiBltBufferToVideo:
860     Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
861     break;
862 
863   case EfiBltVideoToVideo:
864     Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
865     break;
866 
867   case EfiGraphicsOutputBltOperationMax:
868   default:
869     DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
870     Status = EFI_INVALID_PARAMETER;
871     break;
872   }
873 
874 EXIT:
875   return Status;
876 }
877