forked from Minki/linux
66dbe99cfe
Unintuitively, the BGRT graphic is apparently meant to be usable if the valid bit in not set. The valid bit only conveys uncertainty about the validity in relation to the screen state. Windows 10 actually uses the BGRT image for its boot screen even if not 'valid', for example when the user triggered the boot menu. Because it is unclear if all firmwares will provide a usable graphic in this case, we now look at the BMP magic number as an additional check. Reviewed-by: Josh Triplett <josh@joshtriplett.org> Signed-off-by: Môshe van der Sterre <me@moshe.nl> Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk> Cc: =?UTF-8?q?M=C3=B4she=20van=20der=20Sterre?= <me@moshe.nl> Link: http://lkml.kernel.org/r/1454364428-494-10-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar <mingo@kernel.org>
103 lines
2.5 KiB
C
103 lines
2.5 KiB
C
/*
|
|
* Copyright 2012 Intel Corporation
|
|
* Author: Josh Triplett <josh@joshtriplett.org>
|
|
*
|
|
* Based on the bgrt driver:
|
|
* Copyright 2012 Red Hat, Inc <mjg@redhat.com>
|
|
* Author: Matthew Garrett
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/efi.h>
|
|
#include <linux/efi-bgrt.h>
|
|
|
|
struct acpi_table_bgrt *bgrt_tab;
|
|
void *__initdata bgrt_image;
|
|
size_t __initdata bgrt_image_size;
|
|
|
|
struct bmp_header {
|
|
u16 id;
|
|
u32 size;
|
|
} __packed;
|
|
|
|
void __init efi_bgrt_init(void)
|
|
{
|
|
acpi_status status;
|
|
void *image;
|
|
struct bmp_header bmp_header;
|
|
|
|
if (acpi_disabled)
|
|
return;
|
|
|
|
status = acpi_get_table("BGRT", 0,
|
|
(struct acpi_table_header **)&bgrt_tab);
|
|
if (ACPI_FAILURE(status))
|
|
return;
|
|
|
|
if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
|
|
pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n",
|
|
bgrt_tab->header.length, sizeof(*bgrt_tab));
|
|
return;
|
|
}
|
|
if (bgrt_tab->version != 1) {
|
|
pr_err("Ignoring BGRT: invalid version %u (expected 1)\n",
|
|
bgrt_tab->version);
|
|
return;
|
|
}
|
|
if (bgrt_tab->status & 0xfe) {
|
|
pr_err("Ignoring BGRT: reserved status bits are non-zero %u\n",
|
|
bgrt_tab->status);
|
|
return;
|
|
}
|
|
if (bgrt_tab->image_type != 0) {
|
|
pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
|
|
bgrt_tab->image_type);
|
|
return;
|
|
}
|
|
if (!bgrt_tab->image_address) {
|
|
pr_err("Ignoring BGRT: null image address\n");
|
|
return;
|
|
}
|
|
|
|
image = memremap(bgrt_tab->image_address, sizeof(bmp_header), MEMREMAP_WB);
|
|
if (!image) {
|
|
pr_err("Ignoring BGRT: failed to map image header memory\n");
|
|
return;
|
|
}
|
|
|
|
memcpy(&bmp_header, image, sizeof(bmp_header));
|
|
memunmap(image);
|
|
if (bmp_header.id != 0x4d42) {
|
|
pr_err("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n",
|
|
bmp_header.id);
|
|
return;
|
|
}
|
|
bgrt_image_size = bmp_header.size;
|
|
|
|
bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
|
|
if (!bgrt_image) {
|
|
pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n",
|
|
bgrt_image_size);
|
|
return;
|
|
}
|
|
|
|
image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB);
|
|
if (!image) {
|
|
pr_err("Ignoring BGRT: failed to map image memory\n");
|
|
kfree(bgrt_image);
|
|
bgrt_image = NULL;
|
|
return;
|
|
}
|
|
|
|
memcpy(bgrt_image, image, bgrt_image_size);
|
|
memunmap(image);
|
|
}
|