summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-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.c3166
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;
+}