mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-29 01:04:14 -04:00
The BGRT table can be parsed if EFI_PARAVIRT is enabled, even if
EFI_MEMMAP is not. Xen will take care of preserving the image even if
EfiBootServicesData memory is reclaimed already, or invalidate the table
if it didn't preserve it - in both cases accesing the table itself under
virt is safe. Also allow the ESRT to be in reclaimable memory, as that
is where future Xen versions will put it.
This is similar approach as was taken for ESRT table in 01de145dc7
"efi: Actually enable the ESRT under Xen".
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
92 lines
2.3 KiB
C
92 lines
2.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
#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;
|
|
size_t bgrt_image_size;
|
|
|
|
struct bmp_header {
|
|
u16 id;
|
|
u32 size;
|
|
} __packed;
|
|
|
|
void __init efi_bgrt_init(struct acpi_table_header *table)
|
|
{
|
|
void *image;
|
|
struct bmp_header bmp_header;
|
|
struct acpi_table_bgrt *bgrt = &bgrt_tab;
|
|
int mem_type;
|
|
|
|
if (acpi_disabled)
|
|
return;
|
|
|
|
if (!efi_enabled(EFI_MEMMAP) && !efi_enabled(EFI_PARAVIRT))
|
|
return;
|
|
|
|
if (table->length < sizeof(bgrt_tab)) {
|
|
pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n",
|
|
table->length, sizeof(bgrt_tab));
|
|
return;
|
|
}
|
|
*bgrt = *(struct acpi_table_bgrt *)table;
|
|
/*
|
|
* Only version 1 is defined but some older laptops (seen on Lenovo
|
|
* Ivy Bridge models) have a correct version 1 BGRT table with the
|
|
* version set to 0, so we accept version 0 and 1.
|
|
*/
|
|
if (bgrt->version > 1) {
|
|
pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n",
|
|
bgrt->version);
|
|
goto out;
|
|
}
|
|
if (bgrt->image_type != 0) {
|
|
pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n",
|
|
bgrt->image_type);
|
|
goto out;
|
|
}
|
|
if (!bgrt->image_address) {
|
|
pr_notice("Ignoring BGRT: null image address\n");
|
|
goto out;
|
|
}
|
|
|
|
mem_type = efi_mem_type(bgrt->image_address);
|
|
if (mem_type != EFI_BOOT_SERVICES_DATA &&
|
|
mem_type != EFI_ACPI_RECLAIM_MEMORY) {
|
|
pr_notice("Ignoring BGRT: invalid image address\n");
|
|
goto out;
|
|
}
|
|
image = early_memremap(bgrt->image_address, sizeof(bmp_header));
|
|
if (!image) {
|
|
pr_notice("Ignoring BGRT: failed to map image header memory\n");
|
|
goto out;
|
|
}
|
|
|
|
memcpy(&bmp_header, image, sizeof(bmp_header));
|
|
early_memunmap(image, sizeof(bmp_header));
|
|
if (bmp_header.id != 0x4d42) {
|
|
pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n",
|
|
bmp_header.id);
|
|
goto out;
|
|
}
|
|
bgrt_image_size = bmp_header.size;
|
|
efi_mem_reserve(bgrt->image_address, bgrt_image_size);
|
|
|
|
return;
|
|
out:
|
|
memset(bgrt, 0, sizeof(bgrt_tab));
|
|
}
|