Commit a9499fa7 authored by Tom Gundersen's avatar Tom Gundersen Committed by Matt Fleming

efi: split efisubsystem from efivars

This registers /sys/firmware/efi/{,systab,efivars/} whenever EFI is enabled
and the system is booted with EFI.

This allows
 *) userspace to check for the existence of /sys/firmware/efi as a way
    to determine whether or it is running on an EFI system.
 *) 'mount -t efivarfs none /sys/firmware/efi/efivars' without manually
    loading any modules.

[ Also, move the efivar API into vars.c and unconditionally compile it.
  This allows us to move efivars.c, which now only contains the sysfs
  variable code, into the firmware/efi directory. Note that the efivars.c
  filename is kept to maintain backwards compatability with the old
  efivars.ko module. With this patch it is now possible for efivarfs
  to be built without CONFIG_EFI_VARS - Matt ]

Cc: Seiji Aguchi <>
Cc: Tony Luck <>
Cc: Mike Waychison <>
Cc: Kay Sievers <>
Cc: Jeremy Kerr <>
Cc: Matthew Garrett <>
Cc: Chun-Yi Lee <>
Cc: Andy Whitcroft <>
Cc: Tobias Powalowski <>
Signed-off-by: default avatarTom Gundersen <>
Signed-off-by: default avatarMatt Fleming <>
parent d68772b7
......@@ -2987,7 +2987,7 @@ F: arch/ia64/kernel/efi.c
F: arch/x86/boot/compressed/eboot.[ch]
F: arch/x86/include/asm/efi.h
F: arch/x86/platform/efi/*
F: drivers/firmware/efivars.c
F: drivers/firmware/efi/*
F: include/linux/efi*.h
......@@ -4,7 +4,6 @@
obj-$(CONFIG_DMI) += dmi_scan.o
obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
# Makefile for linux kernel
obj-y += efi.o vars.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
* efi.c - EFI subsystem
* Copyright (C) 2001,2003,2004 Dell <>
* Copyright (C) 2004 Intel Corporation <>
* Copyright (C) 2013 Tom Gundersen <>
* This code registers /sys/firmware/efi{,/efivars} when EFI is supported,
* allowing the efivarfs to be mounted or the efivars module to be loaded.
* The existance of /sys/firmware/efi may also be used by userspace to
* determine that the system supports EFI.
* This file is released under the GPLv2.
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/efi.h>
static struct kobject *efi_kobj;
static struct kobject *efivars_kobj;
* Let's not leave out systab information that snuck into
* the efivars driver
static ssize_t systab_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
char *str = buf;
if (!kobj || !buf)
return -EINVAL;
if (efi.mps != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "MPS=0x%lx\n", efi.mps);
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
if (efi.acpi != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
if (efi.uga != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "UGA=0x%lx\n", efi.uga);
return str - buf;
static struct kobj_attribute efi_attr_systab =
__ATTR(systab, 0400, systab_show, NULL);
static struct attribute *efi_subsys_attrs[] = {
NULL, /* maybe more in the future? */
static struct attribute_group efi_subsys_attr_group = {
.attrs = efi_subsys_attrs,
static struct efivars generic_efivars;
static struct efivar_operations generic_ops;
static int generic_ops_register(void)
generic_ops.get_variable = efi.get_variable;
generic_ops.set_variable = efi.set_variable;
generic_ops.get_next_variable = efi.get_next_variable;
generic_ops.query_variable_info = efi.query_variable_info;
return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
static void generic_ops_unregister(void)
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
* EFI.
static int __init efisubsys_init(void)
int error;
if (!efi_enabled(EFI_BOOT))
return 0;
/* We register the efi directory at /sys/firmware/efi */
efi_kobj = kobject_create_and_add("efi", firmware_kobj);
if (!efi_kobj) {
pr_err("efi: Firmware registration failed.\n");
return -ENOMEM;
error = generic_ops_register();
if (error)
goto err_put;
error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
if (error) {
pr_err("efi: Sysfs attribute export failed with error %d.\n",
goto err_unregister;
/* and the standard mountpoint for efivarfs */
efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
if (!efivars_kobj) {
pr_err("efivars: Subsystem registration failed.\n");
error = -ENOMEM;
goto err_remove_group;
return 0;
sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
return error;
This diff is collapsed.
config EFIVAR_FS
tristate "EFI Variable filesystem"
depends on EFI_VARS
depends on EFI
efivarfs is a replacement filesystem for the old EFI
variable support via sysfs, as it doesn't suffer from the
......@@ -742,7 +742,6 @@ utf16_strlen(efi_char16_t *s)
return utf16_strnlen(s, ~0UL);
* Return the number of bytes is the length of this string
* Note: this is NOT the same as the number of unicode characters
......@@ -872,8 +871,10 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
bool efivar_validate(struct efi_variable *var, u8 *data, unsigned long len);
extern struct work_struct efivar_work;
void efivar_run_worker(void);
int efivars_sysfs_init(void);
#endif /* CONFIG_EFI_VARS */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment