]>
Commit | Line | Data |
---|---|---|
f9dd82c0 DHV |
1 | /* |
2 | * WMI embedded Binary MOF driver | |
3 | * | |
4 | * Copyright (c) 2015 Andrew Lutomirski | |
2c9c5664 | 5 | * Copyright (C) 2017 VMware, Inc. All Rights Reserved. |
f9dd82c0 DHV |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License version 2 as published | |
9 | * by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | */ | |
16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
18 | ||
19 | #include <linux/acpi.h> | |
20 | #include <linux/device.h> | |
21 | #include <linux/fs.h> | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/module.h> | |
24 | #include <linux/string.h> | |
25 | #include <linux/sysfs.h> | |
26 | #include <linux/types.h> | |
27 | #include <linux/wmi.h> | |
28 | ||
29 | #define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910" | |
30 | ||
31 | struct bmof_priv { | |
32 | union acpi_object *bmofdata; | |
33 | struct bin_attribute bmof_bin_attr; | |
34 | }; | |
35 | ||
36 | static ssize_t | |
37 | read_bmof(struct file *filp, struct kobject *kobj, | |
38 | struct bin_attribute *attr, | |
39 | char *buf, loff_t off, size_t count) | |
40 | { | |
41 | struct bmof_priv *priv = | |
42 | container_of(attr, struct bmof_priv, bmof_bin_attr); | |
43 | ||
44 | if (off < 0) | |
45 | return -EINVAL; | |
46 | ||
47 | if (off >= priv->bmofdata->buffer.length) | |
48 | return 0; | |
49 | ||
50 | if (count > priv->bmofdata->buffer.length - off) | |
51 | count = priv->bmofdata->buffer.length - off; | |
52 | ||
53 | memcpy(buf, priv->bmofdata->buffer.pointer + off, count); | |
54 | return count; | |
55 | } | |
56 | ||
57 | static int wmi_bmof_probe(struct wmi_device *wdev) | |
58 | { | |
59 | struct bmof_priv *priv; | |
60 | int ret; | |
61 | ||
62 | priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL); | |
63 | if (!priv) | |
64 | return -ENOMEM; | |
65 | ||
66 | dev_set_drvdata(&wdev->dev, priv); | |
67 | ||
68 | priv->bmofdata = wmidev_block_query(wdev, 0); | |
69 | if (!priv->bmofdata) { | |
70 | dev_err(&wdev->dev, "failed to read Binary MOF\n"); | |
71 | return -EIO; | |
72 | } | |
73 | ||
74 | if (priv->bmofdata->type != ACPI_TYPE_BUFFER) { | |
75 | dev_err(&wdev->dev, "Binary MOF is not a buffer\n"); | |
76 | ret = -EIO; | |
77 | goto err_free; | |
78 | } | |
79 | ||
80 | sysfs_bin_attr_init(&priv->bmof_bin_attr); | |
81 | priv->bmof_bin_attr.attr.name = "bmof"; | |
82 | priv->bmof_bin_attr.attr.mode = 0400; | |
83 | priv->bmof_bin_attr.read = read_bmof; | |
84 | priv->bmof_bin_attr.size = priv->bmofdata->buffer.length; | |
85 | ||
86 | ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); | |
87 | if (ret) | |
88 | goto err_free; | |
89 | ||
90 | return 0; | |
91 | ||
92 | err_free: | |
93 | kfree(priv->bmofdata); | |
94 | return ret; | |
95 | } | |
96 | ||
97 | static int wmi_bmof_remove(struct wmi_device *wdev) | |
98 | { | |
99 | struct bmof_priv *priv = dev_get_drvdata(&wdev->dev); | |
100 | ||
101 | sysfs_remove_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr); | |
102 | kfree(priv->bmofdata); | |
103 | return 0; | |
104 | } | |
105 | ||
106 | static const struct wmi_device_id wmi_bmof_id_table[] = { | |
107 | { .guid_string = WMI_BMOF_GUID }, | |
108 | { }, | |
109 | }; | |
110 | ||
111 | static struct wmi_driver wmi_bmof_driver = { | |
112 | .driver = { | |
113 | .name = "wmi-bmof", | |
114 | }, | |
115 | .probe = wmi_bmof_probe, | |
116 | .remove = wmi_bmof_remove, | |
117 | .id_table = wmi_bmof_id_table, | |
118 | }; | |
119 | ||
120 | module_wmi_driver(wmi_bmof_driver); | |
121 | ||
122 | MODULE_ALIAS("wmi:" WMI_BMOF_GUID); | |
123 | MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>"); | |
124 | MODULE_DESCRIPTION("WMI embedded Binary MOF driver"); | |
125 | MODULE_LICENSE("GPL"); |