2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * This program is free software; you can redistribute it and/or modify it
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * under the terms of the GNU Lesser General Public License as published by
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * the Free Software Foundation; either version 2.1 of the License, or
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * (at your option) any later version.
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * This program is distributed in the hope that it will be useful, but
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * WITHOUT ANY WARRANTY; without even the implied warranty of
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * Lesser General Public License for more details.
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers/* we require at least BITMAPINFOHEADER, later versions are
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers accepted, but their features ignored */
2f8d336478536af789d654599f9523d02e0ca693Kay SieversEFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib,
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* check file header */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (file->signature[0] != 'B' || file->signature[1] != 'M')
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* check device-independent bitmap */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers dib = (struct bmp_dib *)(bmp + sizeof(struct bmp_file));
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (dib->compression != 0 && dib->compression != 3)
7c5925a448551129ec2e11157c847703def79608Zbigniew Jędrzejewski-Szmek row_size = ((UINTN) dib->depth * dib->x + 31) / 32 * 4;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (file->size - file->offset < dib->y * row_size)
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* check color table */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers map = (struct bmp_map *)(bmp + sizeof(struct bmp_file) + dib->size);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (file->offset < sizeof(struct bmp_file) + dib->size)
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (file->offset > sizeof(struct bmp_file) + dib->size) {
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers map_size = file->offset - (sizeof(struct bmp_file) + dib->size);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (map_size != sizeof(struct bmp_map) * map_count)
2f8d336478536af789d654599f9523d02e0ca693Kay Sieversstatic VOID pixel_blend(UINT32 *dst, const UINT32 source) {
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* convert src from RGBA to XRGB */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* decompose into RB and G components */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers rb = ((((src_rb - dst_rb) * alpha + 0x800080) >> 8) + dst_rb) & 0xff00ff;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers g = ((((src_g - dst_g) * alpha + 0x008000) >> 8) + dst_g) & 0x00ff00;
2f8d336478536af789d654599f9523d02e0ca693Kay SieversEFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* transform and copy pixels */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers for (y = 0; y < dib->y; y++) {
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* add row padding; new lines always start at 32 bit boundary */
2f8d336478536af789d654599f9523d02e0ca693Kay SieversEFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background) {
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) {
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers err = bmp_parse_header(content, len, &dib, &map, &pixmap);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2;
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers GraphicsOutput->Mode->Info->HorizontalResolution,
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers GraphicsOutput->Mode->Info->VerticalResolution, 0);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers /* EFI buffer */
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers blt_size = dib->x * dib->y * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
2f8d336478536af789d654599f9523d02e0ca693Kay Sievers blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0,