--- /dev/null
+/** @file\r
+\r
+Provides services to convert a BMP graphics image to a GOP BLT buffer\r
+and to convert a GOP BLT buffer to a BMP graphics image.\r
+\r
+Copyright (c) 2016, Microsoft Corporation\r
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+All rights reserved.\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions are met:\r
+1. Redistributions of source code must retain the above copyright notice,\r
+this list of conditions and the following disclaimer.\r
+2. Redistributions in binary form must reproduce the above copyright notice,\r
+this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+**/\r
+\r
+#ifndef __BMP_SUPPORT_LIB_H__\r
+#define __BMP_SUPPORT_LIB_H__\r
+\r
+#include <Protocol/GraphicsOutput.h>\r
+\r
+/**\r
+ Translate a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
+ is passed in a GopBlt buffer will be allocated by this routine using\r
+ EFI_BOOT_SERVICES.AllocatePool(). If a GopBlt buffer is passed in it will be\r
+ used if it is big enough.\r
+\r
+ @param [in] BmpImage Pointer to BMP file.\r
+ @param [in] BmpImageSize Number of bytes in BmpImage.\r
+ @param [in, out] GopBlt Buffer containing GOP version of BmpImage.\r
+ @param [in, out] GopBltSize Size of GopBlt in bytes.\r
+ @param [out] PixelHeight Height of GopBlt/BmpImage in pixels.\r
+ @param [out] PixelWidth Width of GopBlt/BmpImage in pixels.\r
+\r
+ @retval RETURN_SUCCESS GopBlt and GopBltSize are returned.\r
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.\r
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.\r
+ @retval RETURN_INVALID_PARAMETER GopBltSize is NULL.\r
+ @retval RETURN_INVALID_PARAMETER PixelHeight is NULL.\r
+ @retval RETURN_INVALID_PARAMETER PixelWidth is NULL.\r
+ @retval RETURN_UNSUPPORTED BmpImage is not a valid *.BMP image.\r
+ @retval RETURN_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big\r
+ enough. The required size is returned in\r
+ GopBltSize.\r
+ @retval RETURN_OUT_OF_RESOURCES The GopBlt buffer could not be allocated.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TranslateBmpToGopBlt (\r
+ IN VOID *BmpImage,\r
+ IN UINTN BmpImageSize,\r
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **GopBlt,\r
+ IN OUT UINTN *GopBltSize,\r
+ OUT UINTN *PixelHeight,\r
+ OUT UINTN *PixelWidth\r
+ );\r
+\r
+/**\r
+ Translate a GOP blt buffer to an uncompressed 24-bit per pixel BMP graphics\r
+ image. If a NULL BmpImage is passed in a BmpImage buffer will be allocated by\r
+ this routine using EFI_BOOT_SERVICES.AllocatePool(). If a BmpImage buffer is\r
+ passed in it will be used if it is big enough.\r
+\r
+ @param [in] GopBlt Pointer to GOP blt buffer.\r
+ @param [in] PixelHeight Height of GopBlt/BmpImage in pixels.\r
+ @param [in] PixelWidth Width of GopBlt/BmpImage in pixels.\r
+ @param [in, out] BmpImage Buffer containing BMP version of GopBlt.\r
+ @param [in, out] BmpImageSize Size of BmpImage in bytes.\r
+\r
+ @retval RETURN_SUCCESS BmpImage and BmpImageSize are returned.\r
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.\r
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.\r
+ @retval RETURN_INVALID_PARAMETER BmpImageSize is NULL.\r
+ @retval RETURN_UNSUPPORTED GopBlt cannot be converted to a *.BMP image.\r
+ @retval RETURN_BUFFER_TOO_SMALL The passed in BmpImage buffer is not big\r
+ enough. The required size is returned in\r
+ BmpImageSize.\r
+ @retval RETURN_OUT_OF_RESOURCES The BmpImage buffer could not be allocated.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TranslateGopBltToBmp (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt,\r
+ IN UINT32 PixelHeight,\r
+ IN UINT32 PixelWidth,\r
+ IN OUT VOID **BmpImage,\r
+ IN OUT UINT32 *BmpImageSize\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ Provides services to convert a BMP graphics image to a GOP BLT buffer and\r
+ from a GOP BLT buffer to a BMP graphics image.\r
+\r
+ Caution: This module requires additional review when modified.\r
+ This module processes external input - BMP image.\r
+ This external input must be validated carefully to avoid security issue such\r
+ as buffer overflow, integer overflow.\r
+\r
+ TranslateBmpToGopBlt() receives untrusted input and performs basic validation.\r
+\r
+ Copyright (c) 2016-2017, Microsoft Corporation\r
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+ All rights reserved.\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ 1. Redistributions of source code must retain the above copyright notice,\r
+ this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/SafeIntLib.h>\r
+#include <IndustryStandard/Bmp.h>\r
+\r
+#include <Library/BmpSupportLib.h>\r
+\r
+//\r
+// BMP Image header for an uncompressed 24-bit per pixel BMP image.\r
+//\r
+const BMP_IMAGE_HEADER mBmpImageHeaderTemplate = {\r
+ 'B', // CharB\r
+ 'M', // CharM\r
+ 0, // Size will be updated at runtime\r
+ {0, 0}, // Reserved\r
+ sizeof (BMP_IMAGE_HEADER), // ImageOffset\r
+ sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize\r
+ 0, // PixelWidth will be updated at runtime\r
+ 0, // PixelHeight will be updated at runtime\r
+ 1, // Planes\r
+ 24, // BitPerPixel\r
+ 0, // CompressionType\r
+ 0, // ImageSize will be updated at runtime\r
+ 0, // XPixelsPerMeter\r
+ 0, // YPixelsPerMeter\r
+ 0, // NumberOfColors\r
+ 0 // ImportantColors\r
+};\r
+\r
+/**\r
+ Translate a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
+ is passed in a GopBlt buffer will be allocated by this routine using\r
+ EFI_BOOT_SERVICES.AllocatePool(). If a GopBlt buffer is passed in it will be\r
+ used if it is big enough.\r
+\r
+ @param[in] BmpImage Pointer to BMP file.\r
+ @param[in] BmpImageSize Number of bytes in BmpImage.\r
+ @param[in, out] GopBlt Buffer containing GOP version of BmpImage.\r
+ @param[in, out] GopBltSize Size of GopBlt in bytes.\r
+ @param[out] PixelHeight Height of GopBlt/BmpImage in pixels.\r
+ @param[out] PixelWidth Width of GopBlt/BmpImage in pixels.\r
+\r
+ @retval RETURN_SUCCESS GopBlt and GopBltSize are returned.\r
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.\r
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.\r
+ @retval RETURN_INVALID_PARAMETER GopBltSize is NULL.\r
+ @retval RETURN_INVALID_PARAMETER PixelHeight is NULL.\r
+ @retval RETURN_INVALID_PARAMETER PixelWidth is NULL.\r
+ @retval RETURN_UNSUPPORTED BmpImage is not a valid *.BMP image.\r
+ @retval RETURN_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big\r
+ enough. The required size is returned in\r
+ GopBltSize.\r
+ @retval RETURN_OUT_OF_RESOURCES The GopBlt buffer could not be allocated.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TranslateBmpToGopBlt (\r
+ IN VOID *BmpImage,\r
+ IN UINTN BmpImageSize,\r
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **GopBlt,\r
+ IN OUT UINTN *GopBltSize,\r
+ OUT UINTN *PixelHeight,\r
+ OUT UINTN *PixelWidth\r
+ )\r
+{\r
+ UINT8 *Image;\r
+ UINT8 *ImageHeader;\r
+ BMP_IMAGE_HEADER *BmpHeader;\r
+ BMP_COLOR_MAP *BmpColorMap;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ UINT32 BltBufferSize;\r
+ UINTN Index;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ UINTN ImageIndex;\r
+ UINT32 DataSizePerLine;\r
+ BOOLEAN IsAllocated;\r
+ UINT32 ColorMapNum;\r
+ RETURN_STATUS Status;\r
+ UINT32 DataSize;\r
+ UINT32 Temp;\r
+\r
+ if (BmpImage == NULL || GopBlt == NULL || GopBltSize == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+ if (PixelHeight == NULL || PixelWidth == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BmpImageSize < sizeof (BMP_IMAGE_HEADER)) {\r
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpImageSize too small\n"));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ BmpHeader = (BMP_IMAGE_HEADER *)BmpImage;\r
+\r
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpHeader->Char fields incorrect\n"));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Doesn't support compress.\r
+ //\r
+ if (BmpHeader->CompressionType != 0) {\r
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: Compression Type unsupported.\n"));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Only support BITMAPINFOHEADER format.\r
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER\r
+ //\r
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: BmpHeader->Headership is not as expected. Headersize is 0x%x\n",\r
+ BmpHeader->HeaderSize\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // The data size in each line must be 4 byte alignment.\r
+ //\r
+ Status = SafeUint32Mult (\r
+ BmpHeader->PixelWidth,\r
+ BmpHeader->BitPerPixel,\r
+ &DataSizePerLine\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BmpImage... PixelWidth:0x%x BitPerPixel:0x%x\n",\r
+ BmpHeader->PixelWidth,\r
+ BmpHeader->BitPerPixel\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ Status = SafeUint32Add (DataSizePerLine, 31, &DataSizePerLine);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x\n",\r
+ DataSizePerLine\r
+ ));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ DataSizePerLine = (DataSizePerLine >> 3) &(~0x3);\r
+ Status = SafeUint32Mult (\r
+ DataSizePerLine,\r
+ BmpHeader->PixelHeight,\r
+ &BltBufferSize\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x PixelHeight:0x%x\n",\r
+ DataSizePerLine, BmpHeader->PixelHeight\r
+ ));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ Status = SafeUint32Mult (\r
+ BmpHeader->PixelHeight,\r
+ DataSizePerLine,\r
+ &DataSize\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BmpImage... PixelHeight:0x%x DataSizePerLine:0x%x\n",\r
+ BmpHeader->PixelHeight, DataSizePerLine\r
+ ));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ if ((BmpHeader->Size != BmpImageSize) ||\r
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||\r
+ (BmpHeader->Size - BmpHeader->ImageOffset != DataSize)) {\r
+\r
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: invalid BmpImage... \n"));\r
+ DEBUG ((DEBUG_ERROR, " BmpHeader->Size: 0x%x\n", BmpHeader->Size));\r
+ DEBUG ((DEBUG_ERROR, " BmpHeader->ImageOffset: 0x%x\n", BmpHeader->ImageOffset));\r
+ DEBUG ((DEBUG_ERROR, " BmpImageSize: 0x%lx\n", (UINTN)BmpImageSize));\r
+ DEBUG ((DEBUG_ERROR, " DataSize: 0x%lx\n", (UINTN)DataSize));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Calculate Color Map offset in the image.\r
+ //\r
+ Image = BmpImage;\r
+ BmpColorMap = (BMP_COLOR_MAP *)(Image + sizeof (BMP_IMAGE_HEADER));\r
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ ColorMapNum = 2;\r
+ break;\r
+ case 4:\r
+ ColorMapNum = 16;\r
+ break;\r
+ case 8:\r
+ ColorMapNum = 256;\r
+ break;\r
+ default:\r
+ ColorMapNum = 0;\r
+ break;\r
+ }\r
+ //\r
+ // BMP file may has padding data between the bmp header section and the\r
+ // bmp data section.\r
+ //\r
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Calculate graphics image data address in the image\r
+ //\r
+ Image = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset;\r
+ ImageHeader = Image;\r
+\r
+ //\r
+ // Calculate the BltBuffer needed size.\r
+ //\r
+ Status = SafeUint32Mult (\r
+ BmpHeader->PixelWidth,\r
+ BmpHeader->PixelHeight,\r
+ &BltBufferSize\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BltBuffer needed size... PixelWidth:0x%x PixelHeight:0x%x\n",\r
+ BltBufferSize\r
+ ));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ Temp = BltBufferSize;\r
+ Status = SafeUint32Mult (\r
+ BltBufferSize,\r
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),\r
+ &BltBufferSize\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateBmpToGopBlt: invalid BltBuffer needed size... BltBufferSize:0x%lx struct size:0x%x\n",\r
+ Temp, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ ));\r
+\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ IsAllocated = FALSE;\r
+ if (*GopBlt == NULL) {\r
+ //\r
+ // GopBlt is not allocated by caller.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "Bmp Support: Allocating 0x%X bytes of memory\n", BltBufferSize));\r
+ *GopBltSize = (UINTN)BltBufferSize;\r
+ *GopBlt = AllocatePool (*GopBltSize);\r
+ IsAllocated = TRUE;\r
+ if (*GopBlt == NULL) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ //\r
+ // GopBlt has been allocated by caller.\r
+ //\r
+ if (*GopBltSize < (UINTN)BltBufferSize) {\r
+ *GopBltSize = (UINTN)BltBufferSize;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+\r
+ *PixelWidth = BmpHeader->PixelWidth;\r
+ *PixelHeight = BmpHeader->PixelHeight;\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->ImageOffset 0x%X\n", BmpHeader->ImageOffset));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->PixelWidth 0x%X\n", BmpHeader->PixelWidth));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->PixelHeight 0x%X\n", BmpHeader->PixelHeight));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->BitPerPixel 0x%X\n", BmpHeader->BitPerPixel));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->ImageSize 0x%X\n", BmpHeader->ImageSize));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->HeaderSize 0x%X\n", BmpHeader->HeaderSize));\r
+ DEBUG ((DEBUG_INFO, "BmpHeader->Size 0x%X\n", BmpHeader->Size));\r
+\r
+ //\r
+ // Translate image from BMP to Blt buffer format\r
+ //\r
+ BltBuffer = *GopBlt;\r
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+ Blt = &BltBuffer[ (BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ //\r
+ // Translate 1-bit (2 colors) BMP to 24-bit color\r
+ //\r
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+ Blt->Red = BmpColorMap[ ((*Image) >> (7 - Index)) & 0x1].Red;\r
+ Blt->Green = BmpColorMap[ ((*Image) >> (7 - Index)) & 0x1].Green;\r
+ Blt->Blue = BmpColorMap[ ((*Image) >> (7 - Index)) & 0x1].Blue;\r
+ Blt++;\r
+ Width++;\r
+ }\r
+\r
+ Blt--;\r
+ Width--;\r
+ break;\r
+\r
+ case 4:\r
+ //\r
+ // Translate 4-bit (16 colors) BMP Palette to 24-bit color\r
+ //\r
+ Index = (*Image) >> 4;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ if (Width < (BmpHeader->PixelWidth - 1)) {\r
+ Blt++;\r
+ Width++;\r
+ Index = (*Image) & 0x0f;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ }\r
+ break;\r
+\r
+ case 8:\r
+ //\r
+ // Translate 8-bit (256 colors) BMP Palette to 24-bit color\r
+ //\r
+ Blt->Red = BmpColorMap[*Image].Red;\r
+ Blt->Green = BmpColorMap[*Image].Green;\r
+ Blt->Blue = BmpColorMap[*Image].Blue;\r
+ break;\r
+\r
+ case 24:\r
+ //\r
+ // It is 24-bit BMP.\r
+ //\r
+ Blt->Blue = *Image++;\r
+ Blt->Green = *Image++;\r
+ Blt->Red = *Image;\r
+ break;\r
+\r
+ case 32:\r
+ //\r
+ //Conver 32 bit to 24bit bmp - just ignore the final byte of each pixel\r
+ Blt->Blue = *Image++;\r
+ Blt->Green = *Image++;\r
+ Blt->Red = *Image++;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Other bit format BMP is not supported.\r
+ //\r
+ if (IsAllocated) {\r
+ FreePool (*GopBlt);\r
+ *GopBlt = NULL;\r
+ }\r
+ DEBUG ((DEBUG_ERROR, "Bmp Bit format not supported. 0x%X\n", BmpHeader->BitPerPixel));\r
+ return RETURN_UNSUPPORTED;\r
+ break;\r
+ };\r
+\r
+ }\r
+\r
+ ImageIndex = (UINTN)(Image - ImageHeader);\r
+ if ((ImageIndex % 4) != 0) {\r
+ //\r
+ // Bmp Image starts each row on a 32-bit boundary!\r
+ //\r
+ Image = Image + (4 - (ImageIndex % 4));\r
+ }\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Translate a GOP blt buffer to an uncompressed 24-bit per pixel BMP graphics\r
+ image. If a NULL BmpImage is passed in a BmpImage buffer will be allocated by\r
+ this routine using EFI_BOOT_SERVICES.AllocatePool(). If a BmpImage buffer is\r
+ passed in it will be used if it is big enough.\r
+\r
+ @param [in] GopBlt Pointer to GOP blt buffer.\r
+ @param [in] PixelHeight Height of GopBlt/BmpImage in pixels.\r
+ @param [in] PixelWidth Width of GopBlt/BmpImage in pixels.\r
+ @param [in, out] BmpImage Buffer containing BMP version of GopBlt.\r
+ @param [in, out] BmpImageSize Size of BmpImage in bytes.\r
+\r
+ @retval RETURN_SUCCESS BmpImage and BmpImageSize are returned.\r
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.\r
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.\r
+ @retval RETURN_INVALID_PARAMETER BmpImageSize is NULL.\r
+ @retval RETURN_UNSUPPORTED GopBlt cannot be converted to a *.BMP image.\r
+ @retval RETURN_BUFFER_TOO_SMALL The passed in BmpImage buffer is not big\r
+ enough. The required size is returned in\r
+ BmpImageSize.\r
+ @retval RETURN_OUT_OF_RESOURCES The BmpImage buffer could not be allocated.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TranslateGopBltToBmp (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt,\r
+ IN UINT32 PixelHeight,\r
+ IN UINT32 PixelWidth,\r
+ IN OUT VOID **BmpImage,\r
+ IN OUT UINT32 *BmpImageSize\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 PaddingSize;\r
+ UINT32 BmpSize;\r
+ BMP_IMAGE_HEADER *BmpImageHeader;\r
+ UINT8 *Image;\r
+ UINTN Col;\r
+ UINTN Row;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;\r
+\r
+ if (GopBlt == NULL || BmpImage == NULL || BmpImageSize == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Allocate memory for BMP file.\r
+ //\r
+ PaddingSize = PixelWidth & 0x3;\r
+\r
+ //\r
+ // First check PixelWidth * 3 + PaddingSize doesn't overflow\r
+ //\r
+ Status = SafeUint32Mult (PixelWidth, 3, &BmpSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",\r
+ PixelHeight,\r
+ PixelWidth\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ Status = SafeUint32Add (BmpSize, PaddingSize, &BmpSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",\r
+ PixelHeight,\r
+ PixelWidth\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow\r
+ //\r
+ Status = SafeUint32Mult (BmpSize, PixelHeight, &BmpSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",\r
+ PixelHeight,\r
+ PixelWidth\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ Status = SafeUint32Add (BmpSize, sizeof (BMP_IMAGE_HEADER), &BmpSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",\r
+ PixelHeight,\r
+ PixelWidth\r
+ ));\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // The image should be stored in EfiBootServicesData, allowing the system to\r
+ // reclaim the memory\r
+ //\r
+ if (*BmpImage == NULL) {\r
+ *BmpImage = AllocateZeroPool (BmpSize);\r
+ if (*BmpImage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ *BmpImageSize = BmpSize;\r
+ } else if (*BmpImageSize < BmpSize) {\r
+ *BmpImageSize = BmpSize;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ BmpImageHeader = (BMP_IMAGE_HEADER *)*BmpImage;\r
+ CopyMem (BmpImageHeader, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));\r
+ BmpImageHeader->Size = *BmpImageSize;\r
+ BmpImageHeader->ImageSize = *BmpImageSize - sizeof (BMP_IMAGE_HEADER);\r
+ BmpImageHeader->PixelWidth = PixelWidth;\r
+ BmpImageHeader->PixelHeight = PixelHeight;\r
+\r
+ //\r
+ // Convert BLT buffer to BMP file.\r
+ //\r
+ Image = (UINT8 *)BmpImageHeader + sizeof (BMP_IMAGE_HEADER);\r
+ for (Row = 0; Row < PixelHeight; Row++) {\r
+ BltPixel = &GopBlt[(PixelHeight - Row - 1) * PixelWidth];\r
+\r
+ for (Col = 0; Col < PixelWidth; Col++) {\r
+ *Image++ = BltPixel->Blue;\r
+ *Image++ = BltPixel->Green;\r
+ *Image++ = BltPixel->Red;\r
+ BltPixel++;\r
+ }\r
+\r
+ //\r
+ // Padding for 4 byte alignment.\r
+ //\r
+ Image += PaddingSize;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r