2 * efi.c - EFI subsystem
4 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
5 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
6 * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 * This code registers /sys/firmware/efi{,/efivars} when EFI is supported,
9 * allowing the efivarfs to be mounted or the efivars module to be loaded.
10 * The existance of /sys/firmware/efi may also be used by userspace to
11 * determine that the system supports EFI.
13 * This file is released under the GPLv2.
16 #include <linux/kobject.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/device.h>
20 #include <linux/efi.h>
22 static struct kobject
*efi_kobj
;
23 static struct kobject
*efivars_kobj
;
26 * Let's not leave out systab information that snuck into
29 static ssize_t
systab_show(struct kobject
*kobj
,
30 struct kobj_attribute
*attr
, char *buf
)
37 if (efi
.mps
!= EFI_INVALID_TABLE_ADDR
)
38 str
+= sprintf(str
, "MPS=0x%lx\n", efi
.mps
);
39 if (efi
.acpi20
!= EFI_INVALID_TABLE_ADDR
)
40 str
+= sprintf(str
, "ACPI20=0x%lx\n", efi
.acpi20
);
41 if (efi
.acpi
!= EFI_INVALID_TABLE_ADDR
)
42 str
+= sprintf(str
, "ACPI=0x%lx\n", efi
.acpi
);
43 if (efi
.smbios
!= EFI_INVALID_TABLE_ADDR
)
44 str
+= sprintf(str
, "SMBIOS=0x%lx\n", efi
.smbios
);
45 if (efi
.hcdp
!= EFI_INVALID_TABLE_ADDR
)
46 str
+= sprintf(str
, "HCDP=0x%lx\n", efi
.hcdp
);
47 if (efi
.boot_info
!= EFI_INVALID_TABLE_ADDR
)
48 str
+= sprintf(str
, "BOOTINFO=0x%lx\n", efi
.boot_info
);
49 if (efi
.uga
!= EFI_INVALID_TABLE_ADDR
)
50 str
+= sprintf(str
, "UGA=0x%lx\n", efi
.uga
);
55 static struct kobj_attribute efi_attr_systab
=
56 __ATTR(systab
, 0400, systab_show
, NULL
);
58 static struct attribute
*efi_subsys_attrs
[] = {
59 &efi_attr_systab
.attr
,
60 NULL
, /* maybe more in the future? */
63 static struct attribute_group efi_subsys_attr_group
= {
64 .attrs
= efi_subsys_attrs
,
67 static struct efivars generic_efivars
;
68 static struct efivar_operations generic_ops
;
70 static int generic_ops_register(void)
72 generic_ops
.get_variable
= efi
.get_variable
;
73 generic_ops
.set_variable
= efi
.set_variable
;
74 generic_ops
.get_next_variable
= efi
.get_next_variable
;
75 generic_ops
.query_variable_store
= efi_query_variable_store
;
77 return efivars_register(&generic_efivars
, &generic_ops
, efi_kobj
);
80 static void generic_ops_unregister(void)
82 efivars_unregister(&generic_efivars
);
86 * We register the efi subsystem with the firmware subsystem and the
87 * efivars subsystem with the efi subsystem, if the system was booted with
90 static int __init
efisubsys_init(void)
94 if (!efi_enabled(EFI_BOOT
))
97 /* We register the efi directory at /sys/firmware/efi */
98 efi_kobj
= kobject_create_and_add("efi", firmware_kobj
);
100 pr_err("efi: Firmware registration failed.\n");
104 error
= generic_ops_register();
108 error
= sysfs_create_group(efi_kobj
, &efi_subsys_attr_group
);
110 pr_err("efi: Sysfs attribute export failed with error %d.\n",
115 /* and the standard mountpoint for efivarfs */
116 efivars_kobj
= kobject_create_and_add("efivars", efi_kobj
);
118 pr_err("efivars: Subsystem registration failed.\n");
120 goto err_remove_group
;
126 sysfs_remove_group(efi_kobj
, &efi_subsys_attr_group
);
128 generic_ops_unregister();
130 kobject_put(efi_kobj
);
134 subsys_initcall(efisubsys_init
);