summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Library/BaseBmpSupportLib
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Library/BaseBmpSupportLib
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Library/BaseBmpSupportLib')
-rw-r--r--MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf66
-rw-r--r--MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.uni32
-rw-r--r--MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c1170
3 files changed, 634 insertions, 634 deletions
diff --git a/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf b/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
index a289ff8de1..9a47b6036c 100644
--- a/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+++ b/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
@@ -1,33 +1,33 @@
-## @file
-# Base library to support BMP graphics image conversion.
-#
-# Provides services to convert a BMP graphics image to a GOP BLT buffer and
-# from a GOP BLT buffer to a BMP graphics image.
-#
-# Copyright (c) 2017, Microsoft Corporation
-#
-# All rights reserved.
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-
-[Defines]
- INF_VERSION = 0x00010017
- BASE_NAME = BaseBmpSupportLib
- MODULE_UNI_FILE = BaseBmpSupportLib.uni
- FILE_GUID = CF5F650B-C208-409A-B889-0755172E2B0C
- VERSION_STRING = 1.0
- MODULE_TYPE = BASE
- LIBRARY_CLASS = BmpSupportLib
-
-[LibraryClasses]
- DebugLib
- BaseMemoryLib
- MemoryAllocationLib
- SafeIntLib
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[Sources]
- BmpSupportLib.c
+## @file
+# Base library to support BMP graphics image conversion.
+#
+# Provides services to convert a BMP graphics image to a GOP BLT buffer and
+# from a GOP BLT buffer to a BMP graphics image.
+#
+# Copyright (c) 2017, Microsoft Corporation
+#
+# All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = BaseBmpSupportLib
+ MODULE_UNI_FILE = BaseBmpSupportLib.uni
+ FILE_GUID = CF5F650B-C208-409A-B889-0755172E2B0C
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = BmpSupportLib
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ SafeIntLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+ BmpSupportLib.c
diff --git a/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.uni b/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.uni
index a818cac754..77c5047d34 100644
--- a/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.uni
+++ b/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.uni
@@ -1,16 +1,16 @@
-// /** @file
-// Base library to support BMP graphics image conversion.
-//
-// Provides services to convert a BMP graphics image to a GOP BLT buffer and
-// from a GOP BLT buffer to a BMP graphics image.
-//
-// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-#string STR_MODULE_ABSTRACT #language en-US "BmpSupportLib instance"
-
-#string STR_MODULE_DESCRIPTION #language en-US "BmpSupportLib instance."
-
+// /** @file
+// Base library to support BMP graphics image conversion.
+//
+// Provides services to convert a BMP graphics image to a GOP BLT buffer and
+// from a GOP BLT buffer to a BMP graphics image.
+//
+// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "BmpSupportLib instance"
+
+#string STR_MODULE_DESCRIPTION #language en-US "BmpSupportLib instance."
+
diff --git a/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c b/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c
index c5e885d7a6..18df11f008 100644
--- a/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c
+++ b/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c
@@ -1,585 +1,585 @@
-/** @file
-
- Provides services to convert a BMP graphics image to a GOP BLT buffer and
- from a GOP BLT buffer to a BMP graphics image.
-
- Caution: This module requires additional review when modified.
- This module processes external input - BMP image.
- This external input must be validated carefully to avoid security issue such
- as buffer overflow, integer overflow.
-
- TranslateBmpToGopBlt() receives untrusted input and performs basic validation.
-
- Copyright (c) 2016-2017, Microsoft Corporation
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-
- All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/SafeIntLib.h>
-#include <IndustryStandard/Bmp.h>
-
-#include <Library/BmpSupportLib.h>
-
-//
-// BMP Image header for an uncompressed 24-bit per pixel BMP image.
-//
-const BMP_IMAGE_HEADER mBmpImageHeaderTemplate = {
- 'B', // CharB
- 'M', // CharM
- 0, // Size will be updated at runtime
- { 0, 0 }, // Reserved
- sizeof (BMP_IMAGE_HEADER), // ImageOffset
- sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize
- 0, // PixelWidth will be updated at runtime
- 0, // PixelHeight will be updated at runtime
- 1, // Planes
- 24, // BitPerPixel
- 0, // CompressionType
- 0, // ImageSize will be updated at runtime
- 0, // XPixelsPerMeter
- 0, // YPixelsPerMeter
- 0, // NumberOfColors
- 0 // ImportantColors
-};
-
-/**
- Translate a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
- is passed in a GopBlt buffer will be allocated by this routine using
- EFI_BOOT_SERVICES.AllocatePool(). If a GopBlt buffer is passed in it will be
- used if it is big enough.
-
- @param[in] BmpImage Pointer to BMP file.
- @param[in] BmpImageSize Number of bytes in BmpImage.
- @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
- @param[in, out] GopBltSize Size of GopBlt in bytes.
- @param[out] PixelHeight Height of GopBlt/BmpImage in pixels.
- @param[out] PixelWidth Width of GopBlt/BmpImage in pixels.
-
- @retval RETURN_SUCCESS GopBlt and GopBltSize are returned.
- @retval RETURN_INVALID_PARAMETER BmpImage is NULL.
- @retval RETURN_INVALID_PARAMETER GopBlt is NULL.
- @retval RETURN_INVALID_PARAMETER GopBltSize is NULL.
- @retval RETURN_INVALID_PARAMETER PixelHeight is NULL.
- @retval RETURN_INVALID_PARAMETER PixelWidth is NULL.
- @retval RETURN_UNSUPPORTED BmpImage is not a valid *.BMP image.
- @retval RETURN_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big
- enough. The required size is returned in
- GopBltSize.
- @retval RETURN_OUT_OF_RESOURCES The GopBlt buffer could not be allocated.
-
-**/
-RETURN_STATUS
-EFIAPI
-TranslateBmpToGopBlt (
- IN VOID *BmpImage,
- IN UINTN BmpImageSize,
- IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **GopBlt,
- IN OUT UINTN *GopBltSize,
- OUT UINTN *PixelHeight,
- OUT UINTN *PixelWidth
- )
-{
- UINT8 *Image;
- UINT8 *ImageHeader;
- BMP_IMAGE_HEADER *BmpHeader;
- BMP_COLOR_MAP *BmpColorMap;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
- UINT32 BltBufferSize;
- UINTN Index;
- UINTN Height;
- UINTN Width;
- UINTN ImageIndex;
- UINT32 DataSizePerLine;
- BOOLEAN IsAllocated;
- UINT32 ColorMapNum;
- RETURN_STATUS Status;
- UINT32 DataSize;
- UINT32 Temp;
-
- if ((BmpImage == NULL) || (GopBlt == NULL) || (GopBltSize == NULL)) {
- return RETURN_INVALID_PARAMETER;
- }
-
- if ((PixelHeight == NULL) || (PixelWidth == NULL)) {
- return RETURN_INVALID_PARAMETER;
- }
-
- if (BmpImageSize < sizeof (BMP_IMAGE_HEADER)) {
- DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpImageSize too small\n"));
- return RETURN_UNSUPPORTED;
- }
-
- BmpHeader = (BMP_IMAGE_HEADER *)BmpImage;
-
- if ((BmpHeader->CharB != 'B') || (BmpHeader->CharM != 'M')) {
- DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpHeader->Char fields incorrect\n"));
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Doesn't support compress.
- //
- if (BmpHeader->CompressionType != 0) {
- DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: Compression Type unsupported.\n"));
- return RETURN_UNSUPPORTED;
- }
-
- if ((BmpHeader->PixelHeight == 0) || (BmpHeader->PixelWidth == 0)) {
- DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpHeader->PixelHeight or BmpHeader->PixelWidth is 0.\n"));
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Only support BITMAPINFOHEADER format.
- // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
- //
- if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: BmpHeader->Headership is not as expected. Headersize is 0x%x\n",
- BmpHeader->HeaderSize
- ));
- return RETURN_UNSUPPORTED;
- }
-
- //
- // The data size in each line must be 4 byte alignment.
- //
- Status = SafeUint32Mult (
- BmpHeader->PixelWidth,
- BmpHeader->BitPerPixel,
- &DataSizePerLine
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BmpImage... PixelWidth:0x%x BitPerPixel:0x%x\n",
- BmpHeader->PixelWidth,
- BmpHeader->BitPerPixel
- ));
- return RETURN_UNSUPPORTED;
- }
-
- Status = SafeUint32Add (DataSizePerLine, 31, &DataSizePerLine);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x\n",
- DataSizePerLine
- ));
-
- return RETURN_UNSUPPORTED;
- }
-
- DataSizePerLine = (DataSizePerLine >> 3) &(~0x3);
- Status = SafeUint32Mult (
- DataSizePerLine,
- BmpHeader->PixelHeight,
- &BltBufferSize
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x PixelHeight:0x%x\n",
- DataSizePerLine,
- BmpHeader->PixelHeight
- ));
-
- return RETURN_UNSUPPORTED;
- }
-
- Status = SafeUint32Mult (
- BmpHeader->PixelHeight,
- DataSizePerLine,
- &DataSize
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BmpImage... PixelHeight:0x%x DataSizePerLine:0x%x\n",
- BmpHeader->PixelHeight,
- DataSizePerLine
- ));
-
- return RETURN_UNSUPPORTED;
- }
-
- if ((BmpHeader->Size != BmpImageSize) ||
- (BmpHeader->Size < BmpHeader->ImageOffset) ||
- (BmpHeader->Size - BmpHeader->ImageOffset != DataSize))
- {
- DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: invalid BmpImage... \n"));
- DEBUG ((DEBUG_ERROR, " BmpHeader->Size: 0x%x\n", BmpHeader->Size));
- DEBUG ((DEBUG_ERROR, " BmpHeader->ImageOffset: 0x%x\n", BmpHeader->ImageOffset));
- DEBUG ((DEBUG_ERROR, " BmpImageSize: 0x%lx\n", (UINTN)BmpImageSize));
- DEBUG ((DEBUG_ERROR, " DataSize: 0x%lx\n", (UINTN)DataSize));
-
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Calculate Color Map offset in the image.
- //
- Image = BmpImage;
- BmpColorMap = (BMP_COLOR_MAP *)(Image + sizeof (BMP_IMAGE_HEADER));
- if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
- return RETURN_UNSUPPORTED;
- }
-
- if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
- switch (BmpHeader->BitPerPixel) {
- case 1:
- ColorMapNum = 2;
- break;
- case 4:
- ColorMapNum = 16;
- break;
- case 8:
- ColorMapNum = 256;
- break;
- default:
- ColorMapNum = 0;
- break;
- }
-
- //
- // BMP file may has padding data between the bmp header section and the
- // bmp data section.
- //
- if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
- return RETURN_UNSUPPORTED;
- }
- }
-
- //
- // Calculate graphics image data address in the image
- //
- Image = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset;
- ImageHeader = Image;
-
- //
- // Calculate the BltBuffer needed size.
- //
- Status = SafeUint32Mult (
- BmpHeader->PixelWidth,
- BmpHeader->PixelHeight,
- &BltBufferSize
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BltBuffer needed size... PixelWidth:0x%x PixelHeight:0x%x\n",
- BmpHeader->PixelWidth,
- BmpHeader->PixelHeight
- ));
-
- return RETURN_UNSUPPORTED;
- }
-
- Temp = BltBufferSize;
- Status = SafeUint32Mult (
- BltBufferSize,
- sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
- &BltBufferSize
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateBmpToGopBlt: invalid BltBuffer needed size... PixelWidth x PixelHeight:0x%x struct size:0x%x\n",
- Temp,
- sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- ));
-
- return RETURN_UNSUPPORTED;
- }
-
- IsAllocated = FALSE;
- if (*GopBlt == NULL) {
- //
- // GopBlt is not allocated by caller.
- //
- DEBUG ((DEBUG_INFO, "Bmp Support: Allocating 0x%X bytes of memory\n", BltBufferSize));
- *GopBltSize = (UINTN)BltBufferSize;
- *GopBlt = AllocatePool (*GopBltSize);
- IsAllocated = TRUE;
- if (*GopBlt == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- } else {
- //
- // GopBlt has been allocated by caller.
- //
- if (*GopBltSize < (UINTN)BltBufferSize) {
- *GopBltSize = (UINTN)BltBufferSize;
- return RETURN_BUFFER_TOO_SMALL;
- }
- }
-
- *PixelWidth = BmpHeader->PixelWidth;
- *PixelHeight = BmpHeader->PixelHeight;
- DEBUG ((DEBUG_INFO, "BmpHeader->ImageOffset 0x%X\n", BmpHeader->ImageOffset));
- DEBUG ((DEBUG_INFO, "BmpHeader->PixelWidth 0x%X\n", BmpHeader->PixelWidth));
- DEBUG ((DEBUG_INFO, "BmpHeader->PixelHeight 0x%X\n", BmpHeader->PixelHeight));
- DEBUG ((DEBUG_INFO, "BmpHeader->BitPerPixel 0x%X\n", BmpHeader->BitPerPixel));
- DEBUG ((DEBUG_INFO, "BmpHeader->ImageSize 0x%X\n", BmpHeader->ImageSize));
- DEBUG ((DEBUG_INFO, "BmpHeader->HeaderSize 0x%X\n", BmpHeader->HeaderSize));
- DEBUG ((DEBUG_INFO, "BmpHeader->Size 0x%X\n", BmpHeader->Size));
-
- //
- // Translate image from BMP to Blt buffer format
- //
- BltBuffer = *GopBlt;
- for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
- Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
- for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
- switch (BmpHeader->BitPerPixel) {
- case 1:
- //
- // Translate 1-bit (2 colors) BMP to 24-bit color
- //
- for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
- Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
- Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
- Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
- Blt++;
- Width++;
- }
-
- Blt--;
- Width--;
- break;
-
- case 4:
- //
- // Translate 4-bit (16 colors) BMP Palette to 24-bit color
- //
- Index = (*Image) >> 4;
- Blt->Red = BmpColorMap[Index].Red;
- Blt->Green = BmpColorMap[Index].Green;
- Blt->Blue = BmpColorMap[Index].Blue;
- if (Width < (BmpHeader->PixelWidth - 1)) {
- Blt++;
- Width++;
- Index = (*Image) & 0x0f;
- Blt->Red = BmpColorMap[Index].Red;
- Blt->Green = BmpColorMap[Index].Green;
- Blt->Blue = BmpColorMap[Index].Blue;
- }
-
- break;
-
- case 8:
- //
- // Translate 8-bit (256 colors) BMP Palette to 24-bit color
- //
- Blt->Red = BmpColorMap[*Image].Red;
- Blt->Green = BmpColorMap[*Image].Green;
- Blt->Blue = BmpColorMap[*Image].Blue;
- break;
-
- case 24:
- //
- // It is 24-bit BMP.
- //
- Blt->Blue = *Image++;
- Blt->Green = *Image++;
- Blt->Red = *Image;
- break;
-
- case 32:
- //
- // Conver 32 bit to 24bit bmp - just ignore the final byte of each pixel
- Blt->Blue = *Image++;
- Blt->Green = *Image++;
- Blt->Red = *Image++;
- break;
-
- default:
- //
- // Other bit format BMP is not supported.
- //
- if (IsAllocated) {
- FreePool (*GopBlt);
- *GopBlt = NULL;
- }
-
- DEBUG ((DEBUG_ERROR, "Bmp Bit format not supported. 0x%X\n", BmpHeader->BitPerPixel));
- return RETURN_UNSUPPORTED;
- break;
- }
- }
-
- ImageIndex = (UINTN)Image - (UINTN)ImageHeader;
- if ((ImageIndex % 4) != 0) {
- //
- // Bmp Image starts each row on a 32-bit boundary!
- //
- Image = Image + (4 - (ImageIndex % 4));
- }
- }
-
- return RETURN_SUCCESS;
-}
-
-/**
- Translate a GOP blt buffer to an uncompressed 24-bit per pixel BMP graphics
- image. If a NULL BmpImage is passed in a BmpImage buffer will be allocated by
- this routine using EFI_BOOT_SERVICES.AllocatePool(). If a BmpImage buffer is
- passed in it will be used if it is big enough.
-
- @param [in] GopBlt Pointer to GOP blt buffer.
- @param [in] PixelHeight Height of GopBlt/BmpImage in pixels.
- @param [in] PixelWidth Width of GopBlt/BmpImage in pixels.
- @param [in, out] BmpImage Buffer containing BMP version of GopBlt.
- @param [in, out] BmpImageSize Size of BmpImage in bytes.
-
- @retval RETURN_SUCCESS BmpImage and BmpImageSize are returned.
- @retval RETURN_INVALID_PARAMETER GopBlt is NULL.
- @retval RETURN_INVALID_PARAMETER BmpImage is NULL.
- @retval RETURN_INVALID_PARAMETER BmpImageSize is NULL.
- @retval RETURN_UNSUPPORTED GopBlt cannot be converted to a *.BMP image.
- @retval RETURN_BUFFER_TOO_SMALL The passed in BmpImage buffer is not big
- enough. The required size is returned in
- BmpImageSize.
- @retval RETURN_OUT_OF_RESOURCES The BmpImage buffer could not be allocated.
-
-**/
-RETURN_STATUS
-EFIAPI
-TranslateGopBltToBmp (
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt,
- IN UINT32 PixelHeight,
- IN UINT32 PixelWidth,
- IN OUT VOID **BmpImage,
- IN OUT UINT32 *BmpImageSize
- )
-{
- RETURN_STATUS Status;
- UINT32 PaddingSize;
- UINT32 BmpSize;
- BMP_IMAGE_HEADER *BmpImageHeader;
- UINT8 *Image;
- UINTN Col;
- UINTN Row;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;
-
- if ((GopBlt == NULL) || (BmpImage == NULL) || (BmpImageSize == NULL)) {
- return RETURN_INVALID_PARAMETER;
- }
-
- if ((PixelHeight == 0) || (PixelWidth == 0)) {
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Allocate memory for BMP file.
- //
- PaddingSize = PixelWidth & 0x3;
-
- //
- // First check PixelWidth * 3 + PaddingSize doesn't overflow
- //
- Status = SafeUint32Mult (PixelWidth, 3, &BmpSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
- PixelHeight,
- PixelWidth
- ));
- return RETURN_UNSUPPORTED;
- }
-
- Status = SafeUint32Add (BmpSize, PaddingSize, &BmpSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
- PixelHeight,
- PixelWidth
- ));
- return RETURN_UNSUPPORTED;
- }
-
- //
- // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow
- //
- Status = SafeUint32Mult (BmpSize, PixelHeight, &BmpSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
- PixelHeight,
- PixelWidth
- ));
- return RETURN_UNSUPPORTED;
- }
-
- Status = SafeUint32Add (BmpSize, sizeof (BMP_IMAGE_HEADER), &BmpSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
- PixelHeight,
- PixelWidth
- ));
- return RETURN_UNSUPPORTED;
- }
-
- //
- // The image should be stored in EfiBootServicesData, allowing the system to
- // reclaim the memory
- //
- if (*BmpImage == NULL) {
- *BmpImage = AllocateZeroPool (BmpSize);
- if (*BmpImage == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- *BmpImageSize = BmpSize;
- } else if (*BmpImageSize < BmpSize) {
- *BmpImageSize = BmpSize;
- return RETURN_BUFFER_TOO_SMALL;
- }
-
- BmpImageHeader = (BMP_IMAGE_HEADER *)*BmpImage;
- CopyMem (BmpImageHeader, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));
- BmpImageHeader->Size = *BmpImageSize;
- BmpImageHeader->ImageSize = *BmpImageSize - sizeof (BMP_IMAGE_HEADER);
- BmpImageHeader->PixelWidth = PixelWidth;
- BmpImageHeader->PixelHeight = PixelHeight;
-
- //
- // Convert BLT buffer to BMP file.
- //
- Image = (UINT8 *)BmpImageHeader + sizeof (BMP_IMAGE_HEADER);
- for (Row = 0; Row < PixelHeight; Row++) {
- BltPixel = &GopBlt[(PixelHeight - Row - 1) * PixelWidth];
-
- for (Col = 0; Col < PixelWidth; Col++) {
- *Image++ = BltPixel->Blue;
- *Image++ = BltPixel->Green;
- *Image++ = BltPixel->Red;
- BltPixel++;
- }
-
- //
- // Padding for 4 byte alignment.
- //
- Image += PaddingSize;
- }
-
- return RETURN_SUCCESS;
-}
+/** @file
+
+ Provides services to convert a BMP graphics image to a GOP BLT buffer and
+ from a GOP BLT buffer to a BMP graphics image.
+
+ Caution: This module requires additional review when modified.
+ This module processes external input - BMP image.
+ This external input must be validated carefully to avoid security issue such
+ as buffer overflow, integer overflow.
+
+ TranslateBmpToGopBlt() receives untrusted input and performs basic validation.
+
+ Copyright (c) 2016-2017, Microsoft Corporation
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SafeIntLib.h>
+#include <IndustryStandard/Bmp.h>
+
+#include <Library/BmpSupportLib.h>
+
+//
+// BMP Image header for an uncompressed 24-bit per pixel BMP image.
+//
+const BMP_IMAGE_HEADER mBmpImageHeaderTemplate = {
+ 'B', // CharB
+ 'M', // CharM
+ 0, // Size will be updated at runtime
+ { 0, 0 }, // Reserved
+ sizeof (BMP_IMAGE_HEADER), // ImageOffset
+ sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize
+ 0, // PixelWidth will be updated at runtime
+ 0, // PixelHeight will be updated at runtime
+ 1, // Planes
+ 24, // BitPerPixel
+ 0, // CompressionType
+ 0, // ImageSize will be updated at runtime
+ 0, // XPixelsPerMeter
+ 0, // YPixelsPerMeter
+ 0, // NumberOfColors
+ 0 // ImportantColors
+};
+
+/**
+ Translate a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine using
+ EFI_BOOT_SERVICES.AllocatePool(). If a GopBlt buffer is passed in it will be
+ used if it is big enough.
+
+ @param[in] BmpImage Pointer to BMP file.
+ @param[in] BmpImageSize Number of bytes in BmpImage.
+ @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
+ @param[in, out] GopBltSize Size of GopBlt in bytes.
+ @param[out] PixelHeight Height of GopBlt/BmpImage in pixels.
+ @param[out] PixelWidth Width of GopBlt/BmpImage in pixels.
+
+ @retval RETURN_SUCCESS GopBlt and GopBltSize are returned.
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.
+ @retval RETURN_INVALID_PARAMETER GopBltSize is NULL.
+ @retval RETURN_INVALID_PARAMETER PixelHeight is NULL.
+ @retval RETURN_INVALID_PARAMETER PixelWidth is NULL.
+ @retval RETURN_UNSUPPORTED BmpImage is not a valid *.BMP image.
+ @retval RETURN_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big
+ enough. The required size is returned in
+ GopBltSize.
+ @retval RETURN_OUT_OF_RESOURCES The GopBlt buffer could not be allocated.
+
+**/
+RETURN_STATUS
+EFIAPI
+TranslateBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT32 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ UINT32 DataSizePerLine;
+ BOOLEAN IsAllocated;
+ UINT32 ColorMapNum;
+ RETURN_STATUS Status;
+ UINT32 DataSize;
+ UINT32 Temp;
+
+ if ((BmpImage == NULL) || (GopBlt == NULL) || (GopBltSize == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((PixelHeight == NULL) || (PixelWidth == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (BmpImageSize < sizeof (BMP_IMAGE_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpImageSize too small\n"));
+ return RETURN_UNSUPPORTED;
+ }
+
+ BmpHeader = (BMP_IMAGE_HEADER *)BmpImage;
+
+ if ((BmpHeader->CharB != 'B') || (BmpHeader->CharM != 'M')) {
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpHeader->Char fields incorrect\n"));
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: Compression Type unsupported.\n"));
+ return RETURN_UNSUPPORTED;
+ }
+
+ if ((BmpHeader->PixelHeight == 0) || (BmpHeader->PixelWidth == 0)) {
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: BmpHeader->PixelHeight or BmpHeader->PixelWidth is 0.\n"));
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Only support BITMAPINFOHEADER format.
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+ //
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: BmpHeader->Headership is not as expected. Headersize is 0x%x\n",
+ BmpHeader->HeaderSize
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // The data size in each line must be 4 byte alignment.
+ //
+ Status = SafeUint32Mult (
+ BmpHeader->PixelWidth,
+ BmpHeader->BitPerPixel,
+ &DataSizePerLine
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BmpImage... PixelWidth:0x%x BitPerPixel:0x%x\n",
+ BmpHeader->PixelWidth,
+ BmpHeader->BitPerPixel
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ Status = SafeUint32Add (DataSizePerLine, 31, &DataSizePerLine);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x\n",
+ DataSizePerLine
+ ));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ DataSizePerLine = (DataSizePerLine >> 3) &(~0x3);
+ Status = SafeUint32Mult (
+ DataSizePerLine,
+ BmpHeader->PixelHeight,
+ &BltBufferSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BmpImage... DataSizePerLine:0x%x PixelHeight:0x%x\n",
+ DataSizePerLine,
+ BmpHeader->PixelHeight
+ ));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ Status = SafeUint32Mult (
+ BmpHeader->PixelHeight,
+ DataSizePerLine,
+ &DataSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BmpImage... PixelHeight:0x%x DataSizePerLine:0x%x\n",
+ BmpHeader->PixelHeight,
+ DataSizePerLine
+ ));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ if ((BmpHeader->Size != BmpImageSize) ||
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||
+ (BmpHeader->Size - BmpHeader->ImageOffset != DataSize))
+ {
+ DEBUG ((DEBUG_ERROR, "TranslateBmpToGopBlt: invalid BmpImage... \n"));
+ DEBUG ((DEBUG_ERROR, " BmpHeader->Size: 0x%x\n", BmpHeader->Size));
+ DEBUG ((DEBUG_ERROR, " BmpHeader->ImageOffset: 0x%x\n", BmpHeader->ImageOffset));
+ DEBUG ((DEBUG_ERROR, " BmpImageSize: 0x%lx\n", (UINTN)BmpImageSize));
+ DEBUG ((DEBUG_ERROR, " DataSize: 0x%lx\n", (UINTN)DataSize));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *)(Image + sizeof (BMP_IMAGE_HEADER));
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ ColorMapNum = 2;
+ break;
+ case 4:
+ ColorMapNum = 16;
+ break;
+ case 8:
+ ColorMapNum = 256;
+ break;
+ default:
+ ColorMapNum = 0;
+ break;
+ }
+
+ //
+ // BMP file may has padding data between the bmp header section and the
+ // bmp data section.
+ //
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+ return RETURN_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ Status = SafeUint32Mult (
+ BmpHeader->PixelWidth,
+ BmpHeader->PixelHeight,
+ &BltBufferSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BltBuffer needed size... PixelWidth:0x%x PixelHeight:0x%x\n",
+ BmpHeader->PixelWidth,
+ BmpHeader->PixelHeight
+ ));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ Temp = BltBufferSize;
+ Status = SafeUint32Mult (
+ BltBufferSize,
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
+ &BltBufferSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateBmpToGopBlt: invalid BltBuffer needed size... PixelWidth x PixelHeight:0x%x struct size:0x%x\n",
+ Temp,
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ ));
+
+ return RETURN_UNSUPPORTED;
+ }
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ DEBUG ((DEBUG_INFO, "Bmp Support: Allocating 0x%X bytes of memory\n", BltBufferSize));
+ *GopBltSize = (UINTN)BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN)BltBufferSize) {
+ *GopBltSize = (UINTN)BltBufferSize;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+ DEBUG ((DEBUG_INFO, "BmpHeader->ImageOffset 0x%X\n", BmpHeader->ImageOffset));
+ DEBUG ((DEBUG_INFO, "BmpHeader->PixelWidth 0x%X\n", BmpHeader->PixelWidth));
+ DEBUG ((DEBUG_INFO, "BmpHeader->PixelHeight 0x%X\n", BmpHeader->PixelHeight));
+ DEBUG ((DEBUG_INFO, "BmpHeader->BitPerPixel 0x%X\n", BmpHeader->BitPerPixel));
+ DEBUG ((DEBUG_INFO, "BmpHeader->ImageSize 0x%X\n", BmpHeader->ImageSize));
+ DEBUG ((DEBUG_INFO, "BmpHeader->HeaderSize 0x%X\n", BmpHeader->HeaderSize));
+ DEBUG ((DEBUG_INFO, "BmpHeader->Size 0x%X\n", BmpHeader->Size));
+
+ //
+ // Translate image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Translate 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Translate 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+
+ break;
+
+ case 8:
+ //
+ // Translate 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ case 32:
+ //
+ // Conver 32 bit to 24bit bmp - just ignore the final byte of each pixel
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image++;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+
+ DEBUG ((DEBUG_ERROR, "Bmp Bit format not supported. 0x%X\n", BmpHeader->BitPerPixel));
+ return RETURN_UNSUPPORTED;
+ break;
+ }
+ }
+
+ ImageIndex = (UINTN)Image - (UINTN)ImageHeader;
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Translate a GOP blt buffer to an uncompressed 24-bit per pixel BMP graphics
+ image. If a NULL BmpImage is passed in a BmpImage buffer will be allocated by
+ this routine using EFI_BOOT_SERVICES.AllocatePool(). If a BmpImage buffer is
+ passed in it will be used if it is big enough.
+
+ @param [in] GopBlt Pointer to GOP blt buffer.
+ @param [in] PixelHeight Height of GopBlt/BmpImage in pixels.
+ @param [in] PixelWidth Width of GopBlt/BmpImage in pixels.
+ @param [in, out] BmpImage Buffer containing BMP version of GopBlt.
+ @param [in, out] BmpImageSize Size of BmpImage in bytes.
+
+ @retval RETURN_SUCCESS BmpImage and BmpImageSize are returned.
+ @retval RETURN_INVALID_PARAMETER GopBlt is NULL.
+ @retval RETURN_INVALID_PARAMETER BmpImage is NULL.
+ @retval RETURN_INVALID_PARAMETER BmpImageSize is NULL.
+ @retval RETURN_UNSUPPORTED GopBlt cannot be converted to a *.BMP image.
+ @retval RETURN_BUFFER_TOO_SMALL The passed in BmpImage buffer is not big
+ enough. The required size is returned in
+ BmpImageSize.
+ @retval RETURN_OUT_OF_RESOURCES The BmpImage buffer could not be allocated.
+
+**/
+RETURN_STATUS
+EFIAPI
+TranslateGopBltToBmp (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt,
+ IN UINT32 PixelHeight,
+ IN UINT32 PixelWidth,
+ IN OUT VOID **BmpImage,
+ IN OUT UINT32 *BmpImageSize
+ )
+{
+ RETURN_STATUS Status;
+ UINT32 PaddingSize;
+ UINT32 BmpSize;
+ BMP_IMAGE_HEADER *BmpImageHeader;
+ UINT8 *Image;
+ UINTN Col;
+ UINTN Row;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;
+
+ if ((GopBlt == NULL) || (BmpImage == NULL) || (BmpImageSize == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if ((PixelHeight == 0) || (PixelWidth == 0)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Allocate memory for BMP file.
+ //
+ PaddingSize = PixelWidth & 0x3;
+
+ //
+ // First check PixelWidth * 3 + PaddingSize doesn't overflow
+ //
+ Status = SafeUint32Mult (PixelWidth, 3, &BmpSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
+ PixelHeight,
+ PixelWidth
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ Status = SafeUint32Add (BmpSize, PaddingSize, &BmpSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
+ PixelHeight,
+ PixelWidth
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow
+ //
+ Status = SafeUint32Mult (BmpSize, PixelHeight, &BmpSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
+ PixelHeight,
+ PixelWidth
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ Status = SafeUint32Add (BmpSize, sizeof (BMP_IMAGE_HEADER), &BmpSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "TranslateGopBltToBmp: GopBlt is too large. PixelHeight:0x%x PixelWidth:0x%x\n",
+ PixelHeight,
+ PixelWidth
+ ));
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // The image should be stored in EfiBootServicesData, allowing the system to
+ // reclaim the memory
+ //
+ if (*BmpImage == NULL) {
+ *BmpImage = AllocateZeroPool (BmpSize);
+ if (*BmpImage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *BmpImageSize = BmpSize;
+ } else if (*BmpImageSize < BmpSize) {
+ *BmpImageSize = BmpSize;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ BmpImageHeader = (BMP_IMAGE_HEADER *)*BmpImage;
+ CopyMem (BmpImageHeader, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));
+ BmpImageHeader->Size = *BmpImageSize;
+ BmpImageHeader->ImageSize = *BmpImageSize - sizeof (BMP_IMAGE_HEADER);
+ BmpImageHeader->PixelWidth = PixelWidth;
+ BmpImageHeader->PixelHeight = PixelHeight;
+
+ //
+ // Convert BLT buffer to BMP file.
+ //
+ Image = (UINT8 *)BmpImageHeader + sizeof (BMP_IMAGE_HEADER);
+ for (Row = 0; Row < PixelHeight; Row++) {
+ BltPixel = &GopBlt[(PixelHeight - Row - 1) * PixelWidth];
+
+ for (Col = 0; Col < PixelWidth; Col++) {
+ *Image++ = BltPixel->Blue;
+ *Image++ = BltPixel->Green;
+ *Image++ = BltPixel->Red;
+ BltPixel++;
+ }
+
+ //
+ // Padding for 4 byte alignment.
+ //
+ Image += PaddingSize;
+ }
+
+ return RETURN_SUCCESS;
+}