Skip to content

Commit

Permalink
efi: Export more EFI table variables to sysfs
Browse files Browse the repository at this point in the history
Export fw_vendor, runtime and config table physical addresses to
/sys/firmware/efi/{fw_vendor,runtime,config_table} because kexec kernels
need them.

From EFI spec these 3 variables will be updated to virtual address after
entering virtual mode. But kernel startup code will need the physical
address.

Signed-off-by: Dave Young <dyoung@redhat.com>
Tested-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
  • Loading branch information
Dave Young authored and Matt Fleming committed Dec 21, 2013
1 parent 481f75c commit a0998eb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Documentation/ABI/testing/sysfs-firmware-efi
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
What: /sys/firmware/efi/fw_vendor
Date: December 2013
Contact: Dave Young <dyoung@redhat.com>
Description: It shows the physical address of firmware vendor field in the
EFI system table.
Users: Kexec

What: /sys/firmware/efi/runtime
Date: December 2013
Contact: Dave Young <dyoung@redhat.com>
Description: It shows the physical address of runtime service table entry in
the EFI system table.
Users: Kexec

What: /sys/firmware/efi/config_table
Date: December 2013
Contact: Dave Young <dyoung@redhat.com>
Description: It shows the physical address of config table entry in the EFI
system table.
Users: Kexec
4 changes: 4 additions & 0 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,10 @@ void __init efi_init(void)

set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);

efi.config_table = (unsigned long)efi.systab->tables;
efi.fw_vendor = (unsigned long)efi.systab->fw_vendor;
efi.runtime = (unsigned long)efi.systab->runtime;

/*
* Show what we know for posterity
*/
Expand Down
41 changes: 40 additions & 1 deletion drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct efi __read_mostly efi = {
.hcdp = EFI_INVALID_TABLE_ADDR,
.uga = EFI_INVALID_TABLE_ADDR,
.uv_systab = EFI_INVALID_TABLE_ADDR,
.fw_vendor = EFI_INVALID_TABLE_ADDR,
.runtime = EFI_INVALID_TABLE_ADDR,
.config_table = EFI_INVALID_TABLE_ADDR,
};
EXPORT_SYMBOL(efi);

Expand Down Expand Up @@ -71,13 +74,49 @@ static ssize_t systab_show(struct kobject *kobj,
static struct kobj_attribute efi_attr_systab =
__ATTR(systab, 0400, systab_show, NULL);

#define EFI_FIELD(var) efi.var

#define EFI_ATTR_SHOW(name) \
static ssize_t name##_show(struct kobject *kobj, \
struct kobj_attribute *attr, char *buf) \
{ \
return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
}

EFI_ATTR_SHOW(fw_vendor);
EFI_ATTR_SHOW(runtime);
EFI_ATTR_SHOW(config_table);

static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);

static struct attribute *efi_subsys_attrs[] = {
&efi_attr_systab.attr,
NULL, /* maybe more in the future? */
&efi_attr_fw_vendor.attr,
&efi_attr_runtime.attr,
&efi_attr_config_table.attr,
NULL,
};

static umode_t efi_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
umode_t mode = attr->mode;

if (attr == &efi_attr_fw_vendor.attr)
return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
else if (attr == &efi_attr_runtime.attr)
return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
else if (attr == &efi_attr_config_table.attr)
return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode;

return mode;
}

static struct attribute_group efi_subsys_attr_group = {
.attrs = efi_subsys_attrs,
.is_visible = efi_attr_is_visible,
};

static struct efivars generic_efivars;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,9 @@ extern struct efi {
unsigned long hcdp; /* HCDP table */
unsigned long uga; /* UGA table */
unsigned long uv_systab; /* UV system table */
unsigned long fw_vendor; /* fw_vendor */
unsigned long runtime; /* runtime table */
unsigned long config_table; /* config tables */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
Expand Down

0 comments on commit a0998eb

Please sign in to comment.