cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wmi-bmof.c (2693B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * WMI embedded Binary MOF driver
      4 *
      5 * Copyright (c) 2015 Andrew Lutomirski
      6 * Copyright (C) 2017 VMware, Inc. All Rights Reserved.
      7 */
      8
      9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     10
     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
     29read_bmof(struct file *filp, struct kobject *kobj,
     30	 struct bin_attribute *attr,
     31	 char *buf, loff_t off, size_t count)
     32{
     33	struct bmof_priv *priv =
     34		container_of(attr, struct bmof_priv, bmof_bin_attr);
     35
     36	if (off < 0)
     37		return -EINVAL;
     38
     39	if (off >= priv->bmofdata->buffer.length)
     40		return 0;
     41
     42	if (count > priv->bmofdata->buffer.length - off)
     43		count = priv->bmofdata->buffer.length - off;
     44
     45	memcpy(buf, priv->bmofdata->buffer.pointer + off, count);
     46	return count;
     47}
     48
     49static int wmi_bmof_probe(struct wmi_device *wdev, const void *context)
     50{
     51	struct bmof_priv *priv;
     52	int ret;
     53
     54	priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL);
     55	if (!priv)
     56		return -ENOMEM;
     57
     58	dev_set_drvdata(&wdev->dev, priv);
     59
     60	priv->bmofdata = wmidev_block_query(wdev, 0);
     61	if (!priv->bmofdata) {
     62		dev_err(&wdev->dev, "failed to read Binary MOF\n");
     63		return -EIO;
     64	}
     65
     66	if (priv->bmofdata->type != ACPI_TYPE_BUFFER) {
     67		dev_err(&wdev->dev, "Binary MOF is not a buffer\n");
     68		ret = -EIO;
     69		goto err_free;
     70	}
     71
     72	sysfs_bin_attr_init(&priv->bmof_bin_attr);
     73	priv->bmof_bin_attr.attr.name = "bmof";
     74	priv->bmof_bin_attr.attr.mode = 0400;
     75	priv->bmof_bin_attr.read = read_bmof;
     76	priv->bmof_bin_attr.size = priv->bmofdata->buffer.length;
     77
     78	ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr);
     79	if (ret)
     80		goto err_free;
     81
     82	return 0;
     83
     84 err_free:
     85	kfree(priv->bmofdata);
     86	return ret;
     87}
     88
     89static void wmi_bmof_remove(struct wmi_device *wdev)
     90{
     91	struct bmof_priv *priv = dev_get_drvdata(&wdev->dev);
     92
     93	sysfs_remove_bin_file(&wdev->dev.kobj, &priv->bmof_bin_attr);
     94	kfree(priv->bmofdata);
     95}
     96
     97static const struct wmi_device_id wmi_bmof_id_table[] = {
     98	{ .guid_string = WMI_BMOF_GUID },
     99	{ },
    100};
    101
    102static struct wmi_driver wmi_bmof_driver = {
    103	.driver = {
    104		.name = "wmi-bmof",
    105	},
    106	.probe = wmi_bmof_probe,
    107	.remove = wmi_bmof_remove,
    108	.id_table = wmi_bmof_id_table,
    109};
    110
    111module_wmi_driver(wmi_bmof_driver);
    112
    113MODULE_DEVICE_TABLE(wmi, wmi_bmof_id_table);
    114MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>");
    115MODULE_DESCRIPTION("WMI embedded Binary MOF driver");
    116MODULE_LICENSE("GPL");