2 Implementation for EFI_HII_IMAGE_PROTOCOL.
5 Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "HiiDatabase.h"
13 #define MAX_UINT24 0xFFFFFF
16 Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
17 ImageId is zero, otherwise return the address of the
18 corresponding image block with identifier specified by ImageId.
20 This is a internal function.
22 @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
23 @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
24 else use this id to find its corresponding image block address.
26 @return The image block address when input ImageId is not zero; otherwise return NULL.
31 IN EFI_HII_IMAGE_BLOCK
*ImageBlocks
,
32 IN OUT EFI_IMAGE_ID
*ImageId
35 EFI_IMAGE_ID ImageIdCurrent
;
36 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
39 ASSERT (ImageBlocks
!= NULL
&& ImageId
!= NULL
);
40 CurrentImageBlock
= ImageBlocks
;
43 while (CurrentImageBlock
->BlockType
!= EFI_HII_IIBT_END
) {
45 if (*ImageId
== ImageIdCurrent
) {
47 // If the found image block is a duplicate block, update the ImageId to
48 // find the previous defined image block.
50 if (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_DUPLICATE
) {
51 *ImageId
= ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_DUPLICATE_BLOCK
*) CurrentImageBlock
)->ImageId
);
52 ASSERT (*ImageId
!= ImageIdCurrent
);
53 ASSERT (*ImageId
!= 0);
54 CurrentImageBlock
= ImageBlocks
;
59 return CurrentImageBlock
;
61 if (*ImageId
< ImageIdCurrent
) {
63 // Can not find the specified image block in this image.
68 switch (CurrentImageBlock
->BlockType
) {
69 case EFI_HII_IIBT_EXT1
:
70 Length
= ((EFI_HII_IIBT_EXT1_BLOCK
*) CurrentImageBlock
)->Length
;
72 case EFI_HII_IIBT_EXT2
:
73 Length
= ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK
*) CurrentImageBlock
)->Length
);
75 case EFI_HII_IIBT_EXT4
:
76 Length
= ReadUnaligned32 ((VOID
*) &((EFI_HII_IIBT_EXT4_BLOCK
*) CurrentImageBlock
)->Length
);
79 case EFI_HII_IIBT_IMAGE_1BIT
:
80 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
81 Length
= sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
) - sizeof (UINT8
) +
83 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
84 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
89 case EFI_HII_IIBT_IMAGE_4BIT
:
90 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
91 Length
= sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK
) - sizeof (UINT8
) +
93 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
94 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
99 case EFI_HII_IIBT_IMAGE_8BIT
:
100 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
101 Length
= sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK
) - sizeof (UINT8
) +
103 (UINT32
) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
104 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
109 case EFI_HII_IIBT_IMAGE_24BIT
:
110 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
111 Length
= sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
) +
113 (UINT32
) ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
114 ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
119 case EFI_HII_IIBT_DUPLICATE
:
120 Length
= sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK
);
124 case EFI_HII_IIBT_IMAGE_JPEG
:
125 Length
= OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*) &((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Size
);
129 case EFI_HII_IIBT_IMAGE_PNG
:
130 Length
= OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*) &((EFI_HII_IIBT_PNG_BLOCK
*) CurrentImageBlock
)->Size
);
134 case EFI_HII_IIBT_SKIP1
:
135 Length
= sizeof (EFI_HII_IIBT_SKIP1_BLOCK
);
136 ImageIdCurrent
+= ((EFI_HII_IIBT_SKIP1_BLOCK
*) CurrentImageBlock
)->SkipCount
;
139 case EFI_HII_IIBT_SKIP2
:
140 Length
= sizeof (EFI_HII_IIBT_SKIP2_BLOCK
);
141 ImageIdCurrent
+= ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_SKIP2_BLOCK
*) CurrentImageBlock
)->SkipCount
);
146 // Unknown image blocks can not be skipped, processing halts.
153 CurrentImageBlock
= (EFI_HII_IMAGE_BLOCK
*) ((UINT8
*) CurrentImageBlock
+ Length
);
158 // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
161 *ImageId
= ImageIdCurrent
;
162 return CurrentImageBlock
;
171 Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
173 This is a internal function.
176 @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
177 @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
178 @param PixelNum The number of pixels to be converted.
184 OUT EFI_HII_RGB_PIXEL
*BitMapOut
,
185 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapIn
,
191 ASSERT (BitMapOut
!= NULL
&& BitMapIn
!= NULL
);
193 for (Index
= 0; Index
< PixelNum
; Index
++) {
194 CopyMem (BitMapOut
+ Index
, BitMapIn
+ Index
, sizeof (EFI_HII_RGB_PIXEL
));
200 Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
202 This is a internal function.
205 @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
206 @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
207 @param PixelNum The number of pixels to be converted.
213 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapOut
,
214 IN EFI_HII_RGB_PIXEL
*BitMapIn
,
220 ASSERT (BitMapOut
!= NULL
&& BitMapIn
!= NULL
);
222 for (Index
= 0; Index
< PixelNum
; Index
++) {
223 CopyMem (BitMapOut
+ Index
, BitMapIn
+ Index
, sizeof (EFI_HII_RGB_PIXEL
));
229 Output pixels in "1 bit per pixel" format to an image.
231 This is a internal function.
234 @param Image Points to the image which will store the pixels.
235 @param Data Stores the value of output pixels, 0 or 1.
236 @param PaletteInfo PaletteInfo which stores the color of the output
237 pixels. First entry corresponds to color 0 and
238 second one to color 1.
244 IN OUT EFI_IMAGE_INPUT
*Image
,
246 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
253 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
254 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[2];
255 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
259 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
261 BitMapPtr
= Image
->Bitmap
;
264 // First entry corresponds to color 0 and second entry corresponds to color 1.
267 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
268 PaletteSize
+= sizeof (UINT16
);
269 Palette
= AllocateZeroPool (PaletteSize
);
270 ASSERT (Palette
!= NULL
);
271 if (Palette
== NULL
) {
274 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
276 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
277 CopyRgbToGopPixel (&PaletteValue
[0], &Palette
->PaletteValue
[0], 1);
278 CopyRgbToGopPixel (&PaletteValue
[1], &Palette
->PaletteValue
[1], 1);
282 // Convert the pixel from one bit to corresponding color.
284 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
285 OffsetY
= BITMAP_LEN_1_BIT (Image
->Width
, Ypos
);
287 // All bits in these bytes are meaningful
289 for (Xpos
= 0; Xpos
< Image
->Width
/ 8; Xpos
++) {
290 Byte
= *(Data
+ OffsetY
+ Xpos
);
291 for (Index
= 0; Index
< 8; Index
++) {
292 if ((Byte
& (1 << Index
)) != 0) {
293 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + (8 - Index
- 1)] = PaletteValue
[1];
295 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + (8 - Index
- 1)] = PaletteValue
[0];
300 if (Image
->Width
% 8 != 0) {
302 // Padding bits in this byte should be ignored.
304 Byte
= *(Data
+ OffsetY
+ Xpos
);
305 for (Index
= 0; Index
< Image
->Width
% 8; Index
++) {
306 if ((Byte
& (1 << (8 - Index
- 1))) != 0) {
307 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + Index
] = PaletteValue
[1];
309 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + Index
] = PaletteValue
[0];
318 Output pixels in "4 bit per pixel" format to an image.
320 This is a internal function.
323 @param Image Points to the image which will store the pixels.
324 @param Data Stores the value of output pixels, 0 ~ 15.
325 @param[in] PaletteInfo PaletteInfo which stores the color of the output
326 pixels. Each entry corresponds to a color within
333 IN OUT EFI_IMAGE_INPUT
*Image
,
335 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
341 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
342 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[16];
343 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
348 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
350 BitMapPtr
= Image
->Bitmap
;
353 // The bitmap should allocate each color index starting from 0.
356 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
357 PaletteSize
+= sizeof (UINT16
);
358 Palette
= AllocateZeroPool (PaletteSize
);
359 ASSERT (Palette
!= NULL
);
360 if (Palette
== NULL
) {
363 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
364 PaletteNum
= (UINT16
)(Palette
->PaletteSize
/ sizeof (EFI_HII_RGB_PIXEL
));
366 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
367 CopyRgbToGopPixel (PaletteValue
, Palette
->PaletteValue
, MIN (PaletteNum
, ARRAY_SIZE (PaletteValue
)));
371 // Convert the pixel from 4 bit to corresponding color.
373 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
374 OffsetY
= BITMAP_LEN_4_BIT (Image
->Width
, Ypos
);
376 // All bits in these bytes are meaningful
378 for (Xpos
= 0; Xpos
< Image
->Width
/ 2; Xpos
++) {
379 Byte
= *(Data
+ OffsetY
+ Xpos
);
380 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2] = PaletteValue
[Byte
>> 4];
381 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2 + 1] = PaletteValue
[Byte
& 0x0F];
384 if (Image
->Width
% 2 != 0) {
386 // Padding bits in this byte should be ignored.
388 Byte
= *(Data
+ OffsetY
+ Xpos
);
389 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2] = PaletteValue
[Byte
>> 4];
396 Output pixels in "8 bit per pixel" format to an image.
398 This is a internal function.
401 @param Image Points to the image which will store the pixels.
402 @param Data Stores the value of output pixels, 0 ~ 255.
403 @param[in] PaletteInfo PaletteInfo which stores the color of the output
404 pixels. Each entry corresponds to a color within
411 IN OUT EFI_IMAGE_INPUT
*Image
,
413 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
419 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
420 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[256];
421 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
426 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
428 BitMapPtr
= Image
->Bitmap
;
431 // The bitmap should allocate each color index starting from 0.
434 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
435 PaletteSize
+= sizeof (UINT16
);
436 Palette
= AllocateZeroPool (PaletteSize
);
437 ASSERT (Palette
!= NULL
);
438 if (Palette
== NULL
) {
441 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
442 PaletteNum
= (UINT16
)(Palette
->PaletteSize
/ sizeof (EFI_HII_RGB_PIXEL
));
443 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
444 CopyRgbToGopPixel (PaletteValue
, Palette
->PaletteValue
, MIN (PaletteNum
, ARRAY_SIZE (PaletteValue
)));
448 // Convert the pixel from 8 bits to corresponding color.
450 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
451 OffsetY
= BITMAP_LEN_8_BIT ((UINT32
) Image
->Width
, Ypos
);
453 // All bits are meaningful since the bitmap is 8 bits per pixel.
455 for (Xpos
= 0; Xpos
< Image
->Width
; Xpos
++) {
456 Byte
= *(Data
+ OffsetY
+ Xpos
);
457 BitMapPtr
[OffsetY
+ Xpos
] = PaletteValue
[Byte
];
465 Output pixels in "24 bit per pixel" format to an image.
467 This is a internal function.
470 @param Image Points to the image which will store the pixels.
471 @param Data Stores the color of output pixels, allowing 16.8
478 IN OUT EFI_IMAGE_INPUT
*Image
,
479 IN EFI_HII_RGB_PIXEL
*Data
484 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
486 ASSERT (Image
!= NULL
&& Data
!= NULL
);
488 BitMapPtr
= Image
->Bitmap
;
490 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
491 OffsetY
= BITMAP_LEN_8_BIT ((UINT32
) Image
->Width
, Ypos
);
492 CopyRgbToGopPixel (&BitMapPtr
[OffsetY
], &Data
[OffsetY
], Image
->Width
);
499 Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
501 This is a internal function.
504 @param BltBuffer Buffer points to bitmap data of incoming image.
505 @param BltX Specifies the offset from the left and top edge of
506 the output image of the first pixel in the image.
507 @param BltY Specifies the offset from the left and top edge of
508 the output image of the first pixel in the image.
509 @param Width Width of the incoming image, in pixels.
510 @param Height Height of the incoming image, in pixels.
511 @param Transparent If TRUE, all "off" pixels in the image will be
512 drawn using the pixel value from blt and all other
513 pixels will be copied.
514 @param Blt Buffer points to bitmap data of output image.
516 @retval EFI_SUCCESS The image was successfully converted.
517 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
522 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
527 IN BOOLEAN Transparent
,
528 IN OUT EFI_IMAGE_OUTPUT
**Blt
531 EFI_IMAGE_OUTPUT
*ImageOut
;
534 UINTN OffsetY1
; // src buffer
535 UINTN OffsetY2
; // dest buffer
536 EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel
;
537 EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel
;
539 if (BltBuffer
== NULL
|| Blt
== NULL
|| *Blt
== NULL
) {
540 return EFI_INVALID_PARAMETER
;
545 if (Width
+ BltX
> ImageOut
->Width
) {
546 return EFI_INVALID_PARAMETER
;
548 if (Height
+ BltY
> ImageOut
->Height
) {
549 return EFI_INVALID_PARAMETER
;
552 ZeroMem (&ZeroPixel
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
554 for (Ypos
= 0; Ypos
< Height
; Ypos
++) {
555 OffsetY1
= Width
* Ypos
;
556 OffsetY2
= ImageOut
->Width
* (BltY
+ Ypos
);
557 for (Xpos
= 0; Xpos
< Width
; Xpos
++) {
558 SrcPixel
= BltBuffer
[OffsetY1
+ Xpos
];
560 if (CompareMem (&SrcPixel
, &ZeroPixel
, 3) != 0) {
561 ImageOut
->Image
.Bitmap
[OffsetY2
+ BltX
+ Xpos
] = SrcPixel
;
564 ImageOut
->Image
.Bitmap
[OffsetY2
+ BltX
+ Xpos
] = SrcPixel
;
573 Return the HII package list identified by PackageList HII handle.
575 @param Database Pointer to HII database list header.
576 @param PackageList HII handle of the package list to locate.
578 @retval The HII package list instance.
580 HII_DATABASE_PACKAGE_LIST_INSTANCE
*
582 IN LIST_ENTRY
*Database
,
583 IN EFI_HII_HANDLE PackageList
587 HII_DATABASE_RECORD
*Record
;
590 // Get the specified package list and image package.
592 for (Link
= GetFirstNode (Database
);
593 !IsNull (Database
, Link
);
594 Link
= GetNextNode (Database
, Link
)
596 Record
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
597 if (Record
->Handle
== PackageList
) {
598 return Record
->PackageList
;
605 This function adds the image Image to the group of images owned by PackageList, and returns
606 a new image identifier (ImageId).
608 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
609 @param PackageList Handle of the package list where this image will
611 @param ImageId On return, contains the new image id, which is
612 unique within PackageList.
613 @param Image Points to the image.
615 @retval EFI_SUCCESS The new image was added successfully.
616 @retval EFI_NOT_FOUND The specified PackageList could not be found in
618 @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
619 @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
625 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
626 IN EFI_HII_HANDLE PackageList
,
627 OUT EFI_IMAGE_ID
*ImageId
,
628 IN CONST EFI_IMAGE_INPUT
*Image
631 HII_DATABASE_PRIVATE_DATA
*Private
;
632 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
633 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
634 EFI_HII_IMAGE_BLOCK
*ImageBlocks
;
637 if (This
== NULL
|| ImageId
== NULL
|| Image
== NULL
|| Image
->Bitmap
== NULL
) {
638 return EFI_INVALID_PARAMETER
;
641 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
642 PackageListNode
= LocatePackageList (&Private
->DatabaseList
, PackageList
);
643 if (PackageListNode
== NULL
) {
644 return EFI_NOT_FOUND
;
647 EfiAcquireLock (&mHiiDatabaseLock
);
650 // Calcuate the size of new image.
651 // Make sure the size doesn't overflow UINT32.
652 // Note: 24Bit BMP occpuies 3 bytes per pixel.
654 NewBlockSize
= (UINT32
)Image
->Width
* Image
->Height
;
655 if (NewBlockSize
> (MAX_UINT32
- (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
))) / 3) {
656 EfiReleaseLock (&mHiiDatabaseLock
);
657 return EFI_OUT_OF_RESOURCES
;
659 NewBlockSize
= NewBlockSize
* 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
));
662 // Get the image package in the package list,
663 // or create a new image package if image package does not exist.
665 if (PackageListNode
->ImagePkg
!= NULL
) {
666 ImagePackage
= PackageListNode
->ImagePkg
;
669 // Output the image id of the incoming image being inserted, which is the
670 // image id of the EFI_HII_IIBT_END block of old image package.
673 GetImageIdOrAddress (ImagePackage
->ImageBlock
, ImageId
);
676 // Update the package's image block by appending the new block to the end.
680 // Make sure the final package length doesn't overflow.
681 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
683 if (NewBlockSize
> MAX_UINT24
- ImagePackage
->ImagePkgHdr
.Header
.Length
) {
684 EfiReleaseLock (&mHiiDatabaseLock
);
685 return EFI_OUT_OF_RESOURCES
;
688 // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
689 // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
691 ImageBlocks
= AllocatePool (ImagePackage
->ImageBlockSize
+ NewBlockSize
);
692 if (ImageBlocks
== NULL
) {
693 EfiReleaseLock (&mHiiDatabaseLock
);
694 return EFI_OUT_OF_RESOURCES
;
697 // Copy the original content.
701 ImagePackage
->ImageBlock
,
702 ImagePackage
->ImageBlockSize
- sizeof (EFI_HII_IIBT_END_BLOCK
)
704 FreePool (ImagePackage
->ImageBlock
);
705 ImagePackage
->ImageBlock
= ImageBlocks
;
708 // Point to the very last block.
710 ImageBlocks
= (EFI_HII_IMAGE_BLOCK
*) (
711 (UINT8
*) ImageBlocks
+ ImagePackage
->ImageBlockSize
- sizeof (EFI_HII_IIBT_END_BLOCK
)
714 // Update the length record.
716 ImagePackage
->ImageBlockSize
+= NewBlockSize
;
717 ImagePackage
->ImagePkgHdr
.Header
.Length
+= NewBlockSize
;
718 PackageListNode
->PackageListHdr
.PackageLength
+= NewBlockSize
;
722 // Make sure the final package length doesn't overflow.
723 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
725 if (NewBlockSize
> MAX_UINT24
- (sizeof (EFI_HII_IMAGE_PACKAGE_HDR
) + sizeof (EFI_HII_IIBT_END_BLOCK
))) {
726 EfiReleaseLock (&mHiiDatabaseLock
);
727 return EFI_OUT_OF_RESOURCES
;
730 // The specified package list does not contain image package.
731 // Create one to add this image block.
733 ImagePackage
= (HII_IMAGE_PACKAGE_INSTANCE
*) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE
));
734 if (ImagePackage
== NULL
) {
735 EfiReleaseLock (&mHiiDatabaseLock
);
736 return EFI_OUT_OF_RESOURCES
;
739 // Output the image id of the incoming image being inserted, which is the
740 // first image block so that id is initially to one.
744 // Fill in image package header.
746 ImagePackage
->ImagePkgHdr
.Header
.Length
= sizeof (EFI_HII_IMAGE_PACKAGE_HDR
) + NewBlockSize
+ sizeof (EFI_HII_IIBT_END_BLOCK
);
747 ImagePackage
->ImagePkgHdr
.Header
.Type
= EFI_HII_PACKAGE_IMAGES
;
748 ImagePackage
->ImagePkgHdr
.ImageInfoOffset
= sizeof (EFI_HII_IMAGE_PACKAGE_HDR
);
749 ImagePackage
->ImagePkgHdr
.PaletteInfoOffset
= 0;
752 // Fill in palette info.
754 ImagePackage
->PaletteBlock
= NULL
;
755 ImagePackage
->PaletteInfoSize
= 0;
758 // Fill in image blocks.
760 ImagePackage
->ImageBlockSize
= NewBlockSize
+ sizeof (EFI_HII_IIBT_END_BLOCK
);
761 ImagePackage
->ImageBlock
= AllocateZeroPool (NewBlockSize
+ sizeof (EFI_HII_IIBT_END_BLOCK
));
762 if (ImagePackage
->ImageBlock
== NULL
) {
763 FreePool (ImagePackage
);
764 EfiReleaseLock (&mHiiDatabaseLock
);
765 return EFI_OUT_OF_RESOURCES
;
767 ImageBlocks
= ImagePackage
->ImageBlock
;
770 // Insert this image package.
772 PackageListNode
->ImagePkg
= ImagePackage
;
773 PackageListNode
->PackageListHdr
.PackageLength
+= ImagePackage
->ImagePkgHdr
.Header
.Length
;
777 // Append the new block here
779 if (Image
->Flags
== EFI_IMAGE_TRANSPARENT
) {
780 ImageBlocks
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT_TRANS
;
782 ImageBlocks
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT
;
784 WriteUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) ImageBlocks
)->Bitmap
.Width
, Image
->Width
);
785 WriteUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) ImageBlocks
)->Bitmap
.Height
, Image
->Height
);
786 CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) ImageBlocks
)->Bitmap
.Bitmap
, Image
->Bitmap
, (UINT32
) Image
->Width
* Image
->Height
);
789 // Append the block end
791 ImageBlocks
= (EFI_HII_IMAGE_BLOCK
*) ((UINT8
*) ImageBlocks
+ NewBlockSize
);
792 ImageBlocks
->BlockType
= EFI_HII_IIBT_END
;
795 // Check whether need to get the contents of HiiDataBase.
796 // Only after ReadyToBoot to do the export.
798 if (gExportAfterReadyToBoot
) {
799 HiiGetDatabaseInfo(&Private
->HiiDatabase
);
802 EfiReleaseLock (&mHiiDatabaseLock
);
809 This function retrieves the image specified by ImageId which is associated with
810 the specified PackageList and copies it into the buffer specified by Image.
812 @param Database A pointer to the database list header.
813 @param PackageList Handle of the package list where this image will
815 @param ImageId The image's id,, which is unique within
817 @param Image Points to the image.
818 @param BitmapOnly TRUE to only return the bitmap type image.
819 FALSE to locate image decoder instance to decode image.
821 @retval EFI_SUCCESS The new image was returned successfully.
822 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
823 database. The specified PackageList is not in the database.
824 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
826 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
827 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
832 IN LIST_ENTRY
*Database
,
833 IN EFI_HII_HANDLE PackageList
,
834 IN EFI_IMAGE_ID ImageId
,
835 OUT EFI_IMAGE_INPUT
*Image
,
836 IN BOOLEAN BitmapOnly
840 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
841 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
842 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
843 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit
;
850 EFI_HII_IMAGE_DECODER_PROTOCOL
*Decoder
;
851 EFI_IMAGE_OUTPUT
*ImageOut
;
853 if (Image
== NULL
|| ImageId
== 0) {
854 return EFI_INVALID_PARAMETER
;
857 PackageListNode
= LocatePackageList (Database
, PackageList
);
858 if (PackageListNode
== NULL
) {
859 return EFI_NOT_FOUND
;
861 ImagePackage
= PackageListNode
->ImagePkg
;
862 if (ImagePackage
== NULL
) {
863 return EFI_NOT_FOUND
;
867 // Find the image block specified by ImageId
869 CurrentImageBlock
= GetImageIdOrAddress (ImagePackage
->ImageBlock
, &ImageId
);
870 if (CurrentImageBlock
== NULL
) {
871 return EFI_NOT_FOUND
;
875 switch (CurrentImageBlock
->BlockType
) {
876 case EFI_HII_IIBT_IMAGE_JPEG
:
877 case EFI_HII_IIBT_IMAGE_PNG
:
879 return EFI_UNSUPPORTED
;
883 Decoder
= LocateHiiImageDecoder (CurrentImageBlock
->BlockType
);
884 if (Decoder
== NULL
) {
885 return EFI_UNSUPPORTED
;
888 // Use the common block code since the definition of two structures is the same.
890 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
));
891 ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Data
) ==
892 sizeof (((EFI_HII_IIBT_PNG_BLOCK
*) CurrentImageBlock
)->Data
));
893 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Size
) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Size
));
894 ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Size
) ==
895 sizeof (((EFI_HII_IIBT_PNG_BLOCK
*) CurrentImageBlock
)->Size
));
896 Status
= Decoder
->DecodeImage (
898 ((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Data
,
899 ((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Size
,
905 // Spec requires to use the first capable image decoder instance.
906 // The first image decoder instance may fail to decode the image.
908 if (!EFI_ERROR (Status
)) {
909 Image
->Bitmap
= ImageOut
->Image
.Bitmap
;
910 Image
->Height
= ImageOut
->Height
;
911 Image
->Width
= ImageOut
->Width
;
916 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
917 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
918 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
919 Image
->Flags
= EFI_IMAGE_TRANSPARENT
;
923 case EFI_HII_IIBT_IMAGE_1BIT
:
924 case EFI_HII_IIBT_IMAGE_4BIT
:
925 case EFI_HII_IIBT_IMAGE_8BIT
:
927 // Use the common block code since the definition of these structures is the same.
929 CopyMem (&Iibt1bit
, CurrentImageBlock
, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
));
930 ImageLength
= (UINTN
) Iibt1bit
.Bitmap
.Width
* Iibt1bit
.Bitmap
.Height
;
931 if (ImageLength
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
932 return EFI_OUT_OF_RESOURCES
;
934 ImageLength
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
935 Image
->Bitmap
= AllocateZeroPool (ImageLength
);
936 if (Image
->Bitmap
== NULL
) {
937 return EFI_OUT_OF_RESOURCES
;
940 Image
->Width
= Iibt1bit
.Bitmap
.Width
;
941 Image
->Height
= Iibt1bit
.Bitmap
.Height
;
943 PaletteInfo
= ImagePackage
->PaletteBlock
+ sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER
);
944 for (PaletteIndex
= 1; PaletteIndex
< Iibt1bit
.PaletteIndex
; PaletteIndex
++) {
945 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
946 PaletteInfo
+= PaletteSize
+ sizeof (UINT16
);
948 ASSERT (PaletteIndex
== Iibt1bit
.PaletteIndex
);
951 // Output bitmap data
953 if (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_1BIT
||
954 CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_1BIT_TRANS
) {
957 ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Data
,
958 (EFI_HII_IMAGE_PALETTE_INFO
*) PaletteInfo
960 } else if (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_4BIT
||
961 CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_4BIT_TRANS
) {
964 ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Data
,
965 (EFI_HII_IMAGE_PALETTE_INFO
*) PaletteInfo
970 ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Data
,
971 (EFI_HII_IMAGE_PALETTE_INFO
*) PaletteInfo
977 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
978 Image
->Flags
= EFI_IMAGE_TRANSPARENT
;
982 case EFI_HII_IIBT_IMAGE_24BIT
:
983 Width
= ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
);
984 Height
= ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
);
985 ImageLength
= (UINTN
)Width
* Height
;
986 if (ImageLength
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
987 return EFI_OUT_OF_RESOURCES
;
989 ImageLength
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
990 Image
->Bitmap
= AllocateZeroPool (ImageLength
);
991 if (Image
->Bitmap
== NULL
) {
992 return EFI_OUT_OF_RESOURCES
;
995 Image
->Width
= Width
;
996 Image
->Height
= Height
;
999 // Output the bitmap data directly.
1003 ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Bitmap
1008 return EFI_NOT_FOUND
;
1013 This function retrieves the image specified by ImageId which is associated with
1014 the specified PackageList and copies it into the buffer specified by Image.
1016 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1017 @param PackageList Handle of the package list where this image will
1019 @param ImageId The image's id,, which is unique within
1021 @param Image Points to the image.
1023 @retval EFI_SUCCESS The new image was returned successfully.
1024 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1025 database. The specified PackageList is not in the database.
1026 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
1028 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
1029 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
1036 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1037 IN EFI_HII_HANDLE PackageList
,
1038 IN EFI_IMAGE_ID ImageId
,
1039 OUT EFI_IMAGE_INPUT
*Image
1042 HII_DATABASE_PRIVATE_DATA
*Private
;
1043 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1044 return IGetImage (&Private
->DatabaseList
, PackageList
, ImageId
, Image
, TRUE
);
1049 This function updates the image specified by ImageId in the specified PackageListHandle to
1050 the image specified by Image.
1052 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1053 @param PackageList The package list containing the images.
1054 @param ImageId The image's id,, which is unique within
1056 @param Image Points to the image.
1058 @retval EFI_SUCCESS The new image was updated successfully.
1059 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1060 database. The specified PackageList is not in the database.
1061 @retval EFI_INVALID_PARAMETER The Image was NULL.
1067 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1068 IN EFI_HII_HANDLE PackageList
,
1069 IN EFI_IMAGE_ID ImageId
,
1070 IN CONST EFI_IMAGE_INPUT
*Image
1073 HII_DATABASE_PRIVATE_DATA
*Private
;
1074 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1075 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
1076 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
1077 EFI_HII_IMAGE_BLOCK
*ImageBlocks
;
1078 EFI_HII_IMAGE_BLOCK
*NewImageBlock
;
1079 UINT32 NewBlockSize
;
1080 UINT32 OldBlockSize
;
1084 if (This
== NULL
|| Image
== NULL
|| ImageId
== 0 || Image
->Bitmap
== NULL
) {
1085 return EFI_INVALID_PARAMETER
;
1088 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1089 PackageListNode
= LocatePackageList (&Private
->DatabaseList
, PackageList
);
1090 if (PackageListNode
== NULL
) {
1091 return EFI_NOT_FOUND
;
1093 ImagePackage
= PackageListNode
->ImagePkg
;
1094 if (ImagePackage
== NULL
) {
1095 return EFI_NOT_FOUND
;
1099 // Find the image block specified by ImageId
1101 CurrentImageBlock
= GetImageIdOrAddress (ImagePackage
->ImageBlock
, &ImageId
);
1102 if (CurrentImageBlock
== NULL
) {
1103 return EFI_NOT_FOUND
;
1106 EfiAcquireLock (&mHiiDatabaseLock
);
1109 // Get the size of original image block. Use some common block code here
1110 // since the definition of some structures is the same.
1112 switch (CurrentImageBlock
->BlockType
) {
1113 case EFI_HII_IIBT_IMAGE_JPEG
:
1114 OldBlockSize
= OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*) &((EFI_HII_IIBT_JPEG_BLOCK
*) CurrentImageBlock
)->Size
);
1116 case EFI_HII_IIBT_IMAGE_PNG
:
1117 OldBlockSize
= OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*) &((EFI_HII_IIBT_PNG_BLOCK
*) CurrentImageBlock
)->Size
);
1119 case EFI_HII_IIBT_IMAGE_1BIT
:
1120 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
1121 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
) - sizeof (UINT8
) +
1123 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
1124 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
1127 case EFI_HII_IIBT_IMAGE_4BIT
:
1128 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
1129 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK
) - sizeof (UINT8
) +
1131 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
1132 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
1135 case EFI_HII_IIBT_IMAGE_8BIT
:
1136 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
1137 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK
) - sizeof (UINT8
) +
1139 (UINT32
) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
1140 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
1143 case EFI_HII_IIBT_IMAGE_24BIT
:
1144 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
1145 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
) +
1147 (UINT32
) ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Width
),
1148 ReadUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) CurrentImageBlock
)->Bitmap
.Height
)
1152 EfiReleaseLock (&mHiiDatabaseLock
);
1153 return EFI_NOT_FOUND
;
1157 // Create the new image block according to input image.
1161 // Make sure the final package length doesn't overflow.
1162 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
1163 // 24Bit BMP occpuies 3 bytes per pixel.
1165 NewBlockSize
= (UINT32
)Image
->Width
* Image
->Height
;
1166 if (NewBlockSize
> (MAX_UINT32
- (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
))) / 3) {
1167 EfiReleaseLock (&mHiiDatabaseLock
);
1168 return EFI_OUT_OF_RESOURCES
;
1170 NewBlockSize
= NewBlockSize
* 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
));
1171 if ((NewBlockSize
> OldBlockSize
) &&
1172 (NewBlockSize
- OldBlockSize
> MAX_UINT24
- ImagePackage
->ImagePkgHdr
.Header
.Length
)
1174 EfiReleaseLock (&mHiiDatabaseLock
);
1175 return EFI_OUT_OF_RESOURCES
;
1179 // Adjust the image package to remove the original block firstly then add the new block.
1181 ImageBlocks
= AllocateZeroPool (ImagePackage
->ImageBlockSize
+ NewBlockSize
- OldBlockSize
);
1182 if (ImageBlocks
== NULL
) {
1183 EfiReleaseLock (&mHiiDatabaseLock
);
1184 return EFI_OUT_OF_RESOURCES
;
1187 Part1Size
= (UINT32
) ((UINTN
) CurrentImageBlock
- (UINTN
) ImagePackage
->ImageBlock
);
1188 Part2Size
= ImagePackage
->ImageBlockSize
- Part1Size
- OldBlockSize
;
1189 CopyMem (ImageBlocks
, ImagePackage
->ImageBlock
, Part1Size
);
1192 // Set the new image block
1194 NewImageBlock
= (EFI_HII_IMAGE_BLOCK
*) ((UINT8
*) ImageBlocks
+ Part1Size
);
1195 if ((Image
->Flags
& EFI_IMAGE_TRANSPARENT
) == EFI_IMAGE_TRANSPARENT
) {
1196 NewImageBlock
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT_TRANS
;
1198 NewImageBlock
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT
;
1200 WriteUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) NewImageBlock
)->Bitmap
.Width
, Image
->Width
);
1201 WriteUnaligned16 ((VOID
*) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) NewImageBlock
)->Bitmap
.Height
, Image
->Height
);
1202 CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*) NewImageBlock
)->Bitmap
.Bitmap
,
1203 Image
->Bitmap
, (UINT32
) Image
->Width
* Image
->Height
);
1205 CopyMem ((UINT8
*) NewImageBlock
+ NewBlockSize
, (UINT8
*) CurrentImageBlock
+ OldBlockSize
, Part2Size
);
1207 FreePool (ImagePackage
->ImageBlock
);
1208 ImagePackage
->ImageBlock
= ImageBlocks
;
1209 ImagePackage
->ImageBlockSize
+= NewBlockSize
- OldBlockSize
;
1210 ImagePackage
->ImagePkgHdr
.Header
.Length
+= NewBlockSize
- OldBlockSize
;
1211 PackageListNode
->PackageListHdr
.PackageLength
+= NewBlockSize
- OldBlockSize
;
1214 // Check whether need to get the contents of HiiDataBase.
1215 // Only after ReadyToBoot to do the export.
1217 if (gExportAfterReadyToBoot
) {
1218 HiiGetDatabaseInfo(&Private
->HiiDatabase
);
1221 EfiReleaseLock (&mHiiDatabaseLock
);
1228 This function renders an image to a bitmap or the screen using the specified
1229 color and options. It draws the image on an existing bitmap, allocates a new
1230 bitmap or uses the screen. The images can be clipped.
1232 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1233 @param Flags Describes how the image is to be drawn.
1234 @param Image Points to the image to be displayed.
1235 @param Blt If this points to a non-NULL on entry, this points
1236 to the image, which is Width pixels wide and
1237 Height pixels high. The image will be drawn onto
1238 this image and EFI_HII_DRAW_FLAG_CLIP is implied.
1239 If this points to a NULL on entry, then a buffer
1240 will be allocated to hold the generated image and
1241 the pointer updated on exit. It is the caller's
1242 responsibility to free this buffer.
1243 @param BltX Specifies the offset from the left and top edge of
1244 the output image of the first pixel in the image.
1245 @param BltY Specifies the offset from the left and top edge of
1246 the output image of the first pixel in the image.
1248 @retval EFI_SUCCESS The image was successfully drawn.
1249 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1250 @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
1251 @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
1257 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1258 IN EFI_HII_DRAW_FLAGS Flags
,
1259 IN CONST EFI_IMAGE_INPUT
*Image
,
1260 IN OUT EFI_IMAGE_OUTPUT
**Blt
,
1266 HII_DATABASE_PRIVATE_DATA
*Private
;
1267 BOOLEAN Transparent
;
1268 EFI_IMAGE_OUTPUT
*ImageOut
;
1269 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
1277 EFI_FONT_DISPLAY_INFO
*FontInfo
;
1280 if (This
== NULL
|| Image
== NULL
|| Blt
== NULL
) {
1281 return EFI_INVALID_PARAMETER
;
1284 if ((Flags
& EFI_HII_DRAW_FLAG_CLIP
) == EFI_HII_DRAW_FLAG_CLIP
&& *Blt
== NULL
) {
1285 return EFI_INVALID_PARAMETER
;
1288 if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_TRANSPARENT
) {
1289 return EFI_INVALID_PARAMETER
;
1295 // Check whether the image will be drawn transparently or opaquely.
1297 Transparent
= FALSE
;
1298 if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_FORCE_TRANS
) {
1300 } else if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE
){
1301 Transparent
= FALSE
;
1304 // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
1305 // on the image's transparency setting.
1307 if ((Image
->Flags
& EFI_IMAGE_TRANSPARENT
) == EFI_IMAGE_TRANSPARENT
) {
1313 // Image cannot be drawn transparently if Blt points to NULL on entry.
1314 // Currently output to Screen transparently is not supported, either.
1318 return EFI_INVALID_PARAMETER
;
1319 } else if ((Flags
& EFI_HII_DIRECT_TO_SCREEN
) == EFI_HII_DIRECT_TO_SCREEN
) {
1320 return EFI_INVALID_PARAMETER
;
1324 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1327 // When Blt points to a non-NULL on entry, this image will be drawn onto
1328 // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
1329 // Otherwise a new bitmap will be allocated to hold this image.
1333 // Make sure the BltX and BltY is inside the Blt area.
1335 if ((BltX
>= (*Blt
)->Width
) || (BltY
>= (*Blt
)->Height
)) {
1336 return EFI_INVALID_PARAMETER
;
1340 // Clip the image by (Width, Height)
1343 Width
= Image
->Width
;
1344 Height
= Image
->Height
;
1346 if (Width
> (*Blt
)->Width
- (UINT16
)BltX
) {
1347 Width
= (*Blt
)->Width
- (UINT16
)BltX
;
1349 if (Height
> (*Blt
)->Height
- (UINT16
)BltY
) {
1350 Height
= (*Blt
)->Height
- (UINT16
)BltY
;
1354 // Prepare the buffer for the temporary image.
1355 // Make sure the buffer size doesn't overflow UINTN.
1357 BufferLen
= Width
* Height
;
1358 if (BufferLen
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
1359 return EFI_OUT_OF_RESOURCES
;
1361 BufferLen
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1362 BltBuffer
= AllocateZeroPool (BufferLen
);
1363 if (BltBuffer
== NULL
) {
1364 return EFI_OUT_OF_RESOURCES
;
1367 if (Width
== Image
->Width
&& Height
== Image
->Height
) {
1368 CopyMem (BltBuffer
, Image
->Bitmap
, BufferLen
);
1370 for (Ypos
= 0; Ypos
< Height
; Ypos
++) {
1371 OffsetY1
= Image
->Width
* Ypos
;
1372 OffsetY2
= Width
* Ypos
;
1373 for (Xpos
= 0; Xpos
< Width
; Xpos
++) {
1374 BltBuffer
[OffsetY2
+ Xpos
] = Image
->Bitmap
[OffsetY1
+ Xpos
];
1380 // Draw the image to existing bitmap or screen depending on flag.
1382 if ((Flags
& EFI_HII_DIRECT_TO_SCREEN
) == EFI_HII_DIRECT_TO_SCREEN
) {
1384 // Caller should make sure the current UGA console is grarphic mode.
1388 // Write the image directly to the output device specified by Screen.
1390 Status
= (*Blt
)->Image
.Screen
->Blt (
1391 (*Blt
)->Image
.Screen
,
1393 EfiBltBufferToVideo
,
1404 // Draw the image onto the existing bitmap specified by Bitmap.
1406 Status
= ImageToBlt (
1418 FreePool (BltBuffer
);
1423 // Allocate a new bitmap to hold the incoming image.
1427 // Make sure the final width and height doesn't overflow UINT16.
1429 if ((BltX
> (UINTN
)MAX_UINT16
- Image
->Width
) || (BltY
> (UINTN
)MAX_UINT16
- Image
->Height
)) {
1430 return EFI_INVALID_PARAMETER
;
1433 Width
= Image
->Width
+ (UINT16
)BltX
;
1434 Height
= Image
->Height
+ (UINT16
)BltY
;
1437 // Make sure the output image size doesn't overflow UINTN.
1439 BufferLen
= Width
* Height
;
1440 if (BufferLen
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
1441 return EFI_OUT_OF_RESOURCES
;
1443 BufferLen
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1444 BltBuffer
= AllocateZeroPool (BufferLen
);
1445 if (BltBuffer
== NULL
) {
1446 return EFI_OUT_OF_RESOURCES
;
1449 ImageOut
= (EFI_IMAGE_OUTPUT
*) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT
));
1450 if (ImageOut
== NULL
) {
1451 FreePool (BltBuffer
);
1452 return EFI_OUT_OF_RESOURCES
;
1454 ImageOut
->Width
= Width
;
1455 ImageOut
->Height
= Height
;
1456 ImageOut
->Image
.Bitmap
= BltBuffer
;
1459 // BUGBUG: Now all the "blank" pixels are filled with system default background
1460 // color. Not sure if it need to be updated or not.
1462 Status
= GetSystemFont (Private
, &FontInfo
, NULL
);
1463 if (EFI_ERROR (Status
)) {
1464 FreePool (BltBuffer
);
1465 FreePool (ImageOut
);
1468 ASSERT (FontInfo
!= NULL
);
1469 for (Index
= 0; Index
< (UINTN
)Width
* Height
; Index
++) {
1470 BltBuffer
[Index
] = FontInfo
->BackgroundColor
;
1472 FreePool (FontInfo
);
1475 // Draw the incoming image to the new created image.
1493 This function renders an image to a bitmap or the screen using the specified
1494 color and options. It draws the image on an existing bitmap, allocates a new
1495 bitmap or uses the screen. The images can be clipped.
1497 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1498 @param Flags Describes how the image is to be drawn.
1499 @param PackageList The package list in the HII database to search for
1500 the specified image.
1501 @param ImageId The image's id, which is unique within
1503 @param Blt If this points to a non-NULL on entry, this points
1504 to the image, which is Width pixels wide and
1505 Height pixels high. The image will be drawn onto
1507 EFI_HII_DRAW_FLAG_CLIP is implied. If this points
1508 to a NULL on entry, then a buffer will be
1509 allocated to hold the generated image and the
1510 pointer updated on exit. It is the caller's
1511 responsibility to free this buffer.
1512 @param BltX Specifies the offset from the left and top edge of
1513 the output image of the first pixel in the image.
1514 @param BltY Specifies the offset from the left and top edge of
1515 the output image of the first pixel in the image.
1517 @retval EFI_SUCCESS The image was successfully drawn.
1518 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1519 @retval EFI_INVALID_PARAMETER The Blt was NULL.
1520 @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
1521 The specified PackageList is not in the database.
1527 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1528 IN EFI_HII_DRAW_FLAGS Flags
,
1529 IN EFI_HII_HANDLE PackageList
,
1530 IN EFI_IMAGE_ID ImageId
,
1531 IN OUT EFI_IMAGE_OUTPUT
**Blt
,
1537 EFI_IMAGE_INPUT Image
;
1540 // Check input parameter.
1542 if (This
== NULL
|| Blt
== NULL
) {
1543 return EFI_INVALID_PARAMETER
;
1547 // Get the specified Image.
1549 Status
= HiiGetImage (This
, PackageList
, ImageId
, &Image
);
1550 if (EFI_ERROR (Status
)) {
1557 Status
= HiiDrawImage (This
, Flags
, &Image
, Blt
, BltX
, BltY
);
1558 if (Image
.Bitmap
!= NULL
) {
1559 FreePool (Image
.Bitmap
);