summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/dell-smbios-wmi.c
diff options
context:
space:
mode:
authorMario Limonciello <mario.limonciello@dell.com>2017-11-01 14:25:36 -0500
committerDarren Hart (VMware) <dvhart@infradead.org>2017-11-03 16:34:00 -0700
commitf2645fa317b8905b8934f06a0601d5b7fa66aba0 (patch)
tree67e5c5b646383869298a60dd0c6b1e44c345399e /drivers/platform/x86/dell-smbios-wmi.c
parent44b6b7661132b1b0e5fd3147ded66f1e4a817ca9 (diff)
platform/x86: dell-smbios-wmi: introduce userspace interface
It's important for the driver to provide a R/W ioctl to ensure that two competing userspace processes don't race to provide or read each others data. This userspace character device will be used to perform SMBIOS calls from any applications. It provides an ioctl that will allow passing the WMI calling interface buffer between userspace and kernel space. This character device is intended to deprecate the dcdbas kernel module and the interface that it provides to userspace. To perform an SMBIOS IOCTL call using the character device userspace will perform a read() on the the character device. The WMI bus will provide a u64 variable containing the necessary size of the IOCTL buffer. The API for interacting with this interface is defined in documentation as well as the WMI uapi header provides the format of the structures. Not all userspace requests will be accepted. The dell-smbios filtering functionality will be used to prevent access to certain tokens and calls. All whitelisted commands and tokens are now shared out to userspace so applications don't need to define them in their own headers. Signed-off-by: Mario Limonciello <mario.limonciello@dell.com> Reviewed-by: Edward O'Callaghan <quasisec@google.com> Signed-off-by: Darren Hart (VMware) <dvhart@infradead.org>
Diffstat (limited to 'drivers/platform/x86/dell-smbios-wmi.c')
-rw-r--r--drivers/platform/x86/dell-smbios-wmi.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c
index b31f457e58c3..35c13815b24c 100644
--- a/drivers/platform/x86/dell-smbios-wmi.c
+++ b/drivers/platform/x86/dell-smbios-wmi.c
@@ -30,17 +30,6 @@ struct misc_bios_flags_structure {
#define DELL_WMI_SMBIOS_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
-struct dell_wmi_extensions {
- __u32 argattrib;
- __u32 blength;
- __u8 data[];
-} __packed;
-
-struct dell_wmi_smbios_buffer {
- struct calling_interface_buffer std;
- struct dell_wmi_extensions ext;
-} __packed;
-
struct wmi_smbios_priv {
struct dell_wmi_smbios_buffer *buf;
struct list_head list;
@@ -117,6 +106,42 @@ int dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
return ret;
}
+static long dell_smbios_wmi_filter(struct wmi_device *wdev, unsigned int cmd,
+ struct wmi_ioctl_buffer *arg)
+{
+ struct wmi_smbios_priv *priv;
+ int ret = 0;
+
+ switch (cmd) {
+ case DELL_WMI_SMBIOS_CMD:
+ mutex_lock(&call_mutex);
+ priv = dev_get_drvdata(&wdev->dev);
+ if (!priv) {
+ ret = -ENODEV;
+ goto fail_smbios_cmd;
+ }
+ memcpy(priv->buf, arg, priv->req_buf_size);
+ if (dell_smbios_call_filter(&wdev->dev, &priv->buf->std)) {
+ dev_err(&wdev->dev, "Invalid call %d/%d:%8x\n",
+ priv->buf->std.cmd_class,
+ priv->buf->std.cmd_select,
+ priv->buf->std.input[0]);
+ ret = -EFAULT;
+ goto fail_smbios_cmd;
+ }
+ ret = run_smbios_call(priv->wdev);
+ if (ret)
+ goto fail_smbios_cmd;
+ memcpy(arg, priv->buf, priv->req_buf_size);
+fail_smbios_cmd:
+ mutex_unlock(&call_mutex);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+ return ret;
+}
+
static int dell_smbios_wmi_probe(struct wmi_device *wdev)
{
struct wmi_smbios_priv *priv;
@@ -135,6 +160,12 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev)
if (!dell_wmi_get_size(&priv->req_buf_size))
return -EPROBE_DEFER;
+ /* add in the length object we will use internally with ioctl */
+ priv->req_buf_size += sizeof(u64);
+ ret = set_required_buffer_size(wdev, priv->req_buf_size);
+ if (ret)
+ return ret;
+
count = get_order(priv->req_buf_size);
priv->buf = (void *)__get_free_pages(GFP_KERNEL, count);
if (!priv->buf)
@@ -210,6 +241,7 @@ static struct wmi_driver dell_smbios_wmi_driver = {
.probe = dell_smbios_wmi_probe,
.remove = dell_smbios_wmi_remove,
.id_table = dell_smbios_wmi_id_table,
+ .filter_callback = dell_smbios_wmi_filter,
};
static int __init init_dell_smbios_wmi(void)