1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 IBM Corporation <nayna@linux.ibm.com>
5 * This code exposes secure variables to user via sysfs
8 #define pr_fmt(fmt) "secvar-sysfs: "fmt
10 #include <linux/slab.h>
11 #include <linux/compat.h>
12 #include <linux/string.h>
14 #include <asm/secvar.h>
16 #define NAME_MAX_SIZE 1024
18 static struct kobject
*secvar_kobj
;
19 static struct kset
*secvar_kset
;
21 static ssize_t
format_show(struct kobject
*kobj
, struct kobj_attribute
*attr
,
25 struct device_node
*node
;
28 node
= of_find_compatible_node(NULL
, NULL
, "ibm,secvar-backend");
29 if (!of_device_is_available(node
))
32 rc
= of_property_read_string(node
, "format", &format
);
36 rc
= sprintf(buf
, "%s\n", format
);
44 static ssize_t
size_show(struct kobject
*kobj
, struct kobj_attribute
*attr
,
50 rc
= secvar_ops
->get(kobj
->name
, strlen(kobj
->name
) + 1, NULL
, &dsize
);
52 pr_err("Error retrieving %s variable size %d\n", kobj
->name
,
57 return sprintf(buf
, "%llu\n", dsize
);
60 static ssize_t
data_read(struct file
*filep
, struct kobject
*kobj
,
61 struct bin_attribute
*attr
, char *buf
, loff_t off
,
68 rc
= secvar_ops
->get(kobj
->name
, strlen(kobj
->name
) + 1, NULL
, &dsize
);
70 pr_err("Error getting %s variable size %d\n", kobj
->name
, rc
);
73 pr_debug("dsize is %llu\n", dsize
);
75 data
= kzalloc(dsize
, GFP_KERNEL
);
79 rc
= secvar_ops
->get(kobj
->name
, strlen(kobj
->name
) + 1, data
, &dsize
);
81 pr_err("Error getting %s variable %d\n", kobj
->name
, rc
);
85 rc
= memory_read_from_buffer(buf
, count
, &off
, data
, dsize
);
92 static ssize_t
update_write(struct file
*filep
, struct kobject
*kobj
,
93 struct bin_attribute
*attr
, char *buf
, loff_t off
,
98 pr_debug("count is %ld\n", count
);
99 rc
= secvar_ops
->set(kobj
->name
, strlen(kobj
->name
) + 1, buf
, count
);
101 pr_err("Error setting the %s variable %d\n", kobj
->name
, rc
);
108 static struct kobj_attribute format_attr
= __ATTR_RO(format
);
110 static struct kobj_attribute size_attr
= __ATTR_RO(size
);
112 static struct bin_attribute data_attr
= __BIN_ATTR_RO(data
, 0);
114 static struct bin_attribute update_attr
= __BIN_ATTR_WO(update
, 0);
116 static struct bin_attribute
*secvar_bin_attrs
[] = {
122 static struct attribute
*secvar_attrs
[] = {
127 static const struct attribute_group secvar_attr_group
= {
128 .attrs
= secvar_attrs
,
129 .bin_attrs
= secvar_bin_attrs
,
131 __ATTRIBUTE_GROUPS(secvar_attr
);
133 static struct kobj_type secvar_ktype
= {
134 .sysfs_ops
= &kobj_sysfs_ops
,
135 .default_groups
= secvar_attr_groups
,
138 static int update_kobj_size(void)
141 struct device_node
*node
;
145 node
= of_find_compatible_node(NULL
, NULL
, "ibm,secvar-backend");
146 if (!of_device_is_available(node
)) {
151 rc
= of_property_read_u64(node
, "max-var-size", &varsize
);
155 data_attr
.size
= varsize
;
156 update_attr
.size
= varsize
;
164 static int secvar_sysfs_load(void)
167 uint64_t namesize
= 0;
168 struct kobject
*kobj
;
171 name
= kzalloc(NAME_MAX_SIZE
, GFP_KERNEL
);
176 rc
= secvar_ops
->get_next(name
, &namesize
, NAME_MAX_SIZE
);
179 pr_err("error getting secvar from firmware %d\n",
184 kobj
= kzalloc(sizeof(*kobj
), GFP_KERNEL
);
190 kobject_init(kobj
, &secvar_ktype
);
192 rc
= kobject_add(kobj
, &secvar_kset
->kobj
, "%s", name
);
194 pr_warn("kobject_add error %d for attribute: %s\n", rc
,
201 kobject_uevent(kobj
, KOBJ_ADD
);
209 static int secvar_sysfs_init(void)
214 pr_warn("secvar: failed to retrieve secvar operations.\n");
218 secvar_kobj
= kobject_create_and_add("secvar", firmware_kobj
);
220 pr_err("secvar: Failed to create firmware kobj\n");
224 rc
= sysfs_create_file(secvar_kobj
, &format_attr
.attr
);
226 kobject_put(secvar_kobj
);
230 secvar_kset
= kset_create_and_add("vars", NULL
, secvar_kobj
);
232 pr_err("secvar: sysfs kobject registration failed.\n");
233 kobject_put(secvar_kobj
);
237 rc
= update_kobj_size();
239 pr_err("Cannot read the size of the attribute\n");
248 late_initcall(secvar_sysfs_init
);