/* 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 <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(blt_buffer_size));
	if (!gop_blt_ptr)
		die("%s: out of memory. Consider increasing the `CONFIG_HEAP_SIZE`\n",
			 __func__);

	bmp_image = ((uint8_t *)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++) {
			size_t index = 0;
			switch (header->BitPerPixel) {
			/* Translate 1-bit (2 colors) BMP to 24-bit color */
			case 1:
				for (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:
				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;

			/* Convert 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;
			}
		}
		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);
}
