From 101a1122095d57629f59989962198e27181d0308 Mon Sep 17 00:00:00 2001 From: Ruiyu Ni Date: Wed, 21 Sep 2016 17:48:13 +0800 Subject: [PATCH] MdeModulePkg/HiiDatabase: Add HiiImageEx implementation. According to UEFI spec, NewImageEx()/SetImageEx()/DrawImageEx() implicitly call the non-Ex version interface of HiiImage protocol. GetImageEx()/DrawImageIdEx() are the enhanced version of GetImage()/DrawImageId(), which can support decoding JPEG/PNG through the help of HiiImageDecoder protocol. Contributed-under: TianoCore Contribution Agreement 1.0 Reviewed-by: Liming Gao Cc: Eric Dong Cc: Dandan Bi Signed-off-by: Ruiyu Ni --- .../Universal/HiiDatabaseDxe/HiiDatabase.h | 293 +++++++++++- .../HiiDatabaseDxe/HiiDatabaseDxe.inf | 7 +- .../HiiDatabaseDxe/HiiDatabaseEntry.c | 32 +- MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | 120 +++-- .../Universal/HiiDatabaseDxe/ImageEx.c | 423 ++++++++++++++++++ 5 files changed, 822 insertions(+), 53 deletions(-) create mode 100644 MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h index 0ca2fba5ec..ee4936466a 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h @@ -20,6 +20,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include +#include #include #include #include @@ -301,6 +303,7 @@ typedef struct _HII_DATABASE_PRIVATE_DATA { LIST_ENTRY DatabaseNotifyList; EFI_HII_FONT_PROTOCOL HiiFont; EFI_HII_IMAGE_PROTOCOL HiiImage; + EFI_HII_IMAGE_EX_PROTOCOL HiiImageEx; EFI_HII_STRING_PROTOCOL HiiString; EFI_HII_DATABASE_PROTOCOL HiiDatabase; EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting; @@ -327,6 +330,13 @@ typedef struct _HII_DATABASE_PRIVATE_DATA { HII_DATABASE_PRIVATE_DATA_SIGNATURE \ ) +#define HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + HII_DATABASE_PRIVATE_DATA, \ + HiiImageEx, \ + HII_DATABASE_PRIVATE_DATA_SIGNATURE \ + ) + #define HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS(a) \ CR (a, \ HII_DATABASE_PRIVATE_DATA, \ @@ -813,6 +823,82 @@ HiiGetFontInfo ( // EFI_HII_IMAGE_PROTOCOL interfaces // +/** + Get the image id 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Return the first HII image decoder instance which supports the DecoderName. + + @param BlockType The image block type. + + @retval Pointer to the HII image decoder instance. +**/ +EFI_HII_IMAGE_DECODER_PROTOCOL * +LocateHiiImageDecoder ( + UINT8 BlockType + ); /** This function adds the image Image to the group of images owned by PackageList, and returns @@ -984,10 +1070,213 @@ HiiDrawImageId ( IN OUT EFI_IMAGE_OUTPUT **Blt, IN UINTN BltX, IN UINTN BltY - ) + ); -; +/** + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage(). + This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 PackageList could not be found. + @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 +HiiNewImageEx ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_IMAGE_ID *ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ); +/** + Return the information about the image, associated with the package list. + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage(). + + This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage(). The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @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 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 available. The specified + PackageList is not in the Database. + @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +EFI_STATUS +EFIAPI +HiiGetImageEx ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_INPUT *Image + ); + +/** + Change the information about the image. + + Same with EFI_HII_IMAGE_PROTOCOL.SetImage(), this protocol invokes + EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 successfully updated. + @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, the ImageId was 0 or + the Image->Bitmap was NULL. + +**/ +EFI_STATUS +EFIAPI +HiiSetImageEx ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ); + +/** + Renders an image to a bitmap or to the display. + + The prototype of this extension function is the same with + EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes + EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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. + +**/ +EFI_STATUS +EFIAPI +HiiDrawImageEx ( + IN CONST EFI_HII_IMAGE_EX_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 + ); + +/** + Renders an image to a bitmap or the screen containing the contents of the specified + image. + + This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 or ImageId was 0. + @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 +HiiDrawImageIdEx ( + IN CONST EFI_HII_IMAGE_EX_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 + ); + +/** + This function returns the image information to EFI_IMAGE_OUTPUT. Only the width + and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image + to the buffer. This function is used to get the geometry of the image. This function + will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the + system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 was NULL or the ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +EFI_STATUS +EFIAPI +HiiGetImageInfo ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_OUTPUT *Image + ); // // EFI_HII_STRING_PROTOCOL // diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf index 2fb619e05a..f82a1f48fe 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf @@ -35,6 +35,7 @@ [Sources] HiiDatabaseEntry.c Image.c + ImageEx.c HiiDatabase.h ConfigRouting.c String.c @@ -63,7 +64,9 @@ [Protocols] gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES gEfiHiiStringProtocolGuid ## PRODUCES - gEfiHiiImageProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES + gEfiHiiImageProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES + gEfiHiiImageExProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_PRODUCES + gEfiHiiImageDecoderProtocolGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES gEfiHiiConfigRoutingProtocolGuid ## PRODUCES gEfiHiiDatabaseProtocolGuid ## PRODUCES gEfiHiiFontProtocolGuid ## PRODUCES @@ -85,6 +88,8 @@ ## CONSUMES ## Event ## PRODUCES ## Event gEfiHiiKeyBoardLayoutGuid + gEfiHiiImageDecoderNameJpegGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES + gEfiHiiImageDecoderNamePngGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES [Depex] TRUE diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c index b48254f670..9d09c60b23 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c @@ -39,11 +39,19 @@ HII_DATABASE_PRIVATE_DATA mPrivate = { HiiGetFontInfo }, { - NULL, - NULL, - NULL, - NULL, - NULL + HiiNewImage, + HiiGetImage, + HiiSetImage, + HiiDrawImage, + HiiDrawImageId + }, + { + HiiNewImageEx, + HiiGetImageEx, + HiiSetImageEx, + HiiDrawImageEx, + HiiDrawImageIdEx, + HiiGetImageInfo }, { HiiNewString, @@ -96,14 +104,6 @@ HII_DATABASE_PRIVATE_DATA mPrivate = { NULL }; -GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_IMAGE_PROTOCOL mImageProtocol = { - HiiNewImage, - HiiGetImage, - HiiSetImage, - HiiDrawImage, - HiiDrawImageId -}; - /** The default event handler for gHiiKeyboardLayoutChanged event group. @@ -230,12 +230,10 @@ InitializeHiiDatabase ( } if (FeaturePcdGet (PcdSupportHiiImageProtocol)) { - CopyMem (&mPrivate.HiiImage, &mImageProtocol, sizeof (mImageProtocol)); - Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, - &gEfiHiiImageProtocolGuid, - &mPrivate.HiiImage, + &gEfiHiiImageProtocolGuid, &mPrivate.HiiImage, + &gEfiHiiImageExProtocolGuid, &mPrivate.HiiImageEx, NULL ); diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c index c8e9258ba6..1668828486 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c @@ -643,10 +643,6 @@ HiiNewImage ( return EFI_INVALID_PARAMETER; } - if (!IsHiiHandleValid (PackageList)) { - return EFI_NOT_FOUND; - } - Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This); PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList); if (PackageListNode == NULL) { @@ -781,33 +777,34 @@ HiiNewImage ( 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 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_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. - + enough memory. **/ EFI_STATUS -EFIAPI -HiiGetImage ( - IN CONST EFI_HII_IMAGE_PROTOCOL *This, +IGetImage ( + IN LIST_ENTRY *Database, IN EFI_HII_HANDLE PackageList, IN EFI_IMAGE_ID ImageId, - OUT EFI_IMAGE_INPUT *Image + OUT EFI_IMAGE_INPUT *Image, + IN BOOLEAN BitmapOnly ) { - HII_DATABASE_PRIVATE_DATA *Private; + EFI_STATUS Status; HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; HII_IMAGE_PACKAGE_INSTANCE *ImagePackage; EFI_HII_IMAGE_BLOCK *CurrentImageBlock; @@ -818,17 +815,14 @@ HiiGetImage ( UINT8 *PaletteInfo; UINT8 PaletteIndex; UINT16 PaletteSize; + EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder; + EFI_IMAGE_OUTPUT *ImageOut; - if (This == NULL || Image == NULL || ImageId == 0) { + if (Image == NULL || ImageId == 0) { return EFI_INVALID_PARAMETER; } - if (!IsHiiHandleValid (PackageList)) { - return EFI_NOT_FOUND; - } - - Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This); - PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList); + PackageListNode = LocatePackageList (Database, PackageList); if (PackageListNode == NULL) { return EFI_NOT_FOUND; } @@ -845,14 +839,47 @@ HiiGetImage ( 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; + } // - // HiiImage protocol doesn't support return JPEG/PNG. - // Use HiiImageEx instead. + // Use the common block code since the definition of two structures is the same. // - return EFI_UNSUPPORTED; + 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: @@ -870,7 +897,7 @@ HiiGetImage ( CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK)); ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height); - Image->Bitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (ImageLength); + Image->Bitmap = AllocateZeroPool (ImageLength); if (Image->Bitmap == NULL) { return EFI_OUT_OF_RESOURCES; } @@ -943,6 +970,41 @@ HiiGetImage ( } } +/** + 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 @@ -984,10 +1046,6 @@ HiiSetImage ( return EFI_INVALID_PARAMETER; } - if (!IsHiiHandleValid (PackageList)) { - return EFI_NOT_FOUND; - } - Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This); PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList); if (PackageListNode == NULL) { @@ -1394,10 +1452,6 @@ HiiDrawImageId ( return EFI_INVALID_PARAMETER; } - if (!IsHiiHandleValid (PackageList)) { - return EFI_NOT_FOUND; - } - // // Get the specified Image. // diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c new file mode 100644 index 0000000000..1e3f3bd1c8 --- /dev/null +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ImageEx.c @@ -0,0 +1,423 @@ +/** @file +Implementation for EFI_HII_IMAGE_EX_PROTOCOL. + + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "HiiDatabase.h" + +/** + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage(). + This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 PackageList could not be found. + @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 +HiiNewImageEx ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_IMAGE_ID *ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ) +{ + HII_DATABASE_PRIVATE_DATA *Private; + + Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This); + return HiiNewImage (&Private->HiiImage, PackageList, ImageId, Image); +} + +/** + Return the information about the image, associated with the package list. + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage(). + + This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage().The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @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 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 available. The specified + PackageList is not in the Database. + @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +EFI_STATUS +EFIAPI +HiiGetImageEx ( + IN CONST EFI_HII_IMAGE_EX_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_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This); + return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, FALSE); +} + + +/** + Change the information about the image. + + Same with EFI_HII_IMAGE_PROTOCOL.SetImage(),this protocol invokes + EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 successfully updated. + @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, the ImageId was 0 or + the Image->Bitmap was NULL. + +**/ +EFI_STATUS +EFIAPI +HiiSetImageEx ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ) +{ + HII_DATABASE_PRIVATE_DATA *Private; + Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This); + return HiiSetImage (&Private->HiiImage, PackageList, ImageId, Image); +} + + +/** + Renders an image to a bitmap or to the display. + + The prototype of this extension function is the same with + EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes + EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_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. + +**/ +EFI_STATUS +EFIAPI +HiiDrawImageEx ( + IN CONST EFI_HII_IMAGE_EX_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 + ) +{ + HII_DATABASE_PRIVATE_DATA *Private; + Private = HII_IMAGE_EX_DATABASE_PRIVATE_DATA_FROM_THIS (This); + return HiiDrawImage (&Private->HiiImage, Flags, Image, Blt, BltX, BltY); +} + + +/** + Renders an image to a bitmap or the screen containing the contents of the specified + image. + + This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 or ImageId was 0. + @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 +HiiDrawImageIdEx ( + IN CONST EFI_HII_IMAGE_EX_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 = HiiGetImageEx (This, PackageList, ImageId, &Image); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Draw this image. + // + Status = HiiDrawImageEx (This, Flags, &Image, Blt, BltX, BltY); + if (Image.Bitmap != NULL) { + FreePool (Image.Bitmap); + } + return Status; +} + +/** + Return the first HII image decoder instance which supports the DecoderName. + + @param BlockType The image block type. + + @retval Pointer to the HII image decoder instance. +**/ +EFI_HII_IMAGE_DECODER_PROTOCOL * +LocateHiiImageDecoder ( + UINT8 BlockType + ) +{ + EFI_STATUS Status; + EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder; + EFI_HANDLE *Handles; + UINTN HandleNum; + UINTN Index; + EFI_GUID *DecoderNames; + UINT16 NumberOfDecoderName; + UINT16 DecoderNameIndex; + EFI_GUID *DecoderName; + + switch (BlockType) { + case EFI_HII_IIBT_IMAGE_JPEG: + DecoderName = &gEfiHiiImageDecoderNameJpegGuid; + break; + + case EFI_HII_IIBT_IMAGE_PNG: + DecoderName = &gEfiHiiImageDecoderNamePngGuid; + break; + + default: + ASSERT (FALSE); + return NULL; + } + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiHiiImageDecoderProtocolGuid, NULL, &HandleNum, &Handles); + if (EFI_ERROR (Status)) { + return NULL; + } + for (Index = 0; Index < HandleNum; Index++) { + Status = gBS->HandleProtocol (Handles[Index], &gEfiHiiImageDecoderProtocolGuid, (VOID **) &Decoder); + if (EFI_ERROR (Status)) { + continue; + } + + Status = Decoder->GetImageDecoderName (Decoder, &DecoderNames, &NumberOfDecoderName); + if (EFI_ERROR (Status)) { + continue; + } + for (DecoderNameIndex = 0; DecoderNameIndex < NumberOfDecoderName; DecoderNameIndex++) { + if (CompareGuid (DecoderName, &DecoderNames[DecoderNameIndex])) { + return Decoder; + } + } + } + + return NULL; +} + +/** + This function returns the image information to EFI_IMAGE_OUTPUT. Only the width + and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image + to the buffer. This function is used to get the geometry of the image. This function + will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the + system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL. + + @param This A pointer to the EFI_HII_IMAGE_EX_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 was NULL or the ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +EFI_STATUS +EFIAPI +HiiGetImageInfo ( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_OUTPUT *Image + ) +{ + EFI_STATUS Status; + HII_DATABASE_PRIVATE_DATA *Private; + HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; + HII_IMAGE_PACKAGE_INSTANCE *ImagePackage; + EFI_HII_IMAGE_BLOCK *CurrentImageBlock; + EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder; + EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER *ImageInfo; + + if (Image == NULL || ImageId == 0) { + return EFI_INVALID_PARAMETER; + } + + Private = HII_IMAGE_EX_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); + switch (CurrentImageBlock->BlockType) { + case EFI_HII_IIBT_IMAGE_JPEG: + case EFI_HII_IIBT_IMAGE_PNG: + 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->GetImageInfo ( + Decoder, + ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data, + ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size, + &ImageInfo + ); + + // + // 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->Height = ImageInfo->ImageHeight; + Image->Width = ImageInfo->ImageWidth; + Image->Image.Bitmap = NULL; + FreePool (ImageInfo); + } + return Status; + + case EFI_HII_IIBT_IMAGE_1BIT_TRANS: + case EFI_HII_IIBT_IMAGE_4BIT_TRANS: + case EFI_HII_IIBT_IMAGE_8BIT_TRANS: + 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. + // + Image->Width = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width); + Image->Height = ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height); + Image->Image.Bitmap = NULL; + return EFI_SUCCESS; + + case EFI_HII_IIBT_IMAGE_24BIT_TRANS: + case EFI_HII_IIBT_IMAGE_24BIT: + Image->Width = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width); + Image->Height = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height); + Image->Image.Bitmap = NULL; + return EFI_SUCCESS; + + default: + return EFI_NOT_FOUND; + } +} -- 2.39.2