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

cros_ec_vbc.c (3709B)


      1// SPDX-License-Identifier: GPL-2.0+
      2// Expose the vboot context nvram to userspace
      3//
      4// Copyright (C) 2012 Google, Inc.
      5// Copyright (C) 2015 Collabora Ltd.
      6
      7#include <linux/of.h>
      8#include <linux/platform_device.h>
      9#include <linux/module.h>
     10#include <linux/platform_data/cros_ec_commands.h>
     11#include <linux/platform_data/cros_ec_proto.h>
     12#include <linux/slab.h>
     13
     14#define DRV_NAME "cros-ec-vbc"
     15
     16static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
     17				  struct bin_attribute *att, char *buf,
     18				  loff_t pos, size_t count)
     19{
     20	struct device *dev = kobj_to_dev(kobj);
     21	struct cros_ec_dev *ec = to_cros_ec_dev(dev);
     22	struct cros_ec_device *ecdev = ec->ec_dev;
     23	struct ec_params_vbnvcontext *params;
     24	struct cros_ec_command *msg;
     25	int err;
     26	const size_t para_sz = sizeof(params->op);
     27	const size_t resp_sz = sizeof(struct ec_response_vbnvcontext);
     28	const size_t payload = max(para_sz, resp_sz);
     29
     30	msg = kmalloc(sizeof(*msg) + payload, GFP_KERNEL);
     31	if (!msg)
     32		return -ENOMEM;
     33
     34	/* NB: we only kmalloc()ated enough space for the op field */
     35	params = (struct ec_params_vbnvcontext *)msg->data;
     36	params->op = EC_VBNV_CONTEXT_OP_READ;
     37
     38	msg->version = EC_VER_VBNV_CONTEXT;
     39	msg->command = EC_CMD_VBNV_CONTEXT;
     40	msg->outsize = para_sz;
     41	msg->insize = resp_sz;
     42
     43	err = cros_ec_cmd_xfer_status(ecdev, msg);
     44	if (err < 0) {
     45		dev_err(dev, "Error sending read request: %d\n", err);
     46		kfree(msg);
     47		return err;
     48	}
     49
     50	memcpy(buf, msg->data, resp_sz);
     51
     52	kfree(msg);
     53	return resp_sz;
     54}
     55
     56static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
     57				   struct bin_attribute *attr, char *buf,
     58				   loff_t pos, size_t count)
     59{
     60	struct device *dev = kobj_to_dev(kobj);
     61	struct cros_ec_dev *ec = to_cros_ec_dev(dev);
     62	struct cros_ec_device *ecdev = ec->ec_dev;
     63	struct ec_params_vbnvcontext *params;
     64	struct cros_ec_command *msg;
     65	int err;
     66	const size_t para_sz = sizeof(*params);
     67	const size_t data_sz = sizeof(params->block);
     68
     69	/* Only write full values */
     70	if (count != data_sz)
     71		return -EINVAL;
     72
     73	msg = kmalloc(sizeof(*msg) + para_sz, GFP_KERNEL);
     74	if (!msg)
     75		return -ENOMEM;
     76
     77	params = (struct ec_params_vbnvcontext *)msg->data;
     78	params->op = EC_VBNV_CONTEXT_OP_WRITE;
     79	memcpy(params->block, buf, data_sz);
     80
     81	msg->version = EC_VER_VBNV_CONTEXT;
     82	msg->command = EC_CMD_VBNV_CONTEXT;
     83	msg->outsize = para_sz;
     84	msg->insize = 0;
     85
     86	err = cros_ec_cmd_xfer_status(ecdev, msg);
     87	if (err < 0) {
     88		dev_err(dev, "Error sending write request: %d\n", err);
     89		kfree(msg);
     90		return err;
     91	}
     92
     93	kfree(msg);
     94	return data_sz;
     95}
     96
     97static BIN_ATTR_RW(vboot_context, 16);
     98
     99static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
    100	&bin_attr_vboot_context,
    101	NULL
    102};
    103
    104static const struct attribute_group cros_ec_vbc_attr_group = {
    105	.name = "vbc",
    106	.bin_attrs = cros_ec_vbc_bin_attrs,
    107};
    108
    109static int cros_ec_vbc_probe(struct platform_device *pd)
    110{
    111	struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
    112	struct device *dev = &pd->dev;
    113	int ret;
    114
    115	ret = sysfs_create_group(&ec_dev->class_dev.kobj,
    116				 &cros_ec_vbc_attr_group);
    117	if (ret < 0)
    118		dev_err(dev, "failed to create %s attributes. err=%d\n",
    119			cros_ec_vbc_attr_group.name, ret);
    120
    121	return ret;
    122}
    123
    124static int cros_ec_vbc_remove(struct platform_device *pd)
    125{
    126	struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
    127
    128	sysfs_remove_group(&ec_dev->class_dev.kobj,
    129			   &cros_ec_vbc_attr_group);
    130
    131	return 0;
    132}
    133
    134static struct platform_driver cros_ec_vbc_driver = {
    135	.driver = {
    136		.name = DRV_NAME,
    137	},
    138	.probe = cros_ec_vbc_probe,
    139	.remove = cros_ec_vbc_remove,
    140};
    141
    142module_platform_driver(cros_ec_vbc_driver);
    143
    144MODULE_LICENSE("GPL");
    145MODULE_DESCRIPTION("Expose the vboot context nvram to userspace");
    146MODULE_ALIAS("platform:" DRV_NAME);