]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.c
MdeModulePkg/FrameBufferBltLib: Fix copying of unaligned memory
[mirror_edk2.git] / MdeModulePkg / Library / FrameBufferBltLib / FrameBufferBltLib.c
index c9bb206ee8d02985eae1ba0228ab4308f3c99d88..78dc0c0b510cf1aef148a0a54ff8e8489cc5f5bb 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   FrameBufferBltLib - Library to perform blt operations on a frame buffer.\r
 \r
-  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 #include <Library/FrameBufferBltLib.h>\r
 \r
 struct FRAME_BUFFER_CONFIGURE {\r
-  UINTN                           ColorDepth;\r
-  UINTN                           WidthInBytes;\r
-  UINTN                           BytesPerPixel;\r
-  UINTN                           WidthInPixels;\r
-  UINTN                           Height;\r
-  UINT8                           LineBuffer[SIZE_4KB * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)];\r
+  UINT32                          PixelsPerScanLine;\r
+  UINT32                          BytesPerPixel;\r
+  UINT32                          Width;\r
+  UINT32                          Height;\r
   UINT8                           *FrameBuffer;\r
   EFI_GRAPHICS_PIXEL_FORMAT       PixelFormat;\r
   EFI_PIXEL_BITMASK               PixelMasks;\r
-  INTN                            PixelShl[4]; // R-G-B-Rsvd\r
-  INTN                            PixelShr[4]; // R-G-B-Rsvd\r
+  INT8                            PixelShl[4]; // R-G-B-Rsvd\r
+  INT8                            PixelShr[4]; // R-G-B-Rsvd\r
+  UINT8                           LineBuffer[0];\r
 };\r
 \r
 CONST EFI_PIXEL_BITMASK mRgbPixelMasks = {\r
@@ -45,43 +44,47 @@ CONST EFI_PIXEL_BITMASK mBgrPixelMasks = {
 /**\r
   Initialize the bit mask in frame buffer configure.\r
 \r
-  @param Configure  The frame buffer configure.\r
-  @param BitMask    The bit mask of pixel.\r
+  @param BitMask       The bit mask of pixel.\r
+  @param BytesPerPixel Size in bytes of pixel.\r
+  @param PixelShl      Left shift array.\r
+  @param PixelShr      Right shift array.\r
 **/\r
 VOID\r
-ConfigurePixelBitMaskFormat (\r
-  IN FRAME_BUFFER_CONFIGURE     *Configure,\r
-  IN CONST EFI_PIXEL_BITMASK    *BitMask\r
+FrameBufferBltLibConfigurePixelFormat (\r
+  IN CONST EFI_PIXEL_BITMASK    *BitMask,\r
+  OUT UINT32                    *BytesPerPixel,\r
+  OUT INT8                      *PixelShl,\r
+  OUT INT8                      *PixelShr\r
   )\r
 {\r
-  UINTN   Loop;\r
+  UINT8   Index;\r
   UINT32  *Masks;\r
   UINT32  MergedMasks;\r
 \r
+  ASSERT (BytesPerPixel != NULL);\r
+\r
   MergedMasks = 0;\r
   Masks = (UINT32*) BitMask;\r
-  for (Loop = 0; Loop < 3; Loop++) {\r
-    ASSERT ((Loop == 3) || (Masks[Loop] != 0));\r
-    ASSERT ((MergedMasks & Masks[Loop]) == 0);\r
-    Configure->PixelShl[Loop] = HighBitSet32 (Masks[Loop]) - 23 + (Loop * 8);\r
-    if (Configure->PixelShl[Loop] < 0) {\r
-      Configure->PixelShr[Loop] = -Configure->PixelShl[Loop];\r
-      Configure->PixelShl[Loop] = 0;\r
+  for (Index = 0; Index < 3; Index++) {\r
+    ASSERT ((MergedMasks & Masks[Index]) == 0);\r
+\r
+    PixelShl[Index] = (INT8) HighBitSet32 (Masks[Index]) - 23 + (Index * 8);\r
+    if (PixelShl[Index] < 0) {\r
+      PixelShr[Index] = -PixelShl[Index];\r
+      PixelShl[Index] = 0;\r
     } else {\r
-      Configure->PixelShr[Loop] = 0;\r
+      PixelShr[Index] = 0;\r
     }\r
-    MergedMasks = (UINT32) (MergedMasks | Masks[Loop]);\r
-    DEBUG ((EFI_D_VERBOSE, "%d: shl:%d shr:%d mask:%x\n", Loop,\r
-            Configure->PixelShl[Loop], Configure->PixelShr[Loop], Masks[Loop]));\r
+    DEBUG ((DEBUG_INFO, "%d: shl:%d shr:%d mask:%x\n", Index,\r
+            PixelShl[Index], PixelShr[Index], Masks[Index]));\r
+\r
+    MergedMasks = (UINT32) (MergedMasks | Masks[Index]);\r
   }\r
   MergedMasks = (UINT32) (MergedMasks | Masks[3]);\r
 \r
   ASSERT (MergedMasks != 0);\r
-  Configure->BytesPerPixel = (UINTN) ((HighBitSet32 (MergedMasks) + 7) / 8);\r
-\r
-  DEBUG ((EFI_D_VERBOSE, "Bytes per pixel: %d\n", Configure->BytesPerPixel));\r
-\r
-  CopyMem (&Configure->PixelMasks, BitMask, sizeof (*BitMask));\r
+  *BytesPerPixel = (UINT32) ((HighBitSet32 (MergedMasks) + 7) / 8);\r
+  DEBUG ((DEBUG_INFO, "Bytes per pixel: %d\n", *BytesPerPixel));\r
 }\r
 \r
 /**\r
@@ -110,30 +113,26 @@ FrameBufferBltConfigure (
   IN OUT UINTN                                 *ConfigureSize\r
   )\r
 {\r
-  if (ConfigureSize == NULL) {\r
-    return RETURN_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)) {\r
-    *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE);\r
-    return RETURN_BUFFER_TOO_SMALL;\r
-  }\r
+  CONST EFI_PIXEL_BITMASK                      *BitMask;\r
+  UINT32                                       BytesPerPixel;\r
+  INT8                                         PixelShl[4];\r
+  INT8                                         PixelShr[4];\r
 \r
-  if (Configure == NULL) {\r
+  if (ConfigureSize == NULL) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
   switch (FrameBufferInfo->PixelFormat) {\r
   case PixelRedGreenBlueReserved8BitPerColor:\r
-    ConfigurePixelBitMaskFormat (Configure, &mRgbPixelMasks);\r
+    BitMask = &mRgbPixelMasks;\r
     break;\r
 \r
   case PixelBlueGreenRedReserved8BitPerColor:\r
-    ConfigurePixelBitMaskFormat (Configure, &mBgrPixelMasks);\r
+    BitMask = &mBgrPixelMasks;\r
     break;\r
 \r
   case PixelBitMask:\r
-    ConfigurePixelBitMaskFormat (Configure, &(FrameBufferInfo->PixelInformation));\r
+    BitMask = &FrameBufferInfo->PixelInformation;\r
     break;\r
 \r
   case PixelBltOnly:\r
@@ -145,13 +144,32 @@ FrameBufferBltConfigure (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  Configure->PixelFormat   = FrameBufferInfo->PixelFormat;\r
-  Configure->FrameBuffer   = (UINT8*) FrameBuffer;\r
-  Configure->WidthInPixels = (UINTN) FrameBufferInfo->HorizontalResolution;\r
-  Configure->Height        = (UINTN) FrameBufferInfo->VerticalResolution;\r
-  Configure->WidthInBytes  = Configure->WidthInPixels * Configure->BytesPerPixel;\r
+  if (FrameBufferInfo->PixelsPerScanLine < FrameBufferInfo->HorizontalResolution) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  FrameBufferBltLibConfigurePixelFormat (BitMask, &BytesPerPixel, PixelShl, PixelShr);\r
+\r
+  if (*ConfigureSize < sizeof (FRAME_BUFFER_CONFIGURE)\r
+                     + FrameBufferInfo->HorizontalResolution * BytesPerPixel) {\r
+    *ConfigureSize = sizeof (FRAME_BUFFER_CONFIGURE)\r
+                   + FrameBufferInfo->HorizontalResolution * BytesPerPixel;\r
+    return RETURN_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  if (Configure == NULL) {\r
+    return RETURN_INVALID_PARAMETER;\r
+  }\r
 \r
-  ASSERT (Configure->WidthInBytes < sizeof (Configure->LineBuffer));\r
+  CopyMem (&Configure->PixelMasks, BitMask,  sizeof (*BitMask));\r
+  CopyMem (Configure->PixelShl,    PixelShl, sizeof (PixelShl));\r
+  CopyMem (Configure->PixelShr,    PixelShr, sizeof (PixelShr));\r
+  Configure->BytesPerPixel     = BytesPerPixel;\r
+  Configure->PixelFormat       = FrameBufferInfo->PixelFormat;\r
+  Configure->FrameBuffer       = (UINT8*) FrameBuffer;\r
+  Configure->Width             = FrameBufferInfo->HorizontalResolution;\r
+  Configure->Height            = FrameBufferInfo->VerticalResolution;\r
+  Configure->PixelsPerScanLine = FrameBufferInfo->PixelsPerScanLine;\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -201,7 +219,7 @@ FrameBufferBltLibVideoFill (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  if (DestinationX + Width > Configure->WidthInPixels) {\r
+  if (DestinationX + Width > Configure->Width) {\r
     DEBUG ((EFI_D_VERBOSE, "VideoFill: Past screen (X)\n"));\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
@@ -254,14 +272,15 @@ FrameBufferBltLibVideoFill (
     }\r
   }\r
 \r
-  if (UseWideFill && (DestinationX == 0) && (Width == Configure->WidthInPixels)) {\r
+  if (UseWideFill && (DestinationX == 0) && (Width == Configure->PixelsPerScanLine)) {\r
     DEBUG ((EFI_D_VERBOSE, "VideoFill (wide, one-shot)\n"));\r
-    Offset = DestinationY * Configure->WidthInPixels;\r
+    Offset = DestinationY * Configure->PixelsPerScanLine;\r
     Offset = Configure->BytesPerPixel * Offset;\r
     Destination = Configure->FrameBuffer + Offset;\r
     SizeInBytes = WidthInBytes * Height;\r
     if (SizeInBytes >= 8) {\r
       SetMem32 (Destination, SizeInBytes & ~3, (UINT32) WideFill);\r
+      Destination += SizeInBytes & ~3;\r
       SizeInBytes &= 3;\r
     }\r
     if (SizeInBytes > 0) {\r
@@ -270,7 +289,7 @@ FrameBufferBltLibVideoFill (
   } else {\r
     LineBufferReady = FALSE;\r
     for (IndexY = DestinationY; IndexY < (Height + DestinationY); IndexY++) {\r
-      Offset = (IndexY * Configure->WidthInPixels) + DestinationX;\r
+      Offset = (IndexY * Configure->PixelsPerScanLine) + DestinationX;\r
       Offset = Configure->BytesPerPixel * Offset;\r
       Destination = Configure->FrameBuffer + Offset;\r
 \r
@@ -279,6 +298,7 @@ FrameBufferBltLibVideoFill (
         SizeInBytes = WidthInBytes;\r
         if (SizeInBytes >= 8) {\r
           SetMem64 (Destination, SizeInBytes & ~7, WideFill);\r
+          Destination += SizeInBytes & ~7;\r
           SizeInBytes &= 7;\r
         }\r
         if (SizeInBytes > 0) {\r
@@ -354,7 +374,7 @@ FrameBufferBltLibVideoToBltBuffer (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  if (SourceX + Width > Configure->WidthInPixels) {\r
+  if (SourceX + Width > Configure->Width) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
@@ -380,7 +400,7 @@ FrameBufferBltLibVideoToBltBuffer (
        DstY < (Height + DestinationY);\r
        SrcY++, DstY++) {\r
 \r
-    Offset = (SrcY * Configure->WidthInPixels) + SourceX;\r
+    Offset = (SrcY * Configure->PixelsPerScanLine) + SourceX;\r
     Offset = Configure->BytesPerPixel * Offset;\r
     Source = Configure->FrameBuffer + Offset;\r
 \r
@@ -462,7 +482,7 @@ FrameBufferBltLibBufferToVideo (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  if (DestinationX + Width > Configure->WidthInPixels) {\r
+  if (DestinationX + Width > Configure->Width) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
@@ -485,7 +505,7 @@ FrameBufferBltLibBufferToVideo (
        SrcY < (Height + SourceY);\r
        SrcY++, DstY++) {\r
 \r
-    Offset = (DstY * Configure->WidthInPixels) + DestinationX;\r
+    Offset = (DstY * Configure->PixelsPerScanLine) + DestinationX;\r
     Offset = Configure->BytesPerPixel * Offset;\r
     Destination = Configure->FrameBuffer + Offset;\r
 \r
@@ -558,7 +578,7 @@ FrameBufferBltLibVideoToVideo (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  if (SourceX + Width > Configure->WidthInPixels) {\r
+  if (SourceX + Width > Configure->Width) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
@@ -566,7 +586,7 @@ FrameBufferBltLibVideoToVideo (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
-  if (DestinationX + Width > Configure->WidthInPixels) {\r
+  if (DestinationX + Width > Configure->Width) {\r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
@@ -576,15 +596,15 @@ FrameBufferBltLibVideoToVideo (
 \r
   WidthInBytes = Width * Configure->BytesPerPixel;\r
 \r
-  Offset = (SourceY * Configure->WidthInPixels) + SourceX;\r
+  Offset = (SourceY * Configure->PixelsPerScanLine) + SourceX;\r
   Offset = Configure->BytesPerPixel * Offset;\r
   Source = Configure->FrameBuffer + Offset;\r
 \r
-  Offset = (DestinationY * Configure->WidthInPixels) + DestinationX;\r
+  Offset = (DestinationY * Configure->PixelsPerScanLine) + DestinationX;\r
   Offset = Configure->BytesPerPixel * Offset;\r
   Destination = Configure->FrameBuffer + Offset;\r
 \r
-  LineStride = Configure->WidthInBytes;\r
+  LineStride = Configure->BytesPerPixel * Configure->PixelsPerScanLine;\r
   if (Destination > Source) {\r
     //\r
     // Copy from last line to avoid source is corrupted by copying\r