Attention is currently required from: Andrey Petrov.
Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/76921?usp=email )
Change subject: drivers/intel/fsp2_0: Add API to convert BMP images to GOP BLT buffer ......................................................................
drivers/intel/fsp2_0: Add API to convert BMP images to GOP BLT buffer
This patch adds an API to convert BMP images into GOP BLT buffers for Intel FSP-S. This is required to display the OEM splash screen at pre-boot phase.
Previously, Intel FSP-S had provision to consume the *.BMP file as is. However, starting with the Alder Lake platform, Intel FSP has dropped this conversion logic and expects the bootloader to pass the BLT buffer directly.
This patch implements the conversion logic in coreboot. It also adds a new config (BMP_LOGO_TO_GOP_BLT) to ensure backward compatibility with older generation FSP.
BUG=b:284799726 TEST=Able to build and boot google/rex
Signed-off-by: Subrata Banik subratabanik@google.com Change-Id: I992b45d65374f09498ff0cab497f7091e1e7a350 --- M src/drivers/intel/fsp2_0/Kconfig M src/drivers/intel/fsp2_0/Makefile.inc A src/drivers/intel/fsp2_0/fsp_gop_blt.c A src/drivers/intel/fsp2_0/include/fsp/fsp_gop_blt.h 4 files changed, 296 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/21/76921/1
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 378f4fb..15502b8 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -209,6 +209,17 @@ BMP file only. The uncompressed size can be up to 1 MB. The logo can be compressed using LZMA.
+config BMP_LOGO_TO_GOP_BLT + bool "Enable logo by passing GOP BLT Buffer to FSP" + default n + select BMP_LOGO + depends on HAVE_FSP_LOGO_SUPPORT + help + Uses the FSP to display the boot logo. This method translates a *.BMP graphics image + to a GOP blt buffer which can be directly consumed by FSP (rather running the EDK2 + specific conversion logic). `FSP2_0_LOGO_FILE_NAME` to keep the logo file inside CBFS + in compressed (using LZMA) format. The uncompressed size can be up to 1 MB. + config FSP2_0_LOGO_FILE_NAME string "Logo file" depends on BMP_LOGO diff --git a/src/drivers/intel/fsp2_0/Makefile.inc b/src/drivers/intel/fsp2_0/Makefile.inc index ae82833..11d85e8 100644 --- a/src/drivers/intel/fsp2_0/Makefile.inc +++ b/src/drivers/intel/fsp2_0/Makefile.inc @@ -33,6 +33,7 @@ ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += save_mrc_data.c ramstage-$(CONFIG_MMA) += mma_core.c ramstage-$(CONFIG_ENABLE_FSP_ERROR_INFO) += fsp_error_info_hob.c +ramstage-$(CONFIG_BMP_LOGO_TO_GOP_BLT) += fsp_gop_blt.c
ifneq ($(CONFIG_NO_FSP_TEMP_RAM_EXIT),y) postcar-$(CONFIG_FSP_CAR) += temp_ram_exit.c diff --git a/src/drivers/intel/fsp2_0/fsp_gop_blt.c b/src/drivers/intel/fsp2_0/fsp_gop_blt.c new file mode 100644 index 0000000..e51d537 --- /dev/null +++ b/src/drivers/intel/fsp2_0/fsp_gop_blt.c @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <bootsplash.h> +#include <console/console.h> +#include <fsp/api.h> +#include <fsp/fsp_gop_blt.h> +#include <lib.h> +#include <stdlib.h> + +static bool is_bmp_image_valid(efi_bmp_image_header *header) +{ + if (header == NULL) + return false; + + /* Check if the BMP Header Signature is valid */ + if (header->CharB != 'B' || header->CharM != 'M') + return false; + + /* Check if the BMP Image Header Length is valid */ + if (!header->PixelHeight || !header->PixelWidth) + return false; + + if (header->Size < header->ImageOffset) + return false; + + if (header->ImageOffset < sizeof (efi_bmp_image_header)) + return false; + + return true; +} + +static bool is_bmp_image_compressed(efi_bmp_image_header *header) +{ + if (header == NULL) + return false; + + if (header->CompressionType != 0) + return true; + + return false; +} + +static bool is_bitmap_format_supported(efi_bmp_image_header *header) +{ + if (header == NULL) + return false; + + /* + * Check BITMAP format is supported + * BMP_IMAGE_HEADER = BITMAP_FILE_HEADER + BITMAP_INFO_HEADER + */ + if (header->HeaderSize != sizeof (efi_bmp_image_header) - + OFFSET_OF (efi_bmp_image_header, HeaderSize)) + return false; + + return true; +} + +static bool do_bmp_image_authentication(efi_bmp_image_header *header) +{ + if (header == NULL) + return false; + + if (!is_bmp_image_valid(header)) { + printk(BIOS_ERR, "%s: BMP Image Header is invalid.\n", __func__); + return false; + } + + /* + * BMP image compression is unsupported by FSP implementation, + * hence, exit if the BMP image is compressed. + */ + if (is_bmp_image_compressed(header)) { + printk(BIOS_ERR, "%s: BMP Image Compression is unsupported.\n", __func__); + return false; + } + + if (!is_bitmap_format_supported(header)) { + printk(BIOS_ERR, "%s: BmpHeader Header Size (0x%x) is not as expected.\n", + __func__, header->HeaderSize); + return false; + } + + return true; +} + +static uint32_t calculate_blt_buffer_size(efi_bmp_image_header *header) +{ + uint32_t blt_buffer_size; + + if (header == NULL) + return 0; + + /* Calculate the size required for BLT buffer */ + blt_buffer_size = header->PixelWidth * header->PixelHeight * + sizeof(efi_graphics_output_blt_pixel); + if (!blt_buffer_size) + return 0; + + return blt_buffer_size; +} + +static uint32_t get_color_map_num(efi_bmp_image_header *header) +{ + uint32_t col_map_number = 0; + + if (header == NULL) + return 0; + + switch (header->BitPerPixel) { + case 1: + col_map_number = 2; + break; + case 4: + col_map_number = 16; + break; + case 8: + col_map_number = 256; + break; + default: + break; + } + + /* + * At times BMP file may have padding data between its header section and the + * data section. + */ + if (header->ImageOffset - sizeof (efi_bmp_image_header) < + sizeof (efi_bmp_color_map) * col_map_number) + return 0; + + return col_map_number; +} + +/* Fill BMP image into BLT buffer format */ +static void *fill_blt_buffer(efi_bmp_image_header *header, + uint32_t logo_ptr, uint32_t blt_buffer_size) +{ + efi_graphics_output_blt_pixel *gop_blt_buffer; + efi_graphics_output_blt_pixel *gop_blt_ptr; + efi_graphics_output_blt_pixel *gop_blt; + uint8_t *bmp_image; + uint8_t *bmp_image_header; + efi_bmp_color_map *bmp_color_map; + size_t image_index; + + if (header == NULL) + return NULL; + + gop_blt_ptr = malloc(sizeof(uint8_t) * blt_buffer_size); + if (!gop_blt_ptr) + die("%s: out of memory. Consider increasing the `CONFIG_HEAP_SIZE`\n", + __func__); + + bmp_image = ((UINT8 *)logo_ptr) + header->ImageOffset; + bmp_image_header = bmp_image; + gop_blt_buffer = gop_blt_ptr; + bmp_color_map = (efi_bmp_color_map *)(logo_ptr + sizeof (efi_bmp_image_header)); + + for (size_t height = 0; height < header->PixelHeight; height++) { + gop_blt = &gop_blt_buffer[(header->PixelHeight - height - 1) * + header->PixelWidth]; + for (size_t width = 0; width < header->PixelWidth; width++, bmp_image++, + gop_blt++) { + switch (header->BitPerPixel) { + /* Translate 1-bit (2 colors) BMP to 24-bit color */ + case 1: + for (size_t index = 0; index < 8 && width < header->PixelWidth; index++) { + gop_blt->Red = bmp_color_map[((*bmp_image) >> (7 - index)) & 0x1].Red; + gop_blt->Green = bmp_color_map[((*bmp_image) >> (7 - index)) & 0x1].Green; + gop_blt->Blue = bmp_color_map[((*bmp_image) >> (7 - index)) & 0x1].Blue; + gop_blt++; + width++; + } + gop_blt--; + width--; + break; + + /* Translate 4-bit (16 colors) BMP Palette to 24-bit color */ + case 4: + size_t index = (*bmp_image) >> 4; + gop_blt->Red = bmp_color_map[index].Red; + gop_blt->Green = bmp_color_map[index].Green; + gop_blt->Blue = bmp_color_map[index].Blue; + if (width < (header->PixelWidth - 1)) { + gop_blt++; + width++; + index = (*bmp_image) & 0x0f; + gop_blt->Red = bmp_color_map[index].Red; + gop_blt->Green = bmp_color_map[index].Green; + gop_blt->Blue = bmp_color_map[index].Blue; + } + break; + + /* Translate 8-bit (256 colors) BMP Palette to 24-bit color */ + case 8: + gop_blt->Red = bmp_color_map[*bmp_image].Red; + gop_blt->Green = bmp_color_map[*bmp_image].Green; + gop_blt->Blue = bmp_color_map[*bmp_image].Blue; + break; + + /* For 24-bit BMP */ + case 24: + gop_blt->Blue = *bmp_image++; + gop_blt->Green = *bmp_image++; + gop_blt->Red = *bmp_image; + break; + + /* Conver 32 bit to 24bit bmp - just ignore the final byte of each pixel */ + case 32: + gop_blt->Blue = *bmp_image++; + gop_blt->Green = *bmp_image++; + gop_blt->Red = *bmp_image++; + break; + + /* Other bit format of BMP is not supported. */ + default: + free(gop_blt_ptr); + gop_blt_ptr = NULL; + + printk(BIOS_ERR, "%s, BMP Bit format not supported. 0x%X\n", __func__, + header->BitPerPixel); + return NULL; + break; + } + } + image_index = (uintptr_t)bmp_image - (uintptr_t)bmp_image_header; + /* Each row in BMP Image should be 4-byte align */ + if ((image_index % 4) != 0) + bmp_image = bmp_image + (4 - (image_index % 4)); + } + + return gop_blt_ptr; +} + +/* Convert a *.BMP graphics image to a GOP blt buffer */ +void fsp_convert_bmp_to_gop_blt (uint32_t *logo, uint32_t *logo_size, + uint32_t *blt_ptr, uint32_t *blt_size, + uint32_t *pixel_height, uint32_t *pixel_width) +{ + uint32_t logo_ptr, logo_ptr_size, blt_buffer_size; + efi_bmp_image_header *bmp_header; + + if (!logo || !logo_size || !blt_ptr || !blt_size || !pixel_height || !pixel_width) + return; + + bmp_load_logo(&logo_ptr, &logo_ptr_size); + if (!logo_ptr || logo_ptr_size < sizeof (efi_bmp_image_header)) { + printk(BIOS_ERR, "%s: BMP Image size is too small.\n", __func__); + return; + } + + bmp_header = (efi_bmp_image_header *)logo_ptr; + if (!do_bmp_image_authentication(bmp_header) || (bmp_header->Size != logo_ptr_size)) + return; + + blt_buffer_size = calculate_blt_buffer_size(bmp_header); + if (!blt_buffer_size) + return; + + if (!get_color_map_num(bmp_header)) + return; + + *logo = logo_ptr; + *logo_size = logo_ptr_size; + *blt_size = blt_buffer_size; + *pixel_height = bmp_header->PixelHeight; + *pixel_width = bmp_header->PixelWidth; + *blt_ptr = (uint32_t)fill_blt_buffer(bmp_header, logo_ptr, blt_buffer_size); +} diff --git a/src/drivers/intel/fsp2_0/include/fsp/fsp_gop_blt.h b/src/drivers/intel/fsp2_0/include/fsp/fsp_gop_blt.h new file mode 100644 index 0000000..886859e --- /dev/null +++ b/src/drivers/intel/fsp2_0/include/fsp/fsp_gop_blt.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef FSP_GOP_BLT_H +#define FSP_GOP_BLT_H + +#include <efi/efi_datatype.h> +#include <types.h> + +/* Convert a *.BMP graphics image to a GOP blt buffer */ +void fsp_convert_bmp_to_gop_blt (uint32_t *logo, uint32_t *logo_size, + uint32_t *blt_ptr, uint32_t *blt_size, + uint32_t *pixel_height, uint32_t *pixel_width); + +#endif /* FSP_GOP_BLT_H */