diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-07-17 16:17:36 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-07-17 16:17:36 +0200 |
commit | a3db9d60a118571e696b684a6e8c692a2b064941 (patch) | |
tree | ff7bae0f79b7a2ee0bce03de4f883550200c52a9 /drivers/platform/x86/wmi-bmof.c | |
parent | media: staging: cxd2099: Activate cxd2099 buffer mode (diff) | |
parent | Linux v4.13-rc1 (diff) | |
download | linux-a3db9d60a118571e696b684a6e8c692a2b064941.tar.xz linux-a3db9d60a118571e696b684a6e8c692a2b064941.zip |
Merge tag 'v4.13-rc1' into patchwork
Linux v4.13-rc1
* tag 'v4.13-rc1': (11136 commits)
Linux v4.13-rc1
random: reorder READ_ONCE() in get_random_uXX
random: suppress spammy warnings about unseeded randomness
replace incorrect strscpy use in FORTIFY_SOURCE
kmod: throttle kmod thread limit
kmod: add test driver to stress test the module loader
MAINTAINERS: give kmod some maintainer love
xtensa: use generic fb.h
fault-inject: add /proc/<pid>/fail-nth
fault-inject: simplify access check for fail-nth
fault-inject: make fail-nth read/write interface symmetric
fault-inject: parse as natural 1-based value for fail-nth write interface
fault-inject: automatically detect the number base for fail-nth write interface
kernel/watchdog.c: use better pr_fmt prefix
MAINTAINERS: move the befs tree to kernel.org
lib/atomic64_test.c: add a test that atomic64_inc_not_zero() returns an int
mm: fix overflow check in expand_upwards()
ubifs: Set double hash cookie also for RENAME_EXCHANGE
ubifs: Massage assert in ubifs_xattr_set() wrt. init_xattrs
ubifs: Don't leak kernel memory to the MTD
...
Diffstat (limited to 'drivers/platform/x86/wmi-bmof.c')
-rw-r--r-- | drivers/platform/x86/wmi-bmof.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/platform/x86/wmi-bmof.c b/drivers/platform/x86/wmi-bmof.c new file mode 100644 index 000000000000..c4530ba715e8 --- /dev/null +++ b/drivers/platform/x86/wmi-bmof.c @@ -0,0 +1,125 @@ +/* + * WMI embedded Binary MOF driver + * + * Copyright (c) 2015 Andrew Lutomirski + * Copyright (C) 2017 VMware, Inc. All Rights Reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/sysfs.h> +#include <linux/types.h> +#include <linux/wmi.h> + +#define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910" + +struct bmof_priv { + union acpi_object *bmofdata; + struct bin_attribute bmof_bin_attr; +}; + +static ssize_t +read_bmof(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct bmof_priv *priv = + container_of(attr, struct bmof_priv, bmof_bin_attr); + + if (off < 0) + return -EINVAL; + + if (off >= priv->bmofdata->buffer.length) + return 0; + + if (count > priv->bmofdata->buffer.length - off) + count = priv->bmofdata->buffer.length - off; + + memcpy(buf, priv->bmofdata->buffer.pointer + off, count); + return count; +} + +static int wmi_bmof_probe(struct wmi_device *wdev) +{ + struct bmof_priv *priv; + int ret; + + priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + dev_set_drvdata(&wdev->dev, priv); + + priv->bmofdata = wmidev_block_query(wdev, 0); + if (!priv->bmofdata) { + dev_err(&wdev->dev, "failed to read Binary MOF\n"); + return -EIO; + } + + if (priv->bmofdata->type != ACPI_TYPE_BUFFER) { + dev_err(&wdev->dev, "Binary MOF is not a buffer\n"); + ret = -EIO; + goto err_free; + } + + sysfs_bin_attr_init(&priv->bmof_bin_attr); + priv->bmof_bin_attr.attr.name = "bmof"; + priv->bmof_bin_attr.attr.mode = 0400; + priv->bmof_bin_attr.read = read_bmof; + priv->bmof_bin_attr.size = priv->bmofdata->buffer.length; + + ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); + if (ret) + goto err_free; + + return 0; + + err_free: + kfree(priv->bmofdata); + return ret; +} + +static int wmi_bmof_remove(struct wmi_device *wdev) +{ + struct bmof_priv *priv = dev_get_drvdata(&wdev->dev); + + sysfs_remove_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); + kfree(priv->bmofdata); + return 0; +} + +static const struct wmi_device_id wmi_bmof_id_table[] = { + { .guid_string = WMI_BMOF_GUID }, + { }, +}; + +static struct wmi_driver wmi_bmof_driver = { + .driver = { + .name = "wmi-bmof", + }, + .probe = wmi_bmof_probe, + .remove = wmi_bmof_remove, + .id_table = wmi_bmof_id_table, +}; + +module_wmi_driver(wmi_bmof_driver); + +MODULE_ALIAS("wmi:" WMI_BMOF_GUID); +MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>"); +MODULE_DESCRIPTION("WMI embedded Binary MOF driver"); +MODULE_LICENSE("GPL"); |