diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe/Image.c')
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | 3166 |
1 files changed, 1583 insertions, 1583 deletions
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c index b5b9625969..afb312c361 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c @@ -1,1583 +1,1583 @@ -/** @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;
-}
+/** @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; +} |
