Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / firmware / efi / efivars.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Originally from efivars.c,
4  *
5  * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
6  * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
7  *
8  * This code takes all variables accessible from EFI runtime and
9  *  exports them via sysfs
10  */
11
12 #include <linux/efi.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/ucs2_string.h>
16 #include <linux/compat.h>
17
18 #define EFIVARS_VERSION "0.08"
19 #define EFIVARS_DATE "2004-May-17"
20
21 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
22 MODULE_DESCRIPTION("sysfs interface to EFI Variables");
23 MODULE_LICENSE("GPL");
24 MODULE_VERSION(EFIVARS_VERSION);
25 MODULE_ALIAS("platform:efivars");
26
27 LIST_HEAD(efivar_sysfs_list);
28 EXPORT_SYMBOL_GPL(efivar_sysfs_list);
29
30 static struct kset *efivars_kset;
31
32 static struct bin_attribute *efivars_new_var;
33 static struct bin_attribute *efivars_del_var;
34
35 struct compat_efi_variable {
36         efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
37         efi_guid_t    VendorGuid;
38         __u32         DataSize;
39         __u8          Data[1024];
40         __u32         Status;
41         __u32         Attributes;
42 } __packed;
43
44 struct efivar_attribute {
45         struct attribute attr;
46         ssize_t (*show) (struct efivar_entry *entry, char *buf);
47         ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
48 };
49
50 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
51 struct efivar_attribute efivar_attr_##_name = { \
52         .attr = {.name = __stringify(_name), .mode = _mode}, \
53         .show = _show, \
54         .store = _store, \
55 };
56
57 #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
58 #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
59
60 /*
61  * Prototype for sysfs creation function
62  */
63 static int
64 efivar_create_sysfs_entry(struct efivar_entry *new_var);
65
66 static ssize_t
67 efivar_guid_read(struct efivar_entry *entry, char *buf)
68 {
69         struct efi_variable *var = &entry->var;
70         char *str = buf;
71
72         if (!entry || !buf)
73                 return 0;
74
75         efi_guid_to_str(&var->VendorGuid, str);
76         str += strlen(str);
77         str += sprintf(str, "\n");
78
79         return str - buf;
80 }
81
82 static ssize_t
83 efivar_attr_read(struct efivar_entry *entry, char *buf)
84 {
85         struct efi_variable *var = &entry->var;
86         unsigned long size = sizeof(var->Data);
87         char *str = buf;
88         int ret;
89
90         if (!entry || !buf)
91                 return -EINVAL;
92
93         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
94         var->DataSize = size;
95         if (ret)
96                 return -EIO;
97
98         if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
99                 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
100         if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
101                 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
102         if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
103                 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
104         if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
105                 str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
106         if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
107                 str += sprintf(str,
108                         "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
109         if (var->Attributes &
110                         EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
111                 str += sprintf(str,
112                         "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
113         if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
114                 str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
115         return str - buf;
116 }
117
118 static ssize_t
119 efivar_size_read(struct efivar_entry *entry, char *buf)
120 {
121         struct efi_variable *var = &entry->var;
122         unsigned long size = sizeof(var->Data);
123         char *str = buf;
124         int ret;
125
126         if (!entry || !buf)
127                 return -EINVAL;
128
129         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
130         var->DataSize = size;
131         if (ret)
132                 return -EIO;
133
134         str += sprintf(str, "0x%lx\n", var->DataSize);
135         return str - buf;
136 }
137
138 static ssize_t
139 efivar_data_read(struct efivar_entry *entry, char *buf)
140 {
141         struct efi_variable *var = &entry->var;
142         unsigned long size = sizeof(var->Data);
143         int ret;
144
145         if (!entry || !buf)
146                 return -EINVAL;
147
148         ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
149         var->DataSize = size;
150         if (ret)
151                 return -EIO;
152
153         memcpy(buf, var->Data, var->DataSize);
154         return var->DataSize;
155 }
156
157 static inline int
158 sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
159              unsigned long size, u32 attributes, u8 *data)
160 {
161         /*
162          * If only updating the variable data, then the name
163          * and guid should remain the same
164          */
165         if (memcmp(name, var->VariableName, sizeof(var->VariableName)) ||
166                 efi_guidcmp(vendor, var->VendorGuid)) {
167                 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
168                 return -EINVAL;
169         }
170
171         if ((size <= 0) || (attributes == 0)){
172                 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
173                 return -EINVAL;
174         }
175
176         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
177             efivar_validate(vendor, name, data, size) == false) {
178                 printk(KERN_ERR "efivars: Malformed variable content\n");
179                 return -EINVAL;
180         }
181
182         return 0;
183 }
184
185 static void
186 copy_out_compat(struct efi_variable *dst, struct compat_efi_variable *src)
187 {
188         memcpy(dst->VariableName, src->VariableName, EFI_VAR_NAME_LEN);
189         memcpy(dst->Data, src->Data, sizeof(src->Data));
190
191         dst->VendorGuid = src->VendorGuid;
192         dst->DataSize = src->DataSize;
193         dst->Attributes = src->Attributes;
194 }
195
196 /*
197  * We allow each variable to be edited via rewriting the
198  * entire efi variable structure.
199  */
200 static ssize_t
201 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
202 {
203         struct efi_variable *new_var, *var = &entry->var;
204         efi_char16_t *name;
205         unsigned long size;
206         efi_guid_t vendor;
207         u32 attributes;
208         u8 *data;
209         int err;
210
211         if (!entry || !buf)
212                 return -EINVAL;
213
214         if (in_compat_syscall()) {
215                 struct compat_efi_variable *compat;
216
217                 if (count != sizeof(*compat))
218                         return -EINVAL;
219
220                 compat = (struct compat_efi_variable *)buf;
221                 attributes = compat->Attributes;
222                 vendor = compat->VendorGuid;
223                 name = compat->VariableName;
224                 size = compat->DataSize;
225                 data = compat->Data;
226
227                 err = sanity_check(var, name, vendor, size, attributes, data);
228                 if (err)
229                         return err;
230
231                 copy_out_compat(&entry->var, compat);
232         } else {
233                 if (count != sizeof(struct efi_variable))
234                         return -EINVAL;
235
236                 new_var = (struct efi_variable *)buf;
237
238                 attributes = new_var->Attributes;
239                 vendor = new_var->VendorGuid;
240                 name = new_var->VariableName;
241                 size = new_var->DataSize;
242                 data = new_var->Data;
243
244                 err = sanity_check(var, name, vendor, size, attributes, data);
245                 if (err)
246                         return err;
247
248                 memcpy(&entry->var, new_var, count);
249         }
250
251         err = efivar_entry_set(entry, attributes, size, data, NULL);
252         if (err) {
253                 printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
254                 return -EIO;
255         }
256
257         return count;
258 }
259
260 static ssize_t
261 efivar_show_raw(struct efivar_entry *entry, char *buf)
262 {
263         struct efi_variable *var = &entry->var;
264         struct compat_efi_variable *compat;
265         unsigned long datasize = sizeof(var->Data);
266         size_t size;
267         int ret;
268
269         if (!entry || !buf)
270                 return 0;
271
272         ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
273         var->DataSize = datasize;
274         if (ret)
275                 return -EIO;
276
277         if (in_compat_syscall()) {
278                 compat = (struct compat_efi_variable *)buf;
279
280                 size = sizeof(*compat);
281                 memcpy(compat->VariableName, var->VariableName,
282                         EFI_VAR_NAME_LEN);
283                 memcpy(compat->Data, var->Data, sizeof(compat->Data));
284
285                 compat->VendorGuid = var->VendorGuid;
286                 compat->DataSize = var->DataSize;
287                 compat->Attributes = var->Attributes;
288         } else {
289                 size = sizeof(*var);
290                 memcpy(buf, var, size);
291         }
292
293         return size;
294 }
295
296 /*
297  * Generic read/write functions that call the specific functions of
298  * the attributes...
299  */
300 static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
301                                 char *buf)
302 {
303         struct efivar_entry *var = to_efivar_entry(kobj);
304         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
305         ssize_t ret = -EIO;
306
307         if (!capable(CAP_SYS_ADMIN))
308                 return -EACCES;
309
310         if (efivar_attr->show) {
311                 ret = efivar_attr->show(var, buf);
312         }
313         return ret;
314 }
315
316 static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
317                                 const char *buf, size_t count)
318 {
319         struct efivar_entry *var = to_efivar_entry(kobj);
320         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
321         ssize_t ret = -EIO;
322
323         if (!capable(CAP_SYS_ADMIN))
324                 return -EACCES;
325
326         if (efivar_attr->store)
327                 ret = efivar_attr->store(var, buf, count);
328
329         return ret;
330 }
331
332 static const struct sysfs_ops efivar_attr_ops = {
333         .show = efivar_attr_show,
334         .store = efivar_attr_store,
335 };
336
337 static void efivar_release(struct kobject *kobj)
338 {
339         struct efivar_entry *var = to_efivar_entry(kobj);
340         kfree(var);
341 }
342
343 static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
344 static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
345 static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
346 static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
347 static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
348
349 static struct attribute *def_attrs[] = {
350         &efivar_attr_guid.attr,
351         &efivar_attr_size.attr,
352         &efivar_attr_attributes.attr,
353         &efivar_attr_data.attr,
354         &efivar_attr_raw_var.attr,
355         NULL,
356 };
357
358 static struct kobj_type efivar_ktype = {
359         .release = efivar_release,
360         .sysfs_ops = &efivar_attr_ops,
361         .default_attrs = def_attrs,
362 };
363
364 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
365                              struct bin_attribute *bin_attr,
366                              char *buf, loff_t pos, size_t count)
367 {
368         struct compat_efi_variable *compat = (struct compat_efi_variable *)buf;
369         struct efi_variable *new_var = (struct efi_variable *)buf;
370         struct efivar_entry *new_entry;
371         bool need_compat = in_compat_syscall();
372         efi_char16_t *name;
373         unsigned long size;
374         u32 attributes;
375         u8 *data;
376         int err;
377
378         if (!capable(CAP_SYS_ADMIN))
379                 return -EACCES;
380
381         if (need_compat) {
382                 if (count != sizeof(*compat))
383                         return -EINVAL;
384
385                 attributes = compat->Attributes;
386                 name = compat->VariableName;
387                 size = compat->DataSize;
388                 data = compat->Data;
389         } else {
390                 if (count != sizeof(*new_var))
391                         return -EINVAL;
392
393                 attributes = new_var->Attributes;
394                 name = new_var->VariableName;
395                 size = new_var->DataSize;
396                 data = new_var->Data;
397         }
398
399         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
400             efivar_validate(new_var->VendorGuid, name, data,
401                             size) == false) {
402                 printk(KERN_ERR "efivars: Malformed variable content\n");
403                 return -EINVAL;
404         }
405
406         new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
407         if (!new_entry)
408                 return -ENOMEM;
409
410         if (need_compat)
411                 copy_out_compat(&new_entry->var, compat);
412         else
413                 memcpy(&new_entry->var, new_var, sizeof(*new_var));
414
415         err = efivar_entry_set(new_entry, attributes, size,
416                                data, &efivar_sysfs_list);
417         if (err) {
418                 if (err == -EEXIST)
419                         err = -EINVAL;
420                 goto out;
421         }
422
423         if (efivar_create_sysfs_entry(new_entry)) {
424                 printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
425                 kfree(new_entry);
426         }
427         return count;
428
429 out:
430         kfree(new_entry);
431         return err;
432 }
433
434 static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
435                              struct bin_attribute *bin_attr,
436                              char *buf, loff_t pos, size_t count)
437 {
438         struct efi_variable *del_var = (struct efi_variable *)buf;
439         struct compat_efi_variable *compat;
440         struct efivar_entry *entry;
441         efi_char16_t *name;
442         efi_guid_t vendor;
443         int err = 0;
444
445         if (!capable(CAP_SYS_ADMIN))
446                 return -EACCES;
447
448         if (in_compat_syscall()) {
449                 if (count != sizeof(*compat))
450                         return -EINVAL;
451
452                 compat = (struct compat_efi_variable *)buf;
453                 name = compat->VariableName;
454                 vendor = compat->VendorGuid;
455         } else {
456                 if (count != sizeof(*del_var))
457                         return -EINVAL;
458
459                 name = del_var->VariableName;
460                 vendor = del_var->VendorGuid;
461         }
462
463         if (efivar_entry_iter_begin())
464                 return -EINTR;
465         entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true);
466         if (!entry)
467                 err = -EINVAL;
468         else if (__efivar_entry_delete(entry))
469                 err = -EIO;
470
471         if (err) {
472                 efivar_entry_iter_end();
473                 return err;
474         }
475
476         if (!entry->scanning) {
477                 efivar_entry_iter_end();
478                 efivar_unregister(entry);
479         } else
480                 efivar_entry_iter_end();
481
482         /* It's dead Jim.... */
483         return count;
484 }
485
486 /**
487  * efivar_create_sysfs_entry - create a new entry in sysfs
488  * @new_var: efivar entry to create
489  *
490  * Returns 0 on success, negative error code on failure
491  */
492 static int
493 efivar_create_sysfs_entry(struct efivar_entry *new_var)
494 {
495         int short_name_size;
496         char *short_name;
497         unsigned long utf8_name_size;
498         efi_char16_t *variable_name = new_var->var.VariableName;
499         int ret;
500
501         /*
502          * Length of the variable bytes in UTF8, plus the '-' separator,
503          * plus the GUID, plus trailing NUL
504          */
505         utf8_name_size = ucs2_utf8size(variable_name);
506         short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
507
508         short_name = kmalloc(short_name_size, GFP_KERNEL);
509         if (!short_name)
510                 return -ENOMEM;
511
512         ucs2_as_utf8(short_name, variable_name, short_name_size);
513
514         /* This is ugly, but necessary to separate one vendor's
515            private variables from another's.         */
516         short_name[utf8_name_size] = '-';
517         efi_guid_to_str(&new_var->var.VendorGuid,
518                          short_name + utf8_name_size + 1);
519
520         new_var->kobj.kset = efivars_kset;
521
522         ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
523                                    NULL, "%s", short_name);
524         kfree(short_name);
525         if (ret)
526                 return ret;
527
528         kobject_uevent(&new_var->kobj, KOBJ_ADD);
529         if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
530                 efivar_unregister(new_var);
531                 return -EINTR;
532         }
533
534         return 0;
535 }
536
537 static int
538 create_efivars_bin_attributes(void)
539 {
540         struct bin_attribute *attr;
541         int error;
542
543         /* new_var */
544         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
545         if (!attr)
546                 return -ENOMEM;
547
548         attr->attr.name = "new_var";
549         attr->attr.mode = 0200;
550         attr->write = efivar_create;
551         efivars_new_var = attr;
552
553         /* del_var */
554         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
555         if (!attr) {
556                 error = -ENOMEM;
557                 goto out_free;
558         }
559         attr->attr.name = "del_var";
560         attr->attr.mode = 0200;
561         attr->write = efivar_delete;
562         efivars_del_var = attr;
563
564         sysfs_bin_attr_init(efivars_new_var);
565         sysfs_bin_attr_init(efivars_del_var);
566
567         /* Register */
568         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
569         if (error) {
570                 printk(KERN_ERR "efivars: unable to create new_var sysfs file"
571                         " due to error %d\n", error);
572                 goto out_free;
573         }
574
575         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
576         if (error) {
577                 printk(KERN_ERR "efivars: unable to create del_var sysfs file"
578                         " due to error %d\n", error);
579                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
580                 goto out_free;
581         }
582
583         return 0;
584 out_free:
585         kfree(efivars_del_var);
586         efivars_del_var = NULL;
587         kfree(efivars_new_var);
588         efivars_new_var = NULL;
589         return error;
590 }
591
592 static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
593                                      unsigned long name_size, void *data)
594 {
595         struct efivar_entry *entry = data;
596
597         if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
598                 return 0;
599
600         memcpy(entry->var.VariableName, name, name_size);
601         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
602
603         return 1;
604 }
605
606 static void efivar_update_sysfs_entries(struct work_struct *work)
607 {
608         struct efivar_entry *entry;
609         int err;
610
611         /* Add new sysfs entries */
612         while (1) {
613                 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
614                 if (!entry)
615                         return;
616
617                 err = efivar_init(efivar_update_sysfs_entry, entry,
618                                   false, &efivar_sysfs_list);
619                 if (!err)
620                         break;
621
622                 efivar_create_sysfs_entry(entry);
623         }
624
625         kfree(entry);
626 }
627
628 static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
629                                   unsigned long name_size, void *data)
630 {
631         struct efivar_entry *entry;
632
633         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
634         if (!entry)
635                 return -ENOMEM;
636
637         memcpy(entry->var.VariableName, name, name_size);
638         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
639
640         efivar_create_sysfs_entry(entry);
641
642         return 0;
643 }
644
645 static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
646 {
647         int err = efivar_entry_remove(entry);
648
649         if (err)
650                 return err;
651         efivar_unregister(entry);
652         return 0;
653 }
654
655 static void efivars_sysfs_exit(void)
656 {
657         /* Remove all entries and destroy */
658         int err;
659
660         err = __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list,
661                                   NULL, NULL);
662         if (err) {
663                 pr_err("efivars: Failed to destroy sysfs entries\n");
664                 return;
665         }
666
667         if (efivars_new_var)
668                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
669         if (efivars_del_var)
670                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
671         kfree(efivars_new_var);
672         kfree(efivars_del_var);
673         kset_unregister(efivars_kset);
674 }
675
676 int efivars_sysfs_init(void)
677 {
678         struct kobject *parent_kobj = efivars_kobject();
679         int error = 0;
680
681         if (!efi_enabled(EFI_RUNTIME_SERVICES))
682                 return -ENODEV;
683
684         /* No efivars has been registered yet */
685         if (!parent_kobj)
686                 return 0;
687
688         printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
689                EFIVARS_DATE);
690
691         efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
692         if (!efivars_kset) {
693                 printk(KERN_ERR "efivars: Subsystem registration failed.\n");
694                 return -ENOMEM;
695         }
696
697         efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list);
698
699         error = create_efivars_bin_attributes();
700         if (error) {
701                 efivars_sysfs_exit();
702                 return error;
703         }
704
705         INIT_WORK(&efivar_work, efivar_update_sysfs_entries);
706
707         return 0;
708 }
709 EXPORT_SYMBOL_GPL(efivars_sysfs_init);
710
711 module_init(efivars_sysfs_init);
712 module_exit(efivars_sysfs_exit);