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
10 #include "HiiDatabase.h"
12 #define MAX_UINT24 0xFFFFFF
15 Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
16 ImageId is zero, otherwise return the address of the
17 corresponding image block with identifier specified by ImageId.
19 This is a internal function.
21 @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
22 @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
23 else use this id to find its corresponding image block address.
25 @return The image block address when input ImageId is not zero; otherwise return NULL.
30 IN EFI_HII_IMAGE_BLOCK
*ImageBlocks
,
31 IN OUT EFI_IMAGE_ID
*ImageId
34 EFI_IMAGE_ID ImageIdCurrent
;
35 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
38 ASSERT (ImageBlocks
!= NULL
&& ImageId
!= NULL
);
39 CurrentImageBlock
= ImageBlocks
;
42 while (CurrentImageBlock
->BlockType
!= EFI_HII_IIBT_END
) {
44 if (*ImageId
== ImageIdCurrent
) {
46 // If the found image block is a duplicate block, update the ImageId to
47 // find the previous defined image block.
49 if (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_DUPLICATE
) {
50 *ImageId
= ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_DUPLICATE_BLOCK
*)CurrentImageBlock
)->ImageId
);
51 ASSERT (*ImageId
!= ImageIdCurrent
);
52 ASSERT (*ImageId
!= 0);
53 CurrentImageBlock
= ImageBlocks
;
58 return CurrentImageBlock
;
61 if (*ImageId
< ImageIdCurrent
) {
63 // Can not find the specified image block in this image.
69 switch (CurrentImageBlock
->BlockType
) {
70 case EFI_HII_IIBT_EXT1
:
71 Length
= ((EFI_HII_IIBT_EXT1_BLOCK
*)CurrentImageBlock
)->Length
;
73 case EFI_HII_IIBT_EXT2
:
74 Length
= ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK
*)CurrentImageBlock
)->Length
);
76 case EFI_HII_IIBT_EXT4
:
77 Length
= ReadUnaligned32 ((VOID
*)&((EFI_HII_IIBT_EXT4_BLOCK
*)CurrentImageBlock
)->Length
);
80 case EFI_HII_IIBT_IMAGE_1BIT
:
81 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
82 Length
= sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
) - sizeof (UINT8
) +
84 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
85 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
90 case EFI_HII_IIBT_IMAGE_4BIT
:
91 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
92 Length
= sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK
) - sizeof (UINT8
) +
94 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
95 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
100 case EFI_HII_IIBT_IMAGE_8BIT
:
101 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
102 Length
= sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK
) - sizeof (UINT8
) +
104 (UINT32
)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
105 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
110 case EFI_HII_IIBT_IMAGE_24BIT
:
111 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
112 Length
= sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
) +
114 (UINT32
)ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
115 ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
120 case EFI_HII_IIBT_DUPLICATE
:
121 Length
= sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK
);
125 case EFI_HII_IIBT_IMAGE_JPEG
:
126 Length
= OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*)&((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Size
);
130 case EFI_HII_IIBT_IMAGE_PNG
:
131 Length
= OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*)&((EFI_HII_IIBT_PNG_BLOCK
*)CurrentImageBlock
)->Size
);
135 case EFI_HII_IIBT_SKIP1
:
136 Length
= sizeof (EFI_HII_IIBT_SKIP1_BLOCK
);
137 ImageIdCurrent
+= ((EFI_HII_IIBT_SKIP1_BLOCK
*)CurrentImageBlock
)->SkipCount
;
140 case EFI_HII_IIBT_SKIP2
:
141 Length
= sizeof (EFI_HII_IIBT_SKIP2_BLOCK
);
142 ImageIdCurrent
+= ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_SKIP2_BLOCK
*)CurrentImageBlock
)->SkipCount
);
147 // Unknown image blocks can not be skipped, processing halts.
154 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
;
169 Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
171 This is a internal function.
174 @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
175 @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
176 @param PixelNum The number of pixels to be converted.
182 OUT EFI_HII_RGB_PIXEL
*BitMapOut
,
183 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapIn
,
189 ASSERT (BitMapOut
!= NULL
&& BitMapIn
!= NULL
);
191 for (Index
= 0; Index
< PixelNum
; Index
++) {
192 CopyMem (BitMapOut
+ Index
, BitMapIn
+ Index
, sizeof (EFI_HII_RGB_PIXEL
));
197 Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
199 This is a internal function.
202 @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
203 @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
204 @param PixelNum The number of pixels to be converted.
210 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapOut
,
211 IN EFI_HII_RGB_PIXEL
*BitMapIn
,
217 ASSERT (BitMapOut
!= NULL
&& BitMapIn
!= NULL
);
219 for (Index
= 0; Index
< PixelNum
; Index
++) {
220 CopyMem (BitMapOut
+ Index
, BitMapIn
+ Index
, sizeof (EFI_HII_RGB_PIXEL
));
225 Output pixels in "1 bit per pixel" format to an image.
227 This is a internal function.
230 @param Image Points to the image which will store the pixels.
231 @param Data Stores the value of output pixels, 0 or 1.
232 @param PaletteInfo PaletteInfo which stores the color of the output
233 pixels. First entry corresponds to color 0 and
234 second one to color 1.
240 IN OUT EFI_IMAGE_INPUT
*Image
,
242 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
249 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
250 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[2];
251 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
255 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
257 BitMapPtr
= Image
->Bitmap
;
260 // First entry corresponds to color 0 and second entry corresponds to color 1.
263 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
264 PaletteSize
+= sizeof (UINT16
);
265 Palette
= AllocateZeroPool (PaletteSize
);
266 ASSERT (Palette
!= NULL
);
267 if (Palette
== NULL
) {
271 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
273 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
274 CopyRgbToGopPixel (&PaletteValue
[0], &Palette
->PaletteValue
[0], 1);
275 CopyRgbToGopPixel (&PaletteValue
[1], &Palette
->PaletteValue
[1], 1);
279 // Convert the pixel from one bit to corresponding color.
281 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
282 OffsetY
= BITMAP_LEN_1_BIT (Image
->Width
, Ypos
);
284 // All bits in these bytes are meaningful
286 for (Xpos
= 0; Xpos
< Image
->Width
/ 8; Xpos
++) {
287 Byte
= *(Data
+ OffsetY
+ Xpos
);
288 for (Index
= 0; Index
< 8; Index
++) {
289 if ((Byte
& (1 << Index
)) != 0) {
290 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + (8 - Index
- 1)] = PaletteValue
[1];
292 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + (8 - Index
- 1)] = PaletteValue
[0];
297 if (Image
->Width
% 8 != 0) {
299 // Padding bits in this byte should be ignored.
301 Byte
= *(Data
+ OffsetY
+ Xpos
);
302 for (Index
= 0; Index
< Image
->Width
% 8; Index
++) {
303 if ((Byte
& (1 << (8 - Index
- 1))) != 0) {
304 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + Index
] = PaletteValue
[1];
306 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 8 + Index
] = PaletteValue
[0];
314 Output pixels in "4 bit per pixel" format to an image.
316 This is a internal function.
319 @param Image Points to the image which will store the pixels.
320 @param Data Stores the value of output pixels, 0 ~ 15.
321 @param[in] PaletteInfo PaletteInfo which stores the color of the output
322 pixels. Each entry corresponds to a color within
329 IN OUT EFI_IMAGE_INPUT
*Image
,
331 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
337 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
338 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[16];
339 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
344 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
346 BitMapPtr
= Image
->Bitmap
;
349 // The bitmap should allocate each color index starting from 0.
352 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
353 PaletteSize
+= sizeof (UINT16
);
354 Palette
= AllocateZeroPool (PaletteSize
);
355 ASSERT (Palette
!= NULL
);
356 if (Palette
== NULL
) {
360 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
361 PaletteNum
= (UINT16
)(Palette
->PaletteSize
/ sizeof (EFI_HII_RGB_PIXEL
));
363 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
364 CopyRgbToGopPixel (PaletteValue
, Palette
->PaletteValue
, MIN (PaletteNum
, ARRAY_SIZE (PaletteValue
)));
368 // Convert the pixel from 4 bit to corresponding color.
370 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
371 OffsetY
= BITMAP_LEN_4_BIT (Image
->Width
, Ypos
);
373 // All bits in these bytes are meaningful
375 for (Xpos
= 0; Xpos
< Image
->Width
/ 2; Xpos
++) {
376 Byte
= *(Data
+ OffsetY
+ Xpos
);
377 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2] = PaletteValue
[Byte
>> 4];
378 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2 + 1] = PaletteValue
[Byte
& 0x0F];
381 if (Image
->Width
% 2 != 0) {
383 // Padding bits in this byte should be ignored.
385 Byte
= *(Data
+ OffsetY
+ Xpos
);
386 BitMapPtr
[Ypos
* Image
->Width
+ Xpos
* 2] = PaletteValue
[Byte
>> 4];
392 Output pixels in "8 bit per pixel" format to an image.
394 This is a internal function.
397 @param Image Points to the image which will store the pixels.
398 @param Data Stores the value of output pixels, 0 ~ 255.
399 @param[in] PaletteInfo PaletteInfo which stores the color of the output
400 pixels. Each entry corresponds to a color within
407 IN OUT EFI_IMAGE_INPUT
*Image
,
409 IN EFI_HII_IMAGE_PALETTE_INFO
*PaletteInfo
415 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
416 EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue
[256];
417 EFI_HII_IMAGE_PALETTE_INFO
*Palette
;
422 ASSERT (Image
!= NULL
&& Data
!= NULL
&& PaletteInfo
!= NULL
);
424 BitMapPtr
= Image
->Bitmap
;
427 // The bitmap should allocate each color index starting from 0.
430 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
431 PaletteSize
+= sizeof (UINT16
);
432 Palette
= AllocateZeroPool (PaletteSize
);
433 ASSERT (Palette
!= NULL
);
434 if (Palette
== NULL
) {
438 CopyMem (Palette
, PaletteInfo
, PaletteSize
);
439 PaletteNum
= (UINT16
)(Palette
->PaletteSize
/ sizeof (EFI_HII_RGB_PIXEL
));
440 ZeroMem (PaletteValue
, sizeof (PaletteValue
));
441 CopyRgbToGopPixel (PaletteValue
, Palette
->PaletteValue
, MIN (PaletteNum
, ARRAY_SIZE (PaletteValue
)));
445 // Convert the pixel from 8 bits to corresponding color.
447 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
448 OffsetY
= BITMAP_LEN_8_BIT ((UINT32
)Image
->Width
, Ypos
);
450 // All bits are meaningful since the bitmap is 8 bits per pixel.
452 for (Xpos
= 0; Xpos
< Image
->Width
; Xpos
++) {
453 Byte
= *(Data
+ OffsetY
+ Xpos
);
454 BitMapPtr
[OffsetY
+ Xpos
] = PaletteValue
[Byte
];
460 Output pixels in "24 bit per pixel" format to an image.
462 This is a internal function.
465 @param Image Points to the image which will store the pixels.
466 @param Data Stores the color of output pixels, allowing 16.8
473 IN OUT EFI_IMAGE_INPUT
*Image
,
474 IN EFI_HII_RGB_PIXEL
*Data
479 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BitMapPtr
;
481 ASSERT (Image
!= NULL
&& Data
!= NULL
);
483 BitMapPtr
= Image
->Bitmap
;
485 for (Ypos
= 0; Ypos
< Image
->Height
; Ypos
++) {
486 OffsetY
= BITMAP_LEN_8_BIT ((UINT32
)Image
->Width
, Ypos
);
487 CopyRgbToGopPixel (&BitMapPtr
[OffsetY
], &Data
[OffsetY
], Image
->Width
);
492 Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
494 This is a internal function.
497 @param BltBuffer Buffer points to bitmap data of incoming image.
498 @param BltX Specifies the offset from the left and top edge of
499 the output image of the first pixel in the image.
500 @param BltY Specifies the offset from the left and top edge of
501 the output image of the first pixel in the image.
502 @param Width Width of the incoming image, in pixels.
503 @param Height Height of the incoming image, in pixels.
504 @param Transparent If TRUE, all "off" pixels in the image will be
505 drawn using the pixel value from blt and all other
506 pixels will be copied.
507 @param Blt Buffer points to bitmap data of output image.
509 @retval EFI_SUCCESS The image was successfully converted.
510 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
515 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
,
520 IN BOOLEAN Transparent
,
521 IN OUT EFI_IMAGE_OUTPUT
**Blt
524 EFI_IMAGE_OUTPUT
*ImageOut
;
527 UINTN OffsetY1
; // src buffer
528 UINTN OffsetY2
; // dest buffer
529 EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel
;
530 EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel
;
532 if ((BltBuffer
== NULL
) || (Blt
== NULL
) || (*Blt
== NULL
)) {
533 return EFI_INVALID_PARAMETER
;
538 if (Width
+ BltX
> ImageOut
->Width
) {
539 return EFI_INVALID_PARAMETER
;
542 if (Height
+ BltY
> ImageOut
->Height
) {
543 return EFI_INVALID_PARAMETER
;
546 ZeroMem (&ZeroPixel
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
548 for (Ypos
= 0; Ypos
< Height
; Ypos
++) {
549 OffsetY1
= Width
* Ypos
;
550 OffsetY2
= ImageOut
->Width
* (BltY
+ Ypos
);
551 for (Xpos
= 0; Xpos
< Width
; Xpos
++) {
552 SrcPixel
= BltBuffer
[OffsetY1
+ Xpos
];
554 if (CompareMem (&SrcPixel
, &ZeroPixel
, 3) != 0) {
555 ImageOut
->Image
.Bitmap
[OffsetY2
+ BltX
+ Xpos
] = SrcPixel
;
558 ImageOut
->Image
.Bitmap
[OffsetY2
+ BltX
+ Xpos
] = SrcPixel
;
567 Return the HII package list identified by PackageList HII handle.
569 @param Database Pointer to HII database list header.
570 @param PackageList HII handle of the package list to locate.
572 @retval The HII package list instance.
574 HII_DATABASE_PACKAGE_LIST_INSTANCE
*
576 IN LIST_ENTRY
*Database
,
577 IN EFI_HII_HANDLE PackageList
581 HII_DATABASE_RECORD
*Record
;
584 // Get the specified package list and image package.
586 for (Link
= GetFirstNode (Database
);
587 !IsNull (Database
, Link
);
588 Link
= GetNextNode (Database
, Link
)
591 Record
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
592 if (Record
->Handle
== PackageList
) {
593 return Record
->PackageList
;
601 This function adds the image Image to the group of images owned by PackageList, and returns
602 a new image identifier (ImageId).
604 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
605 @param PackageList Handle of the package list where this image will
607 @param ImageId On return, contains the new image id, which is
608 unique within PackageList.
609 @param Image Points to the image.
611 @retval EFI_SUCCESS The new image was added successfully.
612 @retval EFI_NOT_FOUND The specified PackageList could not be found in
614 @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
615 @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
621 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
622 IN EFI_HII_HANDLE PackageList
,
623 OUT EFI_IMAGE_ID
*ImageId
,
624 IN CONST EFI_IMAGE_INPUT
*Image
627 HII_DATABASE_PRIVATE_DATA
*Private
;
628 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
629 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
630 EFI_HII_IMAGE_BLOCK
*ImageBlocks
;
633 if ((This
== NULL
) || (ImageId
== NULL
) || (Image
== NULL
) || (Image
->Bitmap
== NULL
)) {
634 return EFI_INVALID_PARAMETER
;
637 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
638 PackageListNode
= LocatePackageList (&Private
->DatabaseList
, PackageList
);
639 if (PackageListNode
== NULL
) {
640 return EFI_NOT_FOUND
;
643 EfiAcquireLock (&mHiiDatabaseLock
);
646 // Calcuate the size of new image.
647 // Make sure the size doesn't overflow UINT32.
648 // Note: 24Bit BMP occpuies 3 bytes per pixel.
650 NewBlockSize
= (UINT32
)Image
->Width
* Image
->Height
;
651 if (NewBlockSize
> (MAX_UINT32
- (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
))) / 3) {
652 EfiReleaseLock (&mHiiDatabaseLock
);
653 return EFI_OUT_OF_RESOURCES
;
656 NewBlockSize
= NewBlockSize
* 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
));
659 // Get the image package in the package list,
660 // or create a new image package if image package does not exist.
662 if (PackageListNode
->ImagePkg
!= NULL
) {
663 ImagePackage
= PackageListNode
->ImagePkg
;
666 // Output the image id of the incoming image being inserted, which is the
667 // image id of the EFI_HII_IIBT_END block of old image package.
670 GetImageIdOrAddress (ImagePackage
->ImageBlock
, ImageId
);
673 // Update the package's image block by appending the new block to the end.
677 // Make sure the final package length doesn't overflow.
678 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
680 if (NewBlockSize
> MAX_UINT24
- ImagePackage
->ImagePkgHdr
.Header
.Length
) {
681 EfiReleaseLock (&mHiiDatabaseLock
);
682 return EFI_OUT_OF_RESOURCES
;
686 // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
687 // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
689 ImageBlocks
= AllocatePool (ImagePackage
->ImageBlockSize
+ NewBlockSize
);
690 if (ImageBlocks
== NULL
) {
691 EfiReleaseLock (&mHiiDatabaseLock
);
692 return EFI_OUT_OF_RESOURCES
;
696 // Copy the original content.
700 ImagePackage
->ImageBlock
,
701 ImagePackage
->ImageBlockSize
- sizeof (EFI_HII_IIBT_END_BLOCK
)
703 FreePool (ImagePackage
->ImageBlock
);
704 ImagePackage
->ImageBlock
= ImageBlocks
;
707 // Point to the very last block.
709 ImageBlocks
= (EFI_HII_IMAGE_BLOCK
*)(
710 (UINT8
*)ImageBlocks
+ ImagePackage
->ImageBlockSize
- sizeof (EFI_HII_IIBT_END_BLOCK
)
713 // Update the length record.
715 ImagePackage
->ImageBlockSize
+= NewBlockSize
;
716 ImagePackage
->ImagePkgHdr
.Header
.Length
+= NewBlockSize
;
717 PackageListNode
->PackageListHdr
.PackageLength
+= NewBlockSize
;
720 // Make sure the final package length doesn't overflow.
721 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
723 if (NewBlockSize
> MAX_UINT24
- (sizeof (EFI_HII_IMAGE_PACKAGE_HDR
) + sizeof (EFI_HII_IIBT_END_BLOCK
))) {
724 EfiReleaseLock (&mHiiDatabaseLock
);
725 return EFI_OUT_OF_RESOURCES
;
729 // The specified package list does not contain image package.
730 // Create one to add this image block.
732 ImagePackage
= (HII_IMAGE_PACKAGE_INSTANCE
*)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE
));
733 if (ImagePackage
== NULL
) {
734 EfiReleaseLock (&mHiiDatabaseLock
);
735 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
;
768 ImageBlocks
= ImagePackage
->ImageBlock
;
771 // Insert this image package.
773 PackageListNode
->ImagePkg
= ImagePackage
;
774 PackageListNode
->PackageListHdr
.PackageLength
+= ImagePackage
->ImagePkgHdr
.Header
.Length
;
778 // Append the new block here
780 if (Image
->Flags
== EFI_IMAGE_TRANSPARENT
) {
781 ImageBlocks
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT_TRANS
;
783 ImageBlocks
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT
;
786 WriteUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)ImageBlocks
)->Bitmap
.Width
, Image
->Width
);
787 WriteUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)ImageBlocks
)->Bitmap
.Height
, Image
->Height
);
788 CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)ImageBlocks
)->Bitmap
.Bitmap
, Image
->Bitmap
, (UINT32
)Image
->Width
* Image
->Height
);
791 // Append the block end
793 ImageBlocks
= (EFI_HII_IMAGE_BLOCK
*)((UINT8
*)ImageBlocks
+ NewBlockSize
);
794 ImageBlocks
->BlockType
= EFI_HII_IIBT_END
;
797 // Check whether need to get the contents of HiiDataBase.
798 // Only after ReadyToBoot to do the export.
800 if (gExportAfterReadyToBoot
) {
801 HiiGetDatabaseInfo (&Private
->HiiDatabase
);
804 EfiReleaseLock (&mHiiDatabaseLock
);
810 This function retrieves the image specified by ImageId which is associated with
811 the specified PackageList and copies it into the buffer specified by Image.
813 @param Database A pointer to the database list header.
814 @param PackageList Handle of the package list where this image will
816 @param ImageId The image's id,, which is unique within
818 @param Image Points to the image.
819 @param BitmapOnly TRUE to only return the bitmap type image.
820 FALSE to locate image decoder instance to decode image.
822 @retval EFI_SUCCESS The new image was returned successfully.
823 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
824 database. The specified PackageList is not in the database.
825 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
827 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
828 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
833 IN LIST_ENTRY
*Database
,
834 IN EFI_HII_HANDLE PackageList
,
835 IN EFI_IMAGE_ID ImageId
,
836 OUT EFI_IMAGE_INPUT
*Image
,
837 IN BOOLEAN BitmapOnly
841 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
842 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
843 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
844 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit
;
851 EFI_HII_IMAGE_DECODER_PROTOCOL
*Decoder
;
852 EFI_IMAGE_OUTPUT
*ImageOut
;
854 if ((Image
== NULL
) || (ImageId
== 0)) {
855 return EFI_INVALID_PARAMETER
;
858 PackageListNode
= LocatePackageList (Database
, PackageList
);
859 if (PackageListNode
== NULL
) {
860 return EFI_NOT_FOUND
;
863 ImagePackage
= PackageListNode
->ImagePkg
;
864 if (ImagePackage
== NULL
) {
865 return EFI_NOT_FOUND
;
869 // Find the image block specified by ImageId
871 CurrentImageBlock
= GetImageIdOrAddress (ImagePackage
->ImageBlock
, &ImageId
);
872 if (CurrentImageBlock
== NULL
) {
873 return EFI_NOT_FOUND
;
877 switch (CurrentImageBlock
->BlockType
) {
878 case EFI_HII_IIBT_IMAGE_JPEG
:
879 case EFI_HII_IIBT_IMAGE_PNG
:
881 return EFI_UNSUPPORTED
;
885 Decoder
= LocateHiiImageDecoder (CurrentImageBlock
->BlockType
);
886 if (Decoder
== NULL
) {
887 return EFI_UNSUPPORTED
;
891 // Use the common block code since the definition of two structures is the same.
893 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
));
895 sizeof (((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Data
) ==
896 sizeof (((EFI_HII_IIBT_PNG_BLOCK
*)CurrentImageBlock
)->Data
)
898 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Size
) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Size
));
900 sizeof (((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Size
) ==
901 sizeof (((EFI_HII_IIBT_PNG_BLOCK
*)CurrentImageBlock
)->Size
)
903 Status
= Decoder
->DecodeImage (
905 ((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Data
,
906 ((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Size
,
912 // Spec requires to use the first capable image decoder instance.
913 // The first image decoder instance may fail to decode the image.
915 if (!EFI_ERROR (Status
)) {
916 Image
->Bitmap
= ImageOut
->Image
.Bitmap
;
917 Image
->Height
= ImageOut
->Height
;
918 Image
->Width
= ImageOut
->Width
;
924 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
925 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
926 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
927 Image
->Flags
= EFI_IMAGE_TRANSPARENT
;
931 case EFI_HII_IIBT_IMAGE_1BIT
:
932 case EFI_HII_IIBT_IMAGE_4BIT
:
933 case EFI_HII_IIBT_IMAGE_8BIT
:
935 // Use the common block code since the definition of these structures is the same.
937 CopyMem (&Iibt1bit
, CurrentImageBlock
, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
));
938 ImageLength
= (UINTN
)Iibt1bit
.Bitmap
.Width
* Iibt1bit
.Bitmap
.Height
;
939 if (ImageLength
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
940 return EFI_OUT_OF_RESOURCES
;
943 ImageLength
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
944 Image
->Bitmap
= AllocateZeroPool (ImageLength
);
945 if (Image
->Bitmap
== NULL
) {
946 return EFI_OUT_OF_RESOURCES
;
949 Image
->Width
= Iibt1bit
.Bitmap
.Width
;
950 Image
->Height
= Iibt1bit
.Bitmap
.Height
;
952 PaletteInfo
= ImagePackage
->PaletteBlock
+ sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER
);
953 for (PaletteIndex
= 1; PaletteIndex
< Iibt1bit
.PaletteIndex
; PaletteIndex
++) {
954 CopyMem (&PaletteSize
, PaletteInfo
, sizeof (UINT16
));
955 PaletteInfo
+= PaletteSize
+ sizeof (UINT16
);
958 ASSERT (PaletteIndex
== Iibt1bit
.PaletteIndex
);
961 // Output bitmap data
963 if ((CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_1BIT
) ||
964 (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_1BIT_TRANS
))
968 ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Data
,
969 (EFI_HII_IMAGE_PALETTE_INFO
*)PaletteInfo
971 } else if ((CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_4BIT
) ||
972 (CurrentImageBlock
->BlockType
== EFI_HII_IIBT_IMAGE_4BIT_TRANS
))
976 ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Data
,
977 (EFI_HII_IMAGE_PALETTE_INFO
*)PaletteInfo
982 ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Data
,
983 (EFI_HII_IMAGE_PALETTE_INFO
*)PaletteInfo
989 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
990 Image
->Flags
= EFI_IMAGE_TRANSPARENT
;
994 case EFI_HII_IIBT_IMAGE_24BIT
:
995 Width
= ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
);
996 Height
= ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
);
997 ImageLength
= (UINTN
)Width
* Height
;
998 if (ImageLength
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
999 return EFI_OUT_OF_RESOURCES
;
1002 ImageLength
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1003 Image
->Bitmap
= AllocateZeroPool (ImageLength
);
1004 if (Image
->Bitmap
== NULL
) {
1005 return EFI_OUT_OF_RESOURCES
;
1008 Image
->Width
= Width
;
1009 Image
->Height
= Height
;
1012 // Output the bitmap data directly.
1016 ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Bitmap
1021 return EFI_NOT_FOUND
;
1026 This function retrieves the image specified by ImageId which is associated with
1027 the specified PackageList and copies it into the buffer specified by Image.
1029 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1030 @param PackageList Handle of the package list where this image will
1032 @param ImageId The image's id,, which is unique within
1034 @param Image Points to the image.
1036 @retval EFI_SUCCESS The new image was returned successfully.
1037 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1038 database. The specified PackageList is not in the database.
1039 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
1041 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
1042 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
1049 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1050 IN EFI_HII_HANDLE PackageList
,
1051 IN EFI_IMAGE_ID ImageId
,
1052 OUT EFI_IMAGE_INPUT
*Image
1055 HII_DATABASE_PRIVATE_DATA
*Private
;
1057 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1058 return IGetImage (&Private
->DatabaseList
, PackageList
, ImageId
, Image
, TRUE
);
1062 This function updates the image specified by ImageId in the specified PackageListHandle to
1063 the image specified by Image.
1065 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1066 @param PackageList The package list containing the images.
1067 @param ImageId The image's id,, which is unique within
1069 @param Image Points to the image.
1071 @retval EFI_SUCCESS The new image was updated successfully.
1072 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1073 database. The specified PackageList is not in the database.
1074 @retval EFI_INVALID_PARAMETER The Image was NULL.
1080 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1081 IN EFI_HII_HANDLE PackageList
,
1082 IN EFI_IMAGE_ID ImageId
,
1083 IN CONST EFI_IMAGE_INPUT
*Image
1086 HII_DATABASE_PRIVATE_DATA
*Private
;
1087 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1088 HII_IMAGE_PACKAGE_INSTANCE
*ImagePackage
;
1089 EFI_HII_IMAGE_BLOCK
*CurrentImageBlock
;
1090 EFI_HII_IMAGE_BLOCK
*ImageBlocks
;
1091 EFI_HII_IMAGE_BLOCK
*NewImageBlock
;
1092 UINT32 NewBlockSize
;
1093 UINT32 OldBlockSize
;
1097 if ((This
== NULL
) || (Image
== NULL
) || (ImageId
== 0) || (Image
->Bitmap
== NULL
)) {
1098 return EFI_INVALID_PARAMETER
;
1101 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1102 PackageListNode
= LocatePackageList (&Private
->DatabaseList
, PackageList
);
1103 if (PackageListNode
== NULL
) {
1104 return EFI_NOT_FOUND
;
1107 ImagePackage
= PackageListNode
->ImagePkg
;
1108 if (ImagePackage
== NULL
) {
1109 return EFI_NOT_FOUND
;
1113 // Find the image block specified by ImageId
1115 CurrentImageBlock
= GetImageIdOrAddress (ImagePackage
->ImageBlock
, &ImageId
);
1116 if (CurrentImageBlock
== NULL
) {
1117 return EFI_NOT_FOUND
;
1120 EfiAcquireLock (&mHiiDatabaseLock
);
1123 // Get the size of original image block. Use some common block code here
1124 // since the definition of some structures is the same.
1126 switch (CurrentImageBlock
->BlockType
) {
1127 case EFI_HII_IIBT_IMAGE_JPEG
:
1128 OldBlockSize
= OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*)&((EFI_HII_IIBT_JPEG_BLOCK
*)CurrentImageBlock
)->Size
);
1130 case EFI_HII_IIBT_IMAGE_PNG
:
1131 OldBlockSize
= OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK
, Data
) + ReadUnaligned32 ((VOID
*)&((EFI_HII_IIBT_PNG_BLOCK
*)CurrentImageBlock
)->Size
);
1133 case EFI_HII_IIBT_IMAGE_1BIT
:
1134 case EFI_HII_IIBT_IMAGE_1BIT_TRANS
:
1135 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK
) - sizeof (UINT8
) +
1137 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
1138 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
1141 case EFI_HII_IIBT_IMAGE_4BIT
:
1142 case EFI_HII_IIBT_IMAGE_4BIT_TRANS
:
1143 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK
) - sizeof (UINT8
) +
1145 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
1146 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
1149 case EFI_HII_IIBT_IMAGE_8BIT
:
1150 case EFI_HII_IIBT_IMAGE_8BIT_TRANS
:
1151 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK
) - sizeof (UINT8
) +
1153 (UINT32
)ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
1154 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
1157 case EFI_HII_IIBT_IMAGE_24BIT
:
1158 case EFI_HII_IIBT_IMAGE_24BIT_TRANS
:
1159 OldBlockSize
= sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
) +
1161 (UINT32
)ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Width
),
1162 ReadUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)CurrentImageBlock
)->Bitmap
.Height
)
1166 EfiReleaseLock (&mHiiDatabaseLock
);
1167 return EFI_NOT_FOUND
;
1171 // Create the new image block according to input image.
1175 // Make sure the final package length doesn't overflow.
1176 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
1177 // 24Bit BMP occpuies 3 bytes per pixel.
1179 NewBlockSize
= (UINT32
)Image
->Width
* Image
->Height
;
1180 if (NewBlockSize
> (MAX_UINT32
- (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
))) / 3) {
1181 EfiReleaseLock (&mHiiDatabaseLock
);
1182 return EFI_OUT_OF_RESOURCES
;
1185 NewBlockSize
= NewBlockSize
* 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK
) - sizeof (EFI_HII_RGB_PIXEL
));
1186 if ((NewBlockSize
> OldBlockSize
) &&
1187 (NewBlockSize
- OldBlockSize
> MAX_UINT24
- ImagePackage
->ImagePkgHdr
.Header
.Length
)
1190 EfiReleaseLock (&mHiiDatabaseLock
);
1191 return EFI_OUT_OF_RESOURCES
;
1195 // Adjust the image package to remove the original block firstly then add the new block.
1197 ImageBlocks
= AllocateZeroPool (ImagePackage
->ImageBlockSize
+ NewBlockSize
- OldBlockSize
);
1198 if (ImageBlocks
== NULL
) {
1199 EfiReleaseLock (&mHiiDatabaseLock
);
1200 return EFI_OUT_OF_RESOURCES
;
1203 Part1Size
= (UINT32
)((UINTN
)CurrentImageBlock
- (UINTN
)ImagePackage
->ImageBlock
);
1204 Part2Size
= ImagePackage
->ImageBlockSize
- Part1Size
- OldBlockSize
;
1205 CopyMem (ImageBlocks
, ImagePackage
->ImageBlock
, Part1Size
);
1208 // Set the new image block
1210 NewImageBlock
= (EFI_HII_IMAGE_BLOCK
*)((UINT8
*)ImageBlocks
+ Part1Size
);
1211 if ((Image
->Flags
& EFI_IMAGE_TRANSPARENT
) == EFI_IMAGE_TRANSPARENT
) {
1212 NewImageBlock
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT_TRANS
;
1214 NewImageBlock
->BlockType
= EFI_HII_IIBT_IMAGE_24BIT
;
1217 WriteUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)NewImageBlock
)->Bitmap
.Width
, Image
->Width
);
1218 WriteUnaligned16 ((VOID
*)&((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)NewImageBlock
)->Bitmap
.Height
, Image
->Height
);
1220 ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK
*)NewImageBlock
)->Bitmap
.Bitmap
,
1222 (UINT32
)Image
->Width
* Image
->Height
1225 CopyMem ((UINT8
*)NewImageBlock
+ NewBlockSize
, (UINT8
*)CurrentImageBlock
+ OldBlockSize
, Part2Size
);
1227 FreePool (ImagePackage
->ImageBlock
);
1228 ImagePackage
->ImageBlock
= ImageBlocks
;
1229 ImagePackage
->ImageBlockSize
+= NewBlockSize
- OldBlockSize
;
1230 ImagePackage
->ImagePkgHdr
.Header
.Length
+= NewBlockSize
- OldBlockSize
;
1231 PackageListNode
->PackageListHdr
.PackageLength
+= NewBlockSize
- OldBlockSize
;
1234 // Check whether need to get the contents of HiiDataBase.
1235 // Only after ReadyToBoot to do the export.
1237 if (gExportAfterReadyToBoot
) {
1238 HiiGetDatabaseInfo (&Private
->HiiDatabase
);
1241 EfiReleaseLock (&mHiiDatabaseLock
);
1246 This function renders an image to a bitmap or the screen using the specified
1247 color and options. It draws the image on an existing bitmap, allocates a new
1248 bitmap or uses the screen. The images can be clipped.
1250 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1251 @param Flags Describes how the image is to be drawn.
1252 @param Image Points to the image to be displayed.
1253 @param Blt If this points to a non-NULL on entry, this points
1254 to the image, which is Width pixels wide and
1255 Height pixels high. The image will be drawn onto
1256 this image and EFI_HII_DRAW_FLAG_CLIP is implied.
1257 If this points to a NULL on entry, then a buffer
1258 will be allocated to hold the generated image and
1259 the pointer updated on exit. It is the caller's
1260 responsibility to free this buffer.
1261 @param BltX Specifies the offset from the left and top edge of
1262 the output image of the first pixel in the image.
1263 @param BltY Specifies the offset from the left and top edge of
1264 the output image of the first pixel in the image.
1266 @retval EFI_SUCCESS The image was successfully drawn.
1267 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1268 @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
1269 @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
1275 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1276 IN EFI_HII_DRAW_FLAGS Flags
,
1277 IN CONST EFI_IMAGE_INPUT
*Image
,
1278 IN OUT EFI_IMAGE_OUTPUT
**Blt
,
1284 HII_DATABASE_PRIVATE_DATA
*Private
;
1285 BOOLEAN Transparent
;
1286 EFI_IMAGE_OUTPUT
*ImageOut
;
1287 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
1295 EFI_FONT_DISPLAY_INFO
*FontInfo
;
1298 if ((This
== NULL
) || (Image
== NULL
) || (Blt
== NULL
)) {
1299 return EFI_INVALID_PARAMETER
;
1302 if (((Flags
& EFI_HII_DRAW_FLAG_CLIP
) == EFI_HII_DRAW_FLAG_CLIP
) && (*Blt
== NULL
)) {
1303 return EFI_INVALID_PARAMETER
;
1306 if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_TRANSPARENT
) {
1307 return EFI_INVALID_PARAMETER
;
1313 // Check whether the image will be drawn transparently or opaquely.
1315 Transparent
= FALSE
;
1316 if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_FORCE_TRANS
) {
1318 } else if ((Flags
& EFI_HII_DRAW_FLAG_TRANSPARENT
) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE
) {
1319 Transparent
= FALSE
;
1322 // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
1323 // on the image's transparency setting.
1325 if ((Image
->Flags
& EFI_IMAGE_TRANSPARENT
) == EFI_IMAGE_TRANSPARENT
) {
1331 // Image cannot be drawn transparently if Blt points to NULL on entry.
1332 // Currently output to Screen transparently is not supported, either.
1336 return EFI_INVALID_PARAMETER
;
1337 } else if ((Flags
& EFI_HII_DIRECT_TO_SCREEN
) == EFI_HII_DIRECT_TO_SCREEN
) {
1338 return EFI_INVALID_PARAMETER
;
1342 Private
= HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
1345 // When Blt points to a non-NULL on entry, this image will be drawn onto
1346 // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
1347 // Otherwise a new bitmap will be allocated to hold this image.
1351 // Make sure the BltX and BltY is inside the Blt area.
1353 if ((BltX
>= (*Blt
)->Width
) || (BltY
>= (*Blt
)->Height
)) {
1354 return EFI_INVALID_PARAMETER
;
1358 // Clip the image by (Width, Height)
1361 Width
= Image
->Width
;
1362 Height
= Image
->Height
;
1364 if (Width
> (*Blt
)->Width
- (UINT16
)BltX
) {
1365 Width
= (*Blt
)->Width
- (UINT16
)BltX
;
1368 if (Height
> (*Blt
)->Height
- (UINT16
)BltY
) {
1369 Height
= (*Blt
)->Height
- (UINT16
)BltY
;
1373 // Prepare the buffer for the temporary image.
1374 // Make sure the buffer size doesn't overflow UINTN.
1376 BufferLen
= Width
* Height
;
1377 if (BufferLen
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
1378 return EFI_OUT_OF_RESOURCES
;
1381 BufferLen
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1382 BltBuffer
= AllocateZeroPool (BufferLen
);
1383 if (BltBuffer
== NULL
) {
1384 return EFI_OUT_OF_RESOURCES
;
1387 if ((Width
== Image
->Width
) && (Height
== Image
->Height
)) {
1388 CopyMem (BltBuffer
, Image
->Bitmap
, BufferLen
);
1390 for (Ypos
= 0; Ypos
< Height
; Ypos
++) {
1391 OffsetY1
= Image
->Width
* Ypos
;
1392 OffsetY2
= Width
* Ypos
;
1393 for (Xpos
= 0; Xpos
< Width
; Xpos
++) {
1394 BltBuffer
[OffsetY2
+ Xpos
] = Image
->Bitmap
[OffsetY1
+ Xpos
];
1400 // Draw the image to existing bitmap or screen depending on flag.
1402 if ((Flags
& EFI_HII_DIRECT_TO_SCREEN
) == EFI_HII_DIRECT_TO_SCREEN
) {
1404 // Caller should make sure the current UGA console is grarphic mode.
1408 // Write the image directly to the output device specified by Screen.
1410 Status
= (*Blt
)->Image
.Screen
->Blt (
1411 (*Blt
)->Image
.Screen
,
1413 EfiBltBufferToVideo
,
1424 // Draw the image onto the existing bitmap specified by Bitmap.
1426 Status
= ImageToBlt (
1437 FreePool (BltBuffer
);
1441 // Allocate a new bitmap to hold the incoming image.
1445 // Make sure the final width and height doesn't overflow UINT16.
1447 if ((BltX
> (UINTN
)MAX_UINT16
- Image
->Width
) || (BltY
> (UINTN
)MAX_UINT16
- Image
->Height
)) {
1448 return EFI_INVALID_PARAMETER
;
1451 Width
= Image
->Width
+ (UINT16
)BltX
;
1452 Height
= Image
->Height
+ (UINT16
)BltY
;
1455 // Make sure the output image size doesn't overflow UINTN.
1457 BufferLen
= Width
* Height
;
1458 if (BufferLen
> MAX_UINTN
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
1459 return EFI_OUT_OF_RESOURCES
;
1462 BufferLen
*= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1463 BltBuffer
= AllocateZeroPool (BufferLen
);
1464 if (BltBuffer
== NULL
) {
1465 return EFI_OUT_OF_RESOURCES
;
1468 ImageOut
= (EFI_IMAGE_OUTPUT
*)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT
));
1469 if (ImageOut
== NULL
) {
1470 FreePool (BltBuffer
);
1471 return EFI_OUT_OF_RESOURCES
;
1474 ImageOut
->Width
= Width
;
1475 ImageOut
->Height
= Height
;
1476 ImageOut
->Image
.Bitmap
= BltBuffer
;
1479 // BUGBUG: Now all the "blank" pixels are filled with system default background
1480 // color. Not sure if it need to be updated or not.
1482 Status
= GetSystemFont (Private
, &FontInfo
, NULL
);
1483 if (EFI_ERROR (Status
)) {
1484 FreePool (BltBuffer
);
1485 FreePool (ImageOut
);
1489 ASSERT (FontInfo
!= NULL
);
1490 for (Index
= 0; Index
< (UINTN
)Width
* Height
; Index
++) {
1491 BltBuffer
[Index
] = FontInfo
->BackgroundColor
;
1494 FreePool (FontInfo
);
1497 // Draw the incoming image to the new created image.
1513 This function renders an image to a bitmap or the screen using the specified
1514 color and options. It draws the image on an existing bitmap, allocates a new
1515 bitmap or uses the screen. The images can be clipped.
1517 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1518 @param Flags Describes how the image is to be drawn.
1519 @param PackageList The package list in the HII database to search for
1520 the specified image.
1521 @param ImageId The image's id, which is unique within
1523 @param Blt If this points to a non-NULL on entry, this points
1524 to the image, which is Width pixels wide and
1525 Height pixels high. The image will be drawn onto
1527 EFI_HII_DRAW_FLAG_CLIP is implied. If this points
1528 to a NULL on entry, then a buffer will be
1529 allocated to hold the generated image and the
1530 pointer updated on exit. It is the caller's
1531 responsibility to free this buffer.
1532 @param BltX Specifies the offset from the left and top edge of
1533 the output image of the first pixel in the image.
1534 @param BltY Specifies the offset from the left and top edge of
1535 the output image of the first pixel in the image.
1537 @retval EFI_SUCCESS The image was successfully drawn.
1538 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1539 @retval EFI_INVALID_PARAMETER The Blt was NULL.
1540 @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
1541 The specified PackageList is not in the database.
1547 IN CONST EFI_HII_IMAGE_PROTOCOL
*This
,
1548 IN EFI_HII_DRAW_FLAGS Flags
,
1549 IN EFI_HII_HANDLE PackageList
,
1550 IN EFI_IMAGE_ID ImageId
,
1551 IN OUT EFI_IMAGE_OUTPUT
**Blt
,
1557 EFI_IMAGE_INPUT Image
;
1560 // Check input parameter.
1562 if ((This
== NULL
) || (Blt
== NULL
)) {
1563 return EFI_INVALID_PARAMETER
;
1567 // Get the specified Image.
1569 Status
= HiiGetImage (This
, PackageList
, ImageId
, &Image
);
1570 if (EFI_ERROR (Status
)) {
1577 Status
= HiiDrawImage (This
, Flags
, &Image
, Blt
, BltX
, BltY
);
1578 if (Image
.Bitmap
!= NULL
) {
1579 FreePool (Image
.Bitmap
);