1 // SPDX-License-Identifier: GPL-2.0+
2 // Expose the vboot context nvram to userspace
4 // Copyright (C) 2012 Google, Inc.
5 // Copyright (C) 2015 Collabora Ltd.
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>
14 #define DRV_NAME "cros-ec-vbc"
16 static 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
)
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
;
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
);
30 msg
= kmalloc(sizeof(*msg
) + payload
, GFP_KERNEL
);
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
;
38 msg
->version
= EC_VER_VBNV_CONTEXT
;
39 msg
->command
= EC_CMD_VBNV_CONTEXT
;
40 msg
->outsize
= para_sz
;
41 msg
->insize
= resp_sz
;
43 err
= cros_ec_cmd_xfer_status(ecdev
, msg
);
45 dev_err(dev
, "Error sending read request: %d\n", err
);
50 memcpy(buf
, msg
->data
, resp_sz
);
56 static 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
)
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
;
66 const size_t para_sz
= sizeof(*params
);
67 const size_t data_sz
= sizeof(params
->block
);
69 /* Only write full values */
73 msg
= kmalloc(sizeof(*msg
) + para_sz
, GFP_KERNEL
);
77 params
= (struct ec_params_vbnvcontext
*)msg
->data
;
78 params
->op
= EC_VBNV_CONTEXT_OP_WRITE
;
79 memcpy(params
->block
, buf
, data_sz
);
81 msg
->version
= EC_VER_VBNV_CONTEXT
;
82 msg
->command
= EC_CMD_VBNV_CONTEXT
;
83 msg
->outsize
= para_sz
;
86 err
= cros_ec_cmd_xfer_status(ecdev
, msg
);
88 dev_err(dev
, "Error sending write request: %d\n", err
);
97 static BIN_ATTR_RW(vboot_context
, 16);
99 static struct bin_attribute
*cros_ec_vbc_bin_attrs
[] = {
100 &bin_attr_vboot_context
,
104 static struct attribute_group cros_ec_vbc_attr_group
= {
106 .bin_attrs
= cros_ec_vbc_bin_attrs
,
109 static int cros_ec_vbc_probe(struct platform_device
*pd
)
111 struct cros_ec_dev
*ec_dev
= dev_get_drvdata(pd
->dev
.parent
);
112 struct device
*dev
= &pd
->dev
;
115 ret
= sysfs_create_group(&ec_dev
->class_dev
.kobj
,
116 &cros_ec_vbc_attr_group
);
118 dev_err(dev
, "failed to create %s attributes. err=%d\n",
119 cros_ec_vbc_attr_group
.name
, ret
);
124 static int cros_ec_vbc_remove(struct platform_device
*pd
)
126 struct cros_ec_dev
*ec_dev
= dev_get_drvdata(pd
->dev
.parent
);
128 sysfs_remove_group(&ec_dev
->class_dev
.kobj
,
129 &cros_ec_vbc_attr_group
);
134 static struct platform_driver cros_ec_vbc_driver
= {
138 .probe
= cros_ec_vbc_probe
,
139 .remove
= cros_ec_vbc_remove
,
142 module_platform_driver(cros_ec_vbc_driver
);
144 MODULE_LICENSE("GPL");
145 MODULE_DESCRIPTION("Expose the vboot context nvram to userspace");
146 MODULE_ALIAS("platform:" DRV_NAME
);