soc/mediatek/mt8196: Initialize SSPM
[coreboot2.git] / src / drivers / intel / fsp2_0 / fsp_gop_blt.c
blob8292b3b68d9815ea5d5439007999d5cf88e2dd11
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <bootsplash.h>
4 #include <console/console.h>
5 #include <fsp/api.h>
6 #include <fsp/fsp_gop_blt.h>
7 #include <stdlib.h>
9 static bool is_bmp_image_valid(efi_bmp_image_header *header)
11 if (header == NULL)
12 return false;
14 /* Check if the BMP Header Signature is valid */
15 if (header->CharB != 'B' || header->CharM != 'M')
16 return false;
18 /* Check if the BMP Image Header Length is valid */
19 if (!header->PixelHeight || !header->PixelWidth)
20 return false;
22 if (header->Size < header->ImageOffset)
23 return false;
25 if (header->ImageOffset < sizeof(efi_bmp_image_header))
26 return false;
28 return true;
31 static bool is_bmp_image_compressed(efi_bmp_image_header *header)
33 if (header == NULL)
34 return false;
36 if (header->CompressionType != 0)
37 return true;
39 return false;
42 static bool is_bitmap_format_supported(efi_bmp_image_header *header)
44 if (header == NULL)
45 return false;
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))
53 return false;
55 return true;
58 static bool do_bmp_image_authentication(efi_bmp_image_header *header)
60 if (header == NULL)
61 return false;
63 if (!is_bmp_image_valid(header)) {
64 printk(BIOS_ERR, "%s: BMP Image Header is invalid.\n", __func__);
65 return false;
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__);
74 return false;
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);
80 return false;
83 return true;
86 static uint32_t calculate_blt_buffer_size(efi_bmp_image_header *header)
88 uint32_t blt_buffer_size;
90 if (header == NULL)
91 return 0;
93 /* Calculate the size required for BLT buffer */
94 blt_buffer_size = header->PixelWidth * header->PixelHeight *
95 sizeof(efi_graphics_output_blt_pixel);
96 if (!blt_buffer_size)
97 return 0;
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;
106 if (header == NULL)
107 return 0;
109 switch (header->BitPerPixel) {
110 case 1:
111 col_map_number = 2;
112 break;
113 case 4:
114 col_map_number = 16;
115 break;
116 case 8:
117 col_map_number = 256;
118 break;
119 default:
120 break;
124 * At times BMP file may have padding data between its header section and the
125 * data section.
127 if (header->ImageOffset - sizeof(efi_bmp_image_header) <
128 sizeof(efi_bmp_color_map) * col_map_number)
129 return 0;
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;
141 uint8_t *bmp_image;
142 uint8_t *bmp_image_header;
143 efi_bmp_color_map *bmp_color_map;
144 size_t image_index;
146 if (header == NULL)
147 return NULL;
149 gop_blt_ptr = malloc(sizeof(blt_buffer_size));
150 if (!gop_blt_ptr)
151 die("%s: out of memory. Consider increasing the `CONFIG_HEAP_SIZE`\n",
152 __func__);
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) *
161 header->PixelWidth];
162 for (size_t width = 0; width < header->PixelWidth; width++, bmp_image++,
163 gop_blt++) {
164 size_t index = 0;
165 switch (header->BitPerPixel) {
166 /* Translate 1-bit (2 colors) BMP to 24-bit color */
167 case 1:
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;
172 gop_blt++;
173 width++;
175 gop_blt--;
176 width--;
177 break;
179 /* Translate 4-bit (16 colors) BMP Palette to 24-bit color */
180 case 4:
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)) {
186 gop_blt++;
187 width++;
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;
193 break;
195 /* Translate 8-bit (256 colors) BMP Palette to 24-bit color */
196 case 8:
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;
200 break;
202 /* For 24-bit BMP */
203 case 24:
204 gop_blt->Blue = *bmp_image++;
205 gop_blt->Green = *bmp_image++;
206 gop_blt->Red = *bmp_image;
207 break;
209 /* Convert 32 bit to 24bit bmp - just ignore the final byte of each pixel */
210 case 32:
211 gop_blt->Blue = *bmp_image++;
212 gop_blt->Green = *bmp_image++;
213 gop_blt->Red = *bmp_image++;
214 break;
216 /* Other bit format of BMP is not supported. */
217 default:
218 free(gop_blt_ptr);
219 gop_blt_ptr = NULL;
221 printk(BIOS_ERR, "%s, BMP Bit format not supported. 0x%X\n", __func__,
222 header->BitPerPixel);
223 return NULL;
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));
232 return gop_blt_ptr;
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)
240 uintptr_t logo_ptr;
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)
245 return;
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__);
251 return;
254 bmp_header = (efi_bmp_image_header *)logo_ptr;
255 if (!do_bmp_image_authentication(bmp_header) || (bmp_header->Size != logo_ptr_size))
256 return;
258 blt_buffer_size = calculate_blt_buffer_size(bmp_header);
259 if (!blt_buffer_size)
260 return;
262 if (!get_color_map_num(bmp_header))
263 return;
265 *logo = logo_ptr;
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);