1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <bootsplash.h>
4 #include <console/console.h>
6 #include <fsp/fsp_gop_blt.h>
9 static bool is_bmp_image_valid(efi_bmp_image_header
*header
)
14 /* Check if the BMP Header Signature is valid */
15 if (header
->CharB
!= 'B' || header
->CharM
!= 'M')
18 /* Check if the BMP Image Header Length is valid */
19 if (!header
->PixelHeight
|| !header
->PixelWidth
)
22 if (header
->Size
< header
->ImageOffset
)
25 if (header
->ImageOffset
< sizeof(efi_bmp_image_header
))
31 static bool is_bmp_image_compressed(efi_bmp_image_header
*header
)
36 if (header
->CompressionType
!= 0)
42 static bool is_bitmap_format_supported(efi_bmp_image_header
*header
)
48 * Check BITMAP format is supported
49 * BMP_IMAGE_HEADER = BITMAP_FILE_HEADER + BITMAP_INFO_HEADER
51 if (header
->HeaderSize
!= sizeof(efi_bmp_image_header
) -
52 OFFSET_OF(efi_bmp_image_header
, HeaderSize
))
58 static bool do_bmp_image_authentication(efi_bmp_image_header
*header
)
63 if (!is_bmp_image_valid(header
)) {
64 printk(BIOS_ERR
, "%s: BMP Image Header is invalid.\n", __func__
);
69 * BMP image compression is unsupported by FSP implementation,
70 * hence, exit if the BMP image is compressed.
72 if (is_bmp_image_compressed(header
)) {
73 printk(BIOS_ERR
, "%s: BMP Image Compression is unsupported.\n", __func__
);
77 if (!is_bitmap_format_supported(header
)) {
78 printk(BIOS_ERR
, "%s: BmpHeader Header Size (0x%x) is not as expected.\n",
79 __func__
, header
->HeaderSize
);
86 static uint32_t calculate_blt_buffer_size(efi_bmp_image_header
*header
)
88 uint32_t blt_buffer_size
;
93 /* Calculate the size required for BLT buffer */
94 blt_buffer_size
= header
->PixelWidth
* header
->PixelHeight
*
95 sizeof(efi_graphics_output_blt_pixel
);
99 return blt_buffer_size
;
102 static uint32_t get_color_map_num(efi_bmp_image_header
*header
)
104 uint32_t col_map_number
= 0;
109 switch (header
->BitPerPixel
) {
117 col_map_number
= 256;
124 * At times BMP file may have padding data between its header section and the
127 if (header
->ImageOffset
- sizeof(efi_bmp_image_header
) <
128 sizeof(efi_bmp_color_map
) * col_map_number
)
131 return col_map_number
;
134 /* Fill BMP image into BLT buffer format */
135 static void *fill_blt_buffer(efi_bmp_image_header
*header
,
136 uintptr_t logo_ptr
, size_t blt_buffer_size
)
138 efi_graphics_output_blt_pixel
*gop_blt_buffer
;
139 efi_graphics_output_blt_pixel
*gop_blt_ptr
;
140 efi_graphics_output_blt_pixel
*gop_blt
;
142 uint8_t *bmp_image_header
;
143 efi_bmp_color_map
*bmp_color_map
;
149 gop_blt_ptr
= malloc(sizeof(blt_buffer_size
));
151 die("%s: out of memory. Consider increasing the `CONFIG_HEAP_SIZE`\n",
154 bmp_image
= ((uint8_t *)logo_ptr
) + header
->ImageOffset
;
155 bmp_image_header
= bmp_image
;
156 gop_blt_buffer
= gop_blt_ptr
;
157 bmp_color_map
= (efi_bmp_color_map
*)(logo_ptr
+ sizeof(efi_bmp_image_header
));
159 for (size_t height
= 0; height
< header
->PixelHeight
; height
++) {
160 gop_blt
= &gop_blt_buffer
[(header
->PixelHeight
- height
- 1) *
162 for (size_t width
= 0; width
< header
->PixelWidth
; width
++, bmp_image
++,
165 switch (header
->BitPerPixel
) {
166 /* Translate 1-bit (2 colors) BMP to 24-bit color */
168 for (index
= 0; index
< 8 && width
< header
->PixelWidth
; index
++) {
169 gop_blt
->Red
= bmp_color_map
[((*bmp_image
) >> (7 - index
)) & 0x1].Red
;
170 gop_blt
->Green
= bmp_color_map
[((*bmp_image
) >> (7 - index
)) & 0x1].Green
;
171 gop_blt
->Blue
= bmp_color_map
[((*bmp_image
) >> (7 - index
)) & 0x1].Blue
;
179 /* Translate 4-bit (16 colors) BMP Palette to 24-bit color */
181 index
= (*bmp_image
) >> 4;
182 gop_blt
->Red
= bmp_color_map
[index
].Red
;
183 gop_blt
->Green
= bmp_color_map
[index
].Green
;
184 gop_blt
->Blue
= bmp_color_map
[index
].Blue
;
185 if (width
< (header
->PixelWidth
- 1)) {
188 index
= (*bmp_image
) & 0x0f;
189 gop_blt
->Red
= bmp_color_map
[index
].Red
;
190 gop_blt
->Green
= bmp_color_map
[index
].Green
;
191 gop_blt
->Blue
= bmp_color_map
[index
].Blue
;
195 /* Translate 8-bit (256 colors) BMP Palette to 24-bit color */
197 gop_blt
->Red
= bmp_color_map
[*bmp_image
].Red
;
198 gop_blt
->Green
= bmp_color_map
[*bmp_image
].Green
;
199 gop_blt
->Blue
= bmp_color_map
[*bmp_image
].Blue
;
204 gop_blt
->Blue
= *bmp_image
++;
205 gop_blt
->Green
= *bmp_image
++;
206 gop_blt
->Red
= *bmp_image
;
209 /* Convert 32 bit to 24bit bmp - just ignore the final byte of each pixel */
211 gop_blt
->Blue
= *bmp_image
++;
212 gop_blt
->Green
= *bmp_image
++;
213 gop_blt
->Red
= *bmp_image
++;
216 /* Other bit format of BMP is not supported. */
221 printk(BIOS_ERR
, "%s, BMP Bit format not supported. 0x%X\n", __func__
,
222 header
->BitPerPixel
);
226 image_index
= (uintptr_t)bmp_image
- (uintptr_t)bmp_image_header
;
227 /* Each row in BMP Image should be 4-byte align */
228 if ((image_index
% 4) != 0)
229 bmp_image
= bmp_image
+ (4 - (image_index
% 4));
235 /* Convert a *.BMP graphics image to a GOP blt buffer */
236 void fsp_convert_bmp_to_gop_blt(efi_uintn_t
*logo
, uint32_t *logo_size
,
237 efi_uintn_t
*blt_ptr
, efi_uintn_t
*blt_size
,
238 uint32_t *pixel_height
, uint32_t *pixel_width
)
241 size_t logo_ptr_size
, blt_buffer_size
;
242 efi_bmp_image_header
*bmp_header
;
244 if (!logo
|| !logo_size
|| !blt_ptr
|| !blt_size
|| !pixel_height
|| !pixel_width
)
247 logo_ptr
= (uintptr_t)bmp_load_logo(&logo_ptr_size
);
249 if (!logo_ptr
|| logo_ptr_size
< sizeof(efi_bmp_image_header
)) {
250 printk(BIOS_ERR
, "%s: BMP Image size is too small.\n", __func__
);
254 bmp_header
= (efi_bmp_image_header
*)logo_ptr
;
255 if (!do_bmp_image_authentication(bmp_header
) || (bmp_header
->Size
!= logo_ptr_size
))
258 blt_buffer_size
= calculate_blt_buffer_size(bmp_header
);
259 if (!blt_buffer_size
)
262 if (!get_color_map_num(bmp_header
))
266 *logo_size
= logo_ptr_size
;
267 *blt_size
= blt_buffer_size
;
268 *pixel_height
= bmp_header
->PixelHeight
;
269 *pixel_width
= bmp_header
->PixelWidth
;
270 *blt_ptr
= (uintptr_t)fill_blt_buffer(bmp_header
, logo_ptr
, blt_buffer_size
);