Commit e45705fe authored by Dave Young's avatar Dave Young Committed by Ard Biesheuvel

efi/x86: Move EFI BGRT init code to early init code

Before invoking the arch specific handler, efi_mem_reserve() reserves
the given memory region through memblock.

efi_bgrt_init() will call efi_mem_reserve() after mm_init(), at which
time memblock is dead and should not be used anymore.

The EFI BGRT code depends on ACPI initialization to get the BGRT ACPI
table, so move parsing of the BGRT table to ACPI early boot code to
ensure that efi_mem_reserve() in EFI BGRT code still use memblock safely.
Signed-off-by: default avatarDave Young <dyoung@redhat.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
Tested-by: default avatarBhupesh Sharma <bhsharma@redhat.com>
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
parent 7e8595e5
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/efi-bgrt.h>
#include <asm/irqdomain.h> #include <asm/irqdomain.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
...@@ -1557,6 +1558,12 @@ int __init early_acpi_boot_init(void) ...@@ -1557,6 +1558,12 @@ int __init early_acpi_boot_init(void)
return 0; return 0;
} }
static int __init acpi_parse_bgrt(struct acpi_table_header *table)
{
efi_bgrt_init(table);
return 0;
}
int __init acpi_boot_init(void) int __init acpi_boot_init(void)
{ {
/* those are executed after early-quirks are executed */ /* those are executed after early-quirks are executed */
...@@ -1581,6 +1588,8 @@ int __init acpi_boot_init(void) ...@@ -1581,6 +1588,8 @@ int __init acpi_boot_init(void)
acpi_process_madt(); acpi_process_madt();
acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
if (IS_ENABLED(CONFIG_ACPI_BGRT))
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
if (!acpi_noirq) if (!acpi_noirq)
x86_init.pci.init = pci_acpi_init; x86_init.pci.init = pci_acpi_init;
......
...@@ -19,8 +19,7 @@ ...@@ -19,8 +19,7 @@
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/efi-bgrt.h> #include <linux/efi-bgrt.h>
struct acpi_table_bgrt *bgrt_tab; struct acpi_table_bgrt bgrt_tab;
void *__initdata bgrt_image;
size_t __initdata bgrt_image_size; size_t __initdata bgrt_image_size;
struct bmp_header { struct bmp_header {
...@@ -28,66 +27,58 @@ struct bmp_header { ...@@ -28,66 +27,58 @@ struct bmp_header {
u32 size; u32 size;
} __packed; } __packed;
void __init efi_bgrt_init(void) void __init efi_bgrt_init(struct acpi_table_header *table)
{ {
acpi_status status;
void *image; void *image;
struct bmp_header bmp_header; struct bmp_header bmp_header;
struct acpi_table_bgrt *bgrt = &bgrt_tab;
if (acpi_disabled) if (acpi_disabled)
return; return;
status = acpi_get_table("BGRT", 0, if (table->length < sizeof(bgrt_tab)) {
(struct acpi_table_header **)&bgrt_tab);
if (ACPI_FAILURE(status))
return;
if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n",
bgrt_tab->header.length, sizeof(*bgrt_tab)); table->length, sizeof(bgrt_tab));
return; return;
} }
if (bgrt_tab->version != 1) { *bgrt = *(struct acpi_table_bgrt *)table;
if (bgrt->version != 1) {
pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n", pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n",
bgrt_tab->version); bgrt->version);
return; goto out;
} }
if (bgrt_tab->status & 0xfe) { if (bgrt->status & 0xfe) {
pr_notice("Ignoring BGRT: reserved status bits are non-zero %u\n", pr_notice("Ignoring BGRT: reserved status bits are non-zero %u\n",
bgrt_tab->status); bgrt->status);
return; goto out;
} }
if (bgrt_tab->image_type != 0) { if (bgrt->image_type != 0) {
pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n", pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n",
bgrt_tab->image_type); bgrt->image_type);
return; goto out;
} }
if (!bgrt_tab->image_address) { if (!bgrt->image_address) {
pr_notice("Ignoring BGRT: null image address\n"); pr_notice("Ignoring BGRT: null image address\n");
return; goto out;
} }
image = memremap(bgrt_tab->image_address, sizeof(bmp_header), MEMREMAP_WB); image = early_memremap(bgrt->image_address, sizeof(bmp_header));
if (!image) { if (!image) {
pr_notice("Ignoring BGRT: failed to map image header memory\n"); pr_notice("Ignoring BGRT: failed to map image header memory\n");
return; goto out;
} }
memcpy(&bmp_header, image, sizeof(bmp_header)); memcpy(&bmp_header, image, sizeof(bmp_header));
memunmap(image); early_memunmap(image, sizeof(bmp_header));
if (bmp_header.id != 0x4d42) { if (bmp_header.id != 0x4d42) {
pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n", pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n",
bmp_header.id); bmp_header.id);
return; goto out;
} }
bgrt_image_size = bmp_header.size; bgrt_image_size = bmp_header.size;
efi_mem_reserve(bgrt->image_address, bgrt_image_size);
bgrt_image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB); return;
if (!bgrt_image) { out:
pr_notice("Ignoring BGRT: failed to map image memory\n"); memset(bgrt, 0, sizeof(bgrt_tab));
bgrt_image = NULL;
return;
}
efi_mem_reserve(bgrt_tab->image_address, bgrt_image_size);
} }
...@@ -542,11 +542,6 @@ void __init efi_init(void) ...@@ -542,11 +542,6 @@ void __init efi_init(void)
efi_print_memmap(); efi_print_memmap();
} }
void __init efi_late_init(void)
{
efi_bgrt_init();
}
void __init efi_set_executable(efi_memory_desc_t *md, bool executable) void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
{ {
u64 addr, npages; u64 addr, npages;
......
...@@ -15,40 +15,41 @@ ...@@ -15,40 +15,41 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/efi-bgrt.h> #include <linux/efi-bgrt.h>
static void *bgrt_image;
static struct kobject *bgrt_kobj; static struct kobject *bgrt_kobj;
static ssize_t show_version(struct device *dev, static ssize_t show_version(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version); return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version);
} }
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static ssize_t show_status(struct device *dev, static ssize_t show_status(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status); return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status);
} }
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static ssize_t show_type(struct device *dev, static ssize_t show_type(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type); return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type);
} }
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
static ssize_t show_xoffset(struct device *dev, static ssize_t show_xoffset(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x); return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x);
} }
static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL); static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
static ssize_t show_yoffset(struct device *dev, static ssize_t show_yoffset(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y); return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y);
} }
static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
...@@ -84,15 +85,24 @@ static int __init bgrt_init(void) ...@@ -84,15 +85,24 @@ static int __init bgrt_init(void)
{ {
int ret; int ret;
if (!bgrt_image) if (!bgrt_tab.image_address)
return -ENODEV; return -ENODEV;
bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
MEMREMAP_WB);
if (!bgrt_image) {
pr_notice("Ignoring BGRT: failed to map image memory\n");
return -ENOMEM;
}
bin_attr_image.private = bgrt_image; bin_attr_image.private = bgrt_image;
bin_attr_image.size = bgrt_image_size; bin_attr_image.size = bgrt_image_size;
bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
if (!bgrt_kobj) if (!bgrt_kobj) {
return -EINVAL; ret = -EINVAL;
goto out_memmap;
}
ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group);
if (ret) if (ret)
...@@ -102,6 +112,8 @@ static int __init bgrt_init(void) ...@@ -102,6 +112,8 @@ static int __init bgrt_init(void)
out_kobject: out_kobject:
kobject_put(bgrt_kobj); kobject_put(bgrt_kobj);
out_memmap:
memunmap(bgrt_image);
return ret; return ret;
} }
device_initcall(bgrt_init); device_initcall(bgrt_init);
#ifndef _LINUX_EFI_BGRT_H #ifndef _LINUX_EFI_BGRT_H
#define _LINUX_EFI_BGRT_H #define _LINUX_EFI_BGRT_H
#ifdef CONFIG_ACPI_BGRT
#include <linux/acpi.h> #include <linux/acpi.h>
void efi_bgrt_init(void); #ifdef CONFIG_ACPI_BGRT
void efi_bgrt_init(struct acpi_table_header *table);
/* The BGRT data itself; only valid if bgrt_image != NULL. */ /* The BGRT data itself; only valid if bgrt_image != NULL. */
extern void *bgrt_image;
extern size_t bgrt_image_size; extern size_t bgrt_image_size;
extern struct acpi_table_bgrt *bgrt_tab; extern struct acpi_table_bgrt bgrt_tab;
#else /* !CONFIG_ACPI_BGRT */ #else /* !CONFIG_ACPI_BGRT */
static inline void efi_bgrt_init(void) {} static inline void efi_bgrt_init(struct acpi_table_header *table) {}
#endif /* !CONFIG_ACPI_BGRT */ #endif /* !CONFIG_ACPI_BGRT */
......
...@@ -663,7 +663,6 @@ asmlinkage __visible void __init start_kernel(void) ...@@ -663,7 +663,6 @@ asmlinkage __visible void __init start_kernel(void)
sfi_init_late(); sfi_init_late();
if (efi_enabled(EFI_RUNTIME_SERVICES)) { if (efi_enabled(EFI_RUNTIME_SERVICES)) {
efi_late_init();
efi_free_boot_services(); efi_free_boot_services();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment