root/drivers/platform/chrome/cros_ec_vbc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vboot_context_read
  2. vboot_context_write
  3. cros_ec_vbc_probe
  4. cros_ec_vbc_remove

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

/* [<][>][^][v][top][bottom][index][help] */