brintos

brintos / linux-shallow public Read only

0
0
Text · 2.5 KiB · df6f0ae Raw
106 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * WMI embedded Binary MOF driver4 *5 * Copyright (c) 2015 Andrew Lutomirski6 * Copyright (C) 2017 VMware, Inc. All Rights Reserved.7 */8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt10 11#include <linux/acpi.h>12#include <linux/device.h>13#include <linux/fs.h>14#include <linux/kernel.h>15#include <linux/module.h>16#include <linux/string.h>17#include <linux/sysfs.h>18#include <linux/types.h>19#include <linux/wmi.h>20 21#define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910"22 23struct bmof_priv {24	union acpi_object *bmofdata;25	struct bin_attribute bmof_bin_attr;26};27 28static ssize_t read_bmof(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,29			 char *buf, loff_t off, size_t count)30{31	struct bmof_priv *priv = container_of(attr, struct bmof_priv, bmof_bin_attr);32 33	return memory_read_from_buffer(buf, count, &off, priv->bmofdata->buffer.pointer,34				       priv->bmofdata->buffer.length);35}36 37static int wmi_bmof_probe(struct wmi_device *wdev, const void *context)38{39	struct bmof_priv *priv;40	int ret;41 42	priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL);43	if (!priv)44		return -ENOMEM;45 46	dev_set_drvdata(&wdev->dev, priv);47 48	priv->bmofdata = wmidev_block_query(wdev, 0);49	if (!priv->bmofdata) {50		dev_err(&wdev->dev, "failed to read Binary MOF\n");51		return -EIO;52	}53 54	if (priv->bmofdata->type != ACPI_TYPE_BUFFER) {55		dev_err(&wdev->dev, "Binary MOF is not a buffer\n");56		ret = -EIO;57		goto err_free;58	}59 60	sysfs_bin_attr_init(&priv->bmof_bin_attr);61	priv->bmof_bin_attr.attr.name = "bmof";62	priv->bmof_bin_attr.attr.mode = 0400;63	priv->bmof_bin_attr.read = read_bmof;64	priv->bmof_bin_attr.size = priv->bmofdata->buffer.length;65 66	ret = device_create_bin_file(&wdev->dev, &priv->bmof_bin_attr);67	if (ret)68		goto err_free;69 70	return 0;71 72 err_free:73	kfree(priv->bmofdata);74	return ret;75}76 77static void wmi_bmof_remove(struct wmi_device *wdev)78{79	struct bmof_priv *priv = dev_get_drvdata(&wdev->dev);80 81	device_remove_bin_file(&wdev->dev, &priv->bmof_bin_attr);82	kfree(priv->bmofdata);83}84 85static const struct wmi_device_id wmi_bmof_id_table[] = {86	{ .guid_string = WMI_BMOF_GUID },87	{ },88};89 90static struct wmi_driver wmi_bmof_driver = {91	.driver = {92		.name = "wmi-bmof",93	},94	.probe = wmi_bmof_probe,95	.remove = wmi_bmof_remove,96	.id_table = wmi_bmof_id_table,97	.no_singleton = true,98};99 100module_wmi_driver(wmi_bmof_driver);101 102MODULE_DEVICE_TABLE(wmi, wmi_bmof_id_table);103MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>");104MODULE_DESCRIPTION("WMI embedded Binary MOF driver");105MODULE_LICENSE("GPL");106