mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
![Josh Triplett](/assets/img/avatar_default.png)
The ACPI BGRT driver accesses the BIOS logo image when it initializes. However, ACPI 5.0 (which introduces the BGRT) recommends putting the logo image in EFI boot services memory, so that the OS can reclaim that memory. Production systems follow this recommendation, breaking the ACPI BGRT driver. Move the bulk of the BGRT code to run during a new EFI late initialization phase, which occurs after switching EFI to virtual mode, and after initializing ACPI, but before freeing boot services memory. Copy the BIOS logo image to kernel memory at that point, and make it accessible to the BGRT driver. Rework the existing ACPI BGRT driver to act as a simple wrapper exposing that image (and the properties from the BGRT) via sysfs. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/93ce9f823f1c1f3bb88bdd662cce08eee7a17f5d.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
118 lines
2.9 KiB
C
118 lines
2.9 KiB
C
/*
|
|
* Copyright 2012 Red Hat, Inc <mjg@redhat.com>
|
|
* Copyright 2012 Intel Corporation
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/device.h>
|
|
#include <linux/sysfs.h>
|
|
#include <linux/efi-bgrt.h>
|
|
|
|
static struct kobject *bgrt_kobj;
|
|
|
|
static ssize_t show_version(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version);
|
|
}
|
|
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
|
|
|
|
static ssize_t show_status(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status);
|
|
}
|
|
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
|
|
|
|
static ssize_t show_type(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type);
|
|
}
|
|
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
|
|
|
static ssize_t show_xoffset(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x);
|
|
}
|
|
static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
|
|
|
|
static ssize_t show_yoffset(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y);
|
|
}
|
|
static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
|
|
|
|
static ssize_t show_image(struct file *file, struct kobject *kobj,
|
|
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
|
|
{
|
|
memcpy(buf, attr->private + off, count);
|
|
return count;
|
|
}
|
|
|
|
static struct bin_attribute image_attr = {
|
|
.attr = {
|
|
.name = "image",
|
|
.mode = S_IRUGO,
|
|
},
|
|
.read = show_image,
|
|
};
|
|
|
|
static struct attribute *bgrt_attributes[] = {
|
|
&dev_attr_version.attr,
|
|
&dev_attr_status.attr,
|
|
&dev_attr_type.attr,
|
|
&dev_attr_xoffset.attr,
|
|
&dev_attr_yoffset.attr,
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group bgrt_attribute_group = {
|
|
.attrs = bgrt_attributes,
|
|
};
|
|
|
|
static int __init bgrt_init(void)
|
|
{
|
|
int ret;
|
|
|
|
if (!bgrt_image)
|
|
return -ENODEV;
|
|
|
|
sysfs_bin_attr_init(&image_attr);
|
|
image_attr.private = bgrt_image;
|
|
image_attr.size = bgrt_image_size;
|
|
|
|
bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
|
|
if (!bgrt_kobj)
|
|
return -EINVAL;
|
|
|
|
ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group);
|
|
if (ret)
|
|
goto out_kobject;
|
|
|
|
ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
|
|
if (ret)
|
|
goto out_group;
|
|
|
|
return 0;
|
|
|
|
out_group:
|
|
sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
|
|
out_kobject:
|
|
kobject_put(bgrt_kobj);
|
|
return ret;
|
|
}
|
|
|
|
module_init(bgrt_init);
|
|
|
|
MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>");
|
|
MODULE_DESCRIPTION("BGRT boot graphic support");
|
|
MODULE_LICENSE("GPL");
|