0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "secvar-sysfs: "fmt
0009
0010 #include <linux/slab.h>
0011 #include <linux/compat.h>
0012 #include <linux/string.h>
0013 #include <linux/of.h>
0014 #include <asm/secvar.h>
0015
0016 #define NAME_MAX_SIZE 1024
0017
0018 static struct kobject *secvar_kobj;
0019 static struct kset *secvar_kset;
0020
0021 static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
0022 char *buf)
0023 {
0024 ssize_t rc = 0;
0025 struct device_node *node;
0026 const char *format;
0027
0028 node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
0029 if (!of_device_is_available(node)) {
0030 rc = -ENODEV;
0031 goto out;
0032 }
0033
0034 rc = of_property_read_string(node, "format", &format);
0035 if (rc)
0036 goto out;
0037
0038 rc = sprintf(buf, "%s\n", format);
0039
0040 out:
0041 of_node_put(node);
0042
0043 return rc;
0044 }
0045
0046
0047 static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
0048 char *buf)
0049 {
0050 uint64_t dsize;
0051 int rc;
0052
0053 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
0054 if (rc) {
0055 pr_err("Error retrieving %s variable size %d\n", kobj->name,
0056 rc);
0057 return rc;
0058 }
0059
0060 return sprintf(buf, "%llu\n", dsize);
0061 }
0062
0063 static ssize_t data_read(struct file *filep, struct kobject *kobj,
0064 struct bin_attribute *attr, char *buf, loff_t off,
0065 size_t count)
0066 {
0067 uint64_t dsize;
0068 char *data;
0069 int rc;
0070
0071 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
0072 if (rc) {
0073 pr_err("Error getting %s variable size %d\n", kobj->name, rc);
0074 return rc;
0075 }
0076 pr_debug("dsize is %llu\n", dsize);
0077
0078 data = kzalloc(dsize, GFP_KERNEL);
0079 if (!data)
0080 return -ENOMEM;
0081
0082 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, data, &dsize);
0083 if (rc) {
0084 pr_err("Error getting %s variable %d\n", kobj->name, rc);
0085 goto data_fail;
0086 }
0087
0088 rc = memory_read_from_buffer(buf, count, &off, data, dsize);
0089
0090 data_fail:
0091 kfree(data);
0092 return rc;
0093 }
0094
0095 static ssize_t update_write(struct file *filep, struct kobject *kobj,
0096 struct bin_attribute *attr, char *buf, loff_t off,
0097 size_t count)
0098 {
0099 int rc;
0100
0101 pr_debug("count is %ld\n", count);
0102 rc = secvar_ops->set(kobj->name, strlen(kobj->name) + 1, buf, count);
0103 if (rc) {
0104 pr_err("Error setting the %s variable %d\n", kobj->name, rc);
0105 return rc;
0106 }
0107
0108 return count;
0109 }
0110
0111 static struct kobj_attribute format_attr = __ATTR_RO(format);
0112
0113 static struct kobj_attribute size_attr = __ATTR_RO(size);
0114
0115 static struct bin_attribute data_attr = __BIN_ATTR_RO(data, 0);
0116
0117 static struct bin_attribute update_attr = __BIN_ATTR_WO(update, 0);
0118
0119 static struct bin_attribute *secvar_bin_attrs[] = {
0120 &data_attr,
0121 &update_attr,
0122 NULL,
0123 };
0124
0125 static struct attribute *secvar_attrs[] = {
0126 &size_attr.attr,
0127 NULL,
0128 };
0129
0130 static const struct attribute_group secvar_attr_group = {
0131 .attrs = secvar_attrs,
0132 .bin_attrs = secvar_bin_attrs,
0133 };
0134 __ATTRIBUTE_GROUPS(secvar_attr);
0135
0136 static struct kobj_type secvar_ktype = {
0137 .sysfs_ops = &kobj_sysfs_ops,
0138 .default_groups = secvar_attr_groups,
0139 };
0140
0141 static int update_kobj_size(void)
0142 {
0143
0144 struct device_node *node;
0145 u64 varsize;
0146 int rc = 0;
0147
0148 node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
0149 if (!of_device_is_available(node)) {
0150 rc = -ENODEV;
0151 goto out;
0152 }
0153
0154 rc = of_property_read_u64(node, "max-var-size", &varsize);
0155 if (rc)
0156 goto out;
0157
0158 data_attr.size = varsize;
0159 update_attr.size = varsize;
0160
0161 out:
0162 of_node_put(node);
0163
0164 return rc;
0165 }
0166
0167 static int secvar_sysfs_load(void)
0168 {
0169 char *name;
0170 uint64_t namesize = 0;
0171 struct kobject *kobj;
0172 int rc;
0173
0174 name = kzalloc(NAME_MAX_SIZE, GFP_KERNEL);
0175 if (!name)
0176 return -ENOMEM;
0177
0178 do {
0179 rc = secvar_ops->get_next(name, &namesize, NAME_MAX_SIZE);
0180 if (rc) {
0181 if (rc != -ENOENT)
0182 pr_err("error getting secvar from firmware %d\n",
0183 rc);
0184 break;
0185 }
0186
0187 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
0188 if (!kobj) {
0189 rc = -ENOMEM;
0190 break;
0191 }
0192
0193 kobject_init(kobj, &secvar_ktype);
0194
0195 rc = kobject_add(kobj, &secvar_kset->kobj, "%s", name);
0196 if (rc) {
0197 pr_warn("kobject_add error %d for attribute: %s\n", rc,
0198 name);
0199 kobject_put(kobj);
0200 kobj = NULL;
0201 }
0202
0203 if (kobj)
0204 kobject_uevent(kobj, KOBJ_ADD);
0205
0206 } while (!rc);
0207
0208 kfree(name);
0209 return rc;
0210 }
0211
0212 static int secvar_sysfs_init(void)
0213 {
0214 int rc;
0215
0216 if (!secvar_ops) {
0217 pr_warn("secvar: failed to retrieve secvar operations.\n");
0218 return -ENODEV;
0219 }
0220
0221 secvar_kobj = kobject_create_and_add("secvar", firmware_kobj);
0222 if (!secvar_kobj) {
0223 pr_err("secvar: Failed to create firmware kobj\n");
0224 return -ENOMEM;
0225 }
0226
0227 rc = sysfs_create_file(secvar_kobj, &format_attr.attr);
0228 if (rc) {
0229 kobject_put(secvar_kobj);
0230 return -ENOMEM;
0231 }
0232
0233 secvar_kset = kset_create_and_add("vars", NULL, secvar_kobj);
0234 if (!secvar_kset) {
0235 pr_err("secvar: sysfs kobject registration failed.\n");
0236 kobject_put(secvar_kobj);
0237 return -ENOMEM;
0238 }
0239
0240 rc = update_kobj_size();
0241 if (rc) {
0242 pr_err("Cannot read the size of the attribute\n");
0243 return rc;
0244 }
0245
0246 secvar_sysfs_load();
0247
0248 return 0;
0249 }
0250
0251 late_initcall(secvar_sysfs_init);