aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c')
-rw-r--r--roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c1563
1 files changed, 1563 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
new file mode 100644
index 000000000..a108fc615
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -0,0 +1,1563 @@
+/** @file
+Implementation for EFI_HII_IMAGE_PROTOCOL.
+
+
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "HiiDatabase.h"
+
+#define MAX_UINT24 0xFFFFFF
+
+/**
+ Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
+ ImageId is zero, otherwise return the address of the
+ corresponding image block with identifier specified by ImageId.
+
+ This is a internal function.
+
+ @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
+ @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
+ else use this id to find its corresponding image block address.
+
+ @return The image block address when input ImageId is not zero; otherwise return NULL.
+
+**/
+EFI_HII_IMAGE_BLOCK *
+GetImageIdOrAddress (
+ IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
+ IN OUT EFI_IMAGE_ID *ImageId
+ )
+{
+ EFI_IMAGE_ID ImageIdCurrent;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ UINTN Length;
+
+ ASSERT (ImageBlocks != NULL && ImageId != NULL);
+ CurrentImageBlock = ImageBlocks;
+ ImageIdCurrent = 1;
+
+ while (CurrentImageBlock->BlockType != EFI_HII_IIBT_END) {
+ if (*ImageId != 0) {
+ if (*ImageId == ImageIdCurrent) {
+ //
+ // If the found image block is a duplicate block, update the ImageId to
+ // find the previous defined image block.
+ //
+ if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {
+ *ImageId = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_DUPLICATE_BLOCK *) CurrentImageBlock)->ImageId);
+ ASSERT (*ImageId != ImageIdCurrent);
+ ASSERT (*ImageId != 0);
+ CurrentImageBlock = ImageBlocks;
+ ImageIdCurrent = 1;
+ continue;
+ }
+
+ return CurrentImageBlock;
+ }
+ if (*ImageId < ImageIdCurrent) {
+ //
+ // Can not find the specified image block in this image.
+ //
+ return NULL;
+ }
+ }
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_EXT1:
+ Length = ((EFI_HII_IIBT_EXT1_BLOCK *) CurrentImageBlock)->Length;
+ break;
+ case EFI_HII_IIBT_EXT2:
+ Length = ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK *) CurrentImageBlock)->Length);
+ break;
+ case EFI_HII_IIBT_EXT4:
+ Length = ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_EXT4_BLOCK *) CurrentImageBlock)->Length);
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (
+ (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Length = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (
+ (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_DUPLICATE:
+ Length = sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ Length = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_PNG:
+ Length = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_SKIP1:
+ Length = sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
+ ImageIdCurrent += ((EFI_HII_IIBT_SKIP1_BLOCK *) CurrentImageBlock)->SkipCount;
+ break;
+
+ case EFI_HII_IIBT_SKIP2:
+ Length = sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
+ ImageIdCurrent += ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_SKIP2_BLOCK *) CurrentImageBlock)->SkipCount);
+ break;
+
+ default:
+ //
+ // Unknown image blocks can not be skipped, processing halts.
+ //
+ ASSERT (FALSE);
+ Length = 0;
+ break;
+ }
+
+ CurrentImageBlock = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) CurrentImageBlock + Length);
+
+ }
+
+ //
+ // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
+ //
+ if (*ImageId == 0) {
+ *ImageId = ImageIdCurrent;
+ return CurrentImageBlock;
+ }
+
+ return NULL;
+}
+
+
+
+/**
+ Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
+
+ This is a internal function.
+
+
+ @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
+ @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+VOID
+CopyGopToRgbPixel (
+ OUT EFI_HII_RGB_PIXEL *BitMapOut,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+
+/**
+ Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
+
+ This is a internal function.
+
+
+ @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+VOID
+CopyRgbToGopPixel (
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapOut,
+ IN EFI_HII_RGB_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+
+/**
+ Output pixels in "1 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 or 1.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. First entry corresponds to color 0 and
+ second one to color 1.
+
+
+**/
+VOID
+Output1bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ UINT8 Index;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // First entry corresponds to color 0 and second entry corresponds to color 1.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
+ CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from one bit to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Byte & (1 << Index)) != 0) {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
+ } else {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
+ }
+ }
+ }
+
+ if (Image->Width % 8 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + Xpos);
+ for (Index = 0; Index < Image->Width % 8; Index++) {
+ if ((Byte & (1 << (8 - Index - 1))) != 0) {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
+ } else {
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ Output pixels in "4 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 15.
+ @param[in] PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 15].
+
+
+**/
+VOID
+Output4bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from 4 bit to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
+ BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];
+ }
+
+ if (Image->Width % 2 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
+ }
+ }
+}
+
+
+/**
+ Output pixels in "8 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 255.
+ @param[in] PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 255].
+
+
+**/
+VOID
+Output8bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ PaletteSize = 0;
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ if (Palette == NULL) {
+ return;
+ }
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ FreePool (Palette);
+
+ //
+ // Convert the pixel from 8 bits to corresponding color.
+ //
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_8_BIT ((UINT32) Image->Width, Ypos);
+ //
+ // All bits are meaningful since the bitmap is 8 bits per pixel.
+ //
+ for (Xpos = 0; Xpos < Image->Width; Xpos++) {
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];
+ }
+ }
+
+}
+
+
+/**
+ Output pixels in "24 bit per pixel" format to an image.
+
+ This is a internal function.
+
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the color of output pixels, allowing 16.8
+ millions colors.
+
+
+**/
+VOID
+Output24bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN EFI_HII_RGB_PIXEL *Data
+ )
+{
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+
+ ASSERT (Image != NULL && Data != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ for (Ypos = 0; Ypos < Image->Height; Ypos++) {
+ OffsetY = BITMAP_LEN_8_BIT ((UINT32) Image->Width, Ypos);
+ CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
+ }
+
+}
+
+
+/**
+ Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
+
+ This is a internal function.
+
+
+ @param BltBuffer Buffer points to bitmap data of incoming image.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param Width Width of the incoming image, in pixels.
+ @param Height Height of the incoming image, in pixels.
+ @param Transparent If TRUE, all "off" pixels in the image will be
+ drawn using the pixel value from blt and all other
+ pixels will be copied.
+ @param Blt Buffer points to bitmap data of output image.
+
+ @retval EFI_SUCCESS The image was successfully converted.
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+
+**/
+EFI_STATUS
+ImageToBlt (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_IMAGE_OUTPUT **Blt
+ )
+{
+ EFI_IMAGE_OUTPUT *ImageOut;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN OffsetY1; // src buffer
+ UINTN OffsetY2; // dest buffer
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;
+
+ if (BltBuffer == NULL || Blt == NULL || *Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ImageOut = *Blt;
+
+ if (Width + BltX > ImageOut->Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Height + BltY > ImageOut->Height) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for (Ypos = 0; Ypos < Height; Ypos++) {
+ OffsetY1 = Width * Ypos;
+ OffsetY2 = ImageOut->Width * (BltY + Ypos);
+ for (Xpos = 0; Xpos < Width; Xpos++) {
+ SrcPixel = BltBuffer[OffsetY1 + Xpos];
+ if (Transparent) {
+ if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ }
+ } else {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the HII package list identified by PackageList HII handle.
+
+ @param Database Pointer to HII database list header.
+ @param PackageList HII handle of the package list to locate.
+
+ @retval The HII package list instance.
+**/
+HII_DATABASE_PACKAGE_LIST_INSTANCE *
+LocatePackageList (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Record;
+
+ //
+ // Get the specified package list and image package.
+ //
+ for (Link = GetFirstNode (Database);
+ !IsNull (Database, Link);
+ Link = GetNextNode (Database, Link)
+ ) {
+ Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Record->Handle == PackageList) {
+ return Record->PackageList;
+ }
+ }
+ return NULL;
+}
+
+/**
+ This function adds the image Image to the group of images owned by PackageList, and returns
+ a new image identifier (ImageId).
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be added.
+ @param ImageId On return, contains the new image id, which is
+ unique within PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was added successfully.
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in
+ database.
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_IMAGE_ID *ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *ImageBlocks;
+ UINT32 NewBlockSize;
+
+ if (This == NULL || ImageId == NULL || Image == NULL || Image->Bitmap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ //
+ // Calcuate the size of new image.
+ // Make sure the size doesn't overflow UINT32.
+ // Note: 24Bit BMP occpuies 3 bytes per pixel.
+ //
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
+
+ //
+ // Get the image package in the package list,
+ // or create a new image package if image package does not exist.
+ //
+ if (PackageListNode->ImagePkg != NULL) {
+ ImagePackage = PackageListNode->ImagePkg;
+
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // image id of the EFI_HII_IIBT_END block of old image package.
+ //
+ *ImageId = 0;
+ GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
+
+ //
+ // Update the package's image block by appending the new block to the end.
+ //
+
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ //
+ if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
+ // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
+ //
+ ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);
+ if (ImageBlocks == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy the original content.
+ //
+ CopyMem (
+ ImageBlocks,
+ ImagePackage->ImageBlock,
+ ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ FreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlocks;
+
+ //
+ // Point to the very last block.
+ //
+ ImageBlocks = (EFI_HII_IMAGE_BLOCK *) (
+ (UINT8 *) ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ //
+ // Update the length record.
+ //
+ ImagePackage->ImageBlockSize += NewBlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize;
+
+ } else {
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ //
+ if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // The specified package list does not contain image package.
+ // Create one to add this image block.
+ //
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
+ if (ImagePackage == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // first image block so that id is initially to one.
+ //
+ *ImageId = 1;
+ //
+ // Fill in image package header.
+ //
+ ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
+ ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
+ ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
+
+ //
+ // Fill in palette info.
+ //
+ ImagePackage->PaletteBlock = NULL;
+ ImagePackage->PaletteInfoSize = 0;
+
+ //
+ // Fill in image blocks.
+ //
+ ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
+ ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));
+ if (ImagePackage->ImageBlock == NULL) {
+ FreePool (ImagePackage);
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageBlocks = ImagePackage->ImageBlock;
+
+ //
+ // Insert this image package.
+ //
+ PackageListNode->ImagePkg = ImagePackage;
+ PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ //
+ // Append the new block here
+ //
+ if (Image->Flags == EFI_IMAGE_TRANSPARENT) {
+ ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Width, Image->Width);
+ WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Height, Image->Height);
+ CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Bitmap, Image->Bitmap, (UINT32) Image->Width * Image->Height);
+
+ //
+ // Append the block end
+ //
+ ImageBlocks = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + NewBlockSize);
+ ImageBlocks->BlockType = EFI_HII_IIBT_END;
+
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo(&Private->HiiDatabase);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param Database A pointer to the database list header.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+ @param BitmapOnly TRUE to only return the bitmap type image.
+ FALSE to locate image decoder instance to decode image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+**/
+EFI_STATUS
+IGetImage (
+ IN LIST_ENTRY *Database,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image,
+ IN BOOLEAN BitmapOnly
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN ImageLength;
+ UINT8 *PaletteInfo;
+ UINT8 PaletteIndex;
+ UINT16 PaletteSize;
+ EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
+ EFI_IMAGE_OUTPUT *ImageOut;
+
+ if (Image == NULL || ImageId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageListNode = LocatePackageList (Database, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
+ if (CurrentImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Image->Flags = 0;
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ case EFI_HII_IIBT_IMAGE_PNG:
+ if (BitmapOnly) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ImageOut = NULL;
+ Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
+ if (Decoder == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Use the common block code since the definition of two structures is the same.
+ //
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
+ ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Data));
+ ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
+ ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size) ==
+ sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size));
+ Status = Decoder->DecodeImage (
+ Decoder,
+ ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data,
+ ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size,
+ &ImageOut,
+ FALSE
+ );
+
+ //
+ // Spec requires to use the first capable image decoder instance.
+ // The first image decoder instance may fail to decode the image.
+ //
+ if (!EFI_ERROR (Status)) {
+ Image->Bitmap = ImageOut->Image.Bitmap;
+ Image->Height = ImageOut->Height;
+ Image->Width = ImageOut->Width;
+ FreePool (ImageOut);
+ }
+ return Status;
+
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ //
+ // Use the common block code since the definition of these structures is the same.
+ //
+ CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageLength = (UINTN) Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Image->Bitmap = AllocateZeroPool (ImageLength);
+ if (Image->Bitmap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image->Width = Iibt1bit.Bitmap.Width;
+ Image->Height = Iibt1bit.Bitmap.Height;
+
+ PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
+ for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteInfo += PaletteSize + sizeof (UINT16);
+ }
+ ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
+
+ //
+ // Output bitmap data
+ //
+ if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT ||
+ CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
+ Output1bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT ||
+ CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
+ Output4bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else {
+ Output8bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ }
+
+ return EFI_SUCCESS;
+
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ Width = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width);
+ Height = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height);
+ ImageLength = (UINTN)Width * Height;
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ Image->Bitmap = AllocateZeroPool (ImageLength);
+ if (Image->Bitmap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Image->Width = Width;
+ Image->Height = Height;
+
+ //
+ // Output the bitmap data directly.
+ //
+ Output24bitPixel (
+ Image,
+ ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Bitmap
+ );
+ return EFI_SUCCESS;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ This function retrieves the image specified by ImageId which is associated with
+ the specified PackageList and copies it into the buffer specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList Handle of the package list where this image will
+ be searched.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was returned successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
+ hold the image.
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
+ @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
+ enough memory.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ OUT EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, TRUE);
+}
+
+
+/**
+ This function updates the image specified by ImageId in the specified PackageListHandle to
+ the image specified by Image.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param PackageList The package list containing the images.
+ @param ImageId The image's id,, which is unique within
+ PackageList.
+ @param Image Points to the image.
+
+ @retval EFI_SUCCESS The new image was updated successfully.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the
+ database. The specified PackageList is not in the database.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiSetImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN CONST EFI_IMAGE_INPUT *Image
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
+ EFI_HII_IMAGE_BLOCK *ImageBlocks;
+ EFI_HII_IMAGE_BLOCK *NewImageBlock;
+ UINT32 NewBlockSize;
+ UINT32 OldBlockSize;
+ UINT32 Part1Size;
+ UINT32 Part2Size;
+
+ if (This == NULL || Image == NULL || ImageId == 0 || Image->Bitmap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
+ if (CurrentImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EfiAcquireLock (&mHiiDatabaseLock);
+
+ //
+ // Get the size of original image block. Use some common block code here
+ // since the definition of some structures is the same.
+ //
+ switch (CurrentImageBlock->BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ OldBlockSize = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);
+ break;
+ case EFI_HII_IIBT_IMAGE_PNG:
+ OldBlockSize = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size);
+ break;
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (
+ (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (
+ (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
+ ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
+ );
+ break;
+ default:
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Create the new image block according to input image.
+ //
+
+ //
+ // Make sure the final package length doesn't overflow.
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
+ // 24Bit BMP occpuies 3 bytes per pixel.
+ //
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
+ if ((NewBlockSize > OldBlockSize) &&
+ (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)
+ ) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Adjust the image package to remove the original block firstly then add the new block.
+ //
+ ImageBlocks = AllocateZeroPool (ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize);
+ if (ImageBlocks == NULL) {
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Part1Size = (UINT32) ((UINTN) CurrentImageBlock - (UINTN) ImagePackage->ImageBlock);
+ Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
+ CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);
+
+ //
+ // Set the new image block
+ //
+ NewImageBlock = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + Part1Size);
+ if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ NewImageBlock->BlockType= EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Width, Image->Width);
+ WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Height, Image->Height);
+ CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Bitmap,
+ Image->Bitmap, (UINT32) Image->Width * Image->Height);
+
+ CopyMem ((UINT8 *) NewImageBlock + NewBlockSize, (UINT8 *) CurrentImageBlock + OldBlockSize, Part2Size);
+
+ FreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlocks;
+ ImagePackage->ImageBlockSize += NewBlockSize - OldBlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
+
+ //
+ // Check whether need to get the contents of HiiDataBase.
+ // Only after ReadyToBoot to do the export.
+ //
+ if (gExportAfterReadyToBoot) {
+ HiiGetDatabaseInfo(&Private->HiiDatabase);
+ }
+
+ EfiReleaseLock (&mHiiDatabaseLock);
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param Image Points to the image to be displayed.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.
+ If this points to a NULL on entry, then a buffer
+ will be allocated to hold the generated image and
+ the pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
+ @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImage (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN CONST EFI_IMAGE_INPUT *Image,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ BOOLEAN Transparent;
+ EFI_IMAGE_OUTPUT *ImageOut;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ UINTN BufferLen;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN OffsetY1;
+ UINTN OffsetY2;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+ UINTN Index;
+
+ if (This == NULL || Image == NULL || Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FontInfo = NULL;
+
+ //
+ // Check whether the image will be drawn transparently or opaquely.
+ //
+ Transparent = FALSE;
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
+ Transparent = TRUE;
+ } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){
+ Transparent = FALSE;
+ } else {
+ //
+ // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
+ // on the image's transparency setting.
+ //
+ if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ Transparent = TRUE;
+ }
+ }
+
+ //
+ // Image cannot be drawn transparently if Blt points to NULL on entry.
+ // Currently output to Screen transparently is not supported, either.
+ //
+ if (Transparent) {
+ if (*Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // When Blt points to a non-NULL on entry, this image will be drawn onto
+ // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
+ // Otherwise a new bitmap will be allocated to hold this image.
+ //
+ if (*Blt != NULL) {
+ //
+ // Make sure the BltX and BltY is inside the Blt area.
+ //
+ if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Clip the image by (Width, Height)
+ //
+
+ Width = Image->Width;
+ Height = Image->Height;
+
+ if (Width > (*Blt)->Width - (UINT16)BltX) {
+ Width = (*Blt)->Width - (UINT16)BltX;
+ }
+ if (Height > (*Blt)->Height - (UINT16)BltY) {
+ Height = (*Blt)->Height - (UINT16)BltY;
+ }
+
+ //
+ // Prepare the buffer for the temporary image.
+ // Make sure the buffer size doesn't overflow UINTN.
+ //
+ BufferLen = Width * Height;
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Width == Image->Width && Height == Image->Height) {
+ CopyMem (BltBuffer, Image->Bitmap, BufferLen);
+ } else {
+ for (Ypos = 0; Ypos < Height; Ypos++) {
+ OffsetY1 = Image->Width * Ypos;
+ OffsetY2 = Width * Ypos;
+ for (Xpos = 0; Xpos < Width; Xpos++) {
+ BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];
+ }
+ }
+ }
+
+ //
+ // Draw the image to existing bitmap or screen depending on flag.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ //
+ // Caller should make sure the current UGA console is grarphic mode.
+ //
+
+ //
+ // Write the image directly to the output device specified by Screen.
+ //
+ Status = (*Blt)->Image.Screen->Blt (
+ (*Blt)->Image.Screen,
+ BltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ 0
+ );
+ } else {
+ //
+ // Draw the image onto the existing bitmap specified by Bitmap.
+ //
+ Status = ImageToBlt (
+ BltBuffer,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ Transparent,
+ Blt
+ );
+
+ }
+
+ FreePool (BltBuffer);
+ return Status;
+
+ } else {
+ //
+ // Allocate a new bitmap to hold the incoming image.
+ //
+
+ //
+ // Make sure the final width and height doesn't overflow UINT16.
+ //
+ if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Width = Image->Width + (UINT16)BltX;
+ Height = Image->Height + (UINT16)BltY;
+
+ //
+ // Make sure the output image size doesn't overflow UINTN.
+ //
+ BufferLen = Width * Height;
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (ImageOut == NULL) {
+ FreePool (BltBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageOut->Width = Width;
+ ImageOut->Height = Height;
+ ImageOut->Image.Bitmap = BltBuffer;
+
+ //
+ // BUGBUG: Now all the "blank" pixels are filled with system default background
+ // color. Not sure if it need to be updated or not.
+ //
+ Status = GetSystemFont (Private, &FontInfo, NULL);
+ if (EFI_ERROR (Status)) {
+ FreePool (BltBuffer);
+ FreePool (ImageOut);
+ return Status;
+ }
+ ASSERT (FontInfo != NULL);
+ for (Index = 0; Index < (UINTN)Width * Height; Index++) {
+ BltBuffer[Index] = FontInfo->BackgroundColor;
+ }
+ FreePool (FontInfo);
+
+ //
+ // Draw the incoming image to the new created image.
+ //
+ *Blt = ImageOut;
+ return ImageToBlt (
+ Image->Bitmap,
+ BltX,
+ BltY,
+ Image->Width,
+ Image->Height,
+ Transparent,
+ Blt
+ );
+
+ }
+}
+
+
+/**
+ This function renders an image to a bitmap or the screen using the specified
+ color and options. It draws the image on an existing bitmap, allocates a new
+ bitmap or uses the screen. The images can be clipped.
+
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
+ @param Flags Describes how the image is to be drawn.
+ @param PackageList The package list in the HII database to search for
+ the specified image.
+ @param ImageId The image's id, which is unique within
+ PackageList.
+ @param Blt If this points to a non-NULL on entry, this points
+ to the image, which is Width pixels wide and
+ Height pixels high. The image will be drawn onto
+ this image and
+ EFI_HII_DRAW_FLAG_CLIP is implied. If this points
+ to a NULL on entry, then a buffer will be
+ allocated to hold the generated image and the
+ pointer updated on exit. It is the caller's
+ responsibility to free this buffer.
+ @param BltX Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+
+ @retval EFI_SUCCESS The image was successfully drawn.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
+ @retval EFI_INVALID_PARAMETER The Blt was NULL.
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
+ The specified PackageList is not in the database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiDrawImageId (
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,
+ IN EFI_HII_DRAW_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_IMAGE_ID ImageId,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_INPUT Image;
+
+ //
+ // Check input parameter.
+ //
+ if (This == NULL || Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the specified Image.
+ //
+ Status = HiiGetImage (This, PackageList, ImageId, &Image);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Draw this image.
+ //
+ Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
+ if (Image.Bitmap != NULL) {
+ FreePool (Image.Bitmap);
+ }
+ return Status;
+}
+