Commit 937d96d2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'efi-next-for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel:
 "Although some more stuff is brewing, the EFI changes that are ready
  for mainline are few this cycle:

   - improve the PCI DMA paranoia logic in the EFI stub

   - some constification changes

   - add statfs support to efivarfs

   - allow user space to enumerate updatable firmware resources without
     CAP_SYS_ADMIN"

* tag 'efi-next-for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  efi/libstub: Disable PCI DMA before grabbing the EFI memory map
  efi/esrt: Allow ESRT access without CAP_SYS_ADMIN
  efivarfs: expose used and total size
  efi: make kobj_type structure constant
  efi: x86: make kobj_type structure constant
parents 5d95ff84 2e28a798
...@@ -114,6 +114,14 @@ void efi_delete_dummy_variable(void) ...@@ -114,6 +114,14 @@ void efi_delete_dummy_variable(void)
EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL);
} }
u64 efivar_reserved_space(void)
{
if (efi_no_storage_paranoia)
return 0;
return EFI_MIN_RESERVE;
}
EXPORT_SYMBOL_GPL(efivar_reserved_space);
/* /*
* In the nonblocking case we do not attempt to perform garbage * In the nonblocking case we do not attempt to perform garbage
* collection if we do not have enough free space. Rather, we do the * collection if we do not have enough free space. Rather, we do the
......
...@@ -93,7 +93,7 @@ static void map_release(struct kobject *kobj) ...@@ -93,7 +93,7 @@ static void map_release(struct kobject *kobj)
kfree(entry); kfree(entry);
} }
static struct kobj_type __refdata map_ktype = { static const struct kobj_type __refconst map_ktype = {
.sysfs_ops = &map_attr_ops, .sysfs_ops = &map_attr_ops,
.default_groups = def_groups, .default_groups = def_groups,
.release = map_release, .release = map_release,
......
...@@ -214,6 +214,7 @@ static int generic_ops_register(void) ...@@ -214,6 +214,7 @@ static int generic_ops_register(void)
generic_ops.get_variable = efi.get_variable; generic_ops.get_variable = efi.get_variable;
generic_ops.get_next_variable = efi.get_next_variable; generic_ops.get_next_variable = efi.get_next_variable;
generic_ops.query_variable_store = efi_query_variable_store; generic_ops.query_variable_store = efi_query_variable_store;
generic_ops.query_variable_info = efi.query_variable_info;
if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) { if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) {
generic_ops.set_variable = efi.set_variable; generic_ops.set_variable = efi.set_variable;
......
...@@ -95,10 +95,6 @@ static ssize_t esre_attr_show(struct kobject *kobj, ...@@ -95,10 +95,6 @@ static ssize_t esre_attr_show(struct kobject *kobj,
struct esre_entry *entry = to_entry(kobj); struct esre_entry *entry = to_entry(kobj);
struct esre_attribute *attr = to_attr(_attr); struct esre_attribute *attr = to_attr(_attr);
/* Don't tell normal users what firmware versions we've got... */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return attr->show(entry, buf); return attr->show(entry, buf);
} }
...@@ -156,7 +152,7 @@ static void esre_release(struct kobject *kobj) ...@@ -156,7 +152,7 @@ static void esre_release(struct kobject *kobj)
kfree(entry); kfree(entry);
} }
static struct kobj_type esre1_ktype = { static const struct kobj_type esre1_ktype = {
.release = esre_release, .release = esre_release,
.sysfs_ops = &esre_attr_ops, .sysfs_ops = &esre_attr_ops,
.default_groups = esre1_groups, .default_groups = esre1_groups,
......
...@@ -378,6 +378,9 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, ...@@ -378,6 +378,9 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,
struct efi_boot_memmap *map; struct efi_boot_memmap *map;
efi_status_t status; efi_status_t status;
if (efi_disable_pci_dma)
efi_pci_disable_bridge_busmaster();
status = efi_get_memory_map(&map, true); status = efi_get_memory_map(&map, true);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
...@@ -388,9 +391,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, ...@@ -388,9 +391,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,
return status; return status;
} }
if (efi_disable_pci_dma)
efi_pci_disable_bridge_busmaster();
status = efi_bs_call(exit_boot_services, handle, map->map_key); status = efi_bs_call(exit_boot_services, handle, map->map_key);
if (status == EFI_INVALID_PARAMETER) { if (status == EFI_INVALID_PARAMETER) {
......
...@@ -245,3 +245,15 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor, ...@@ -245,3 +245,15 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
return status; return status;
} }
EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR); EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR);
efi_status_t efivar_query_variable_info(u32 attr,
u64 *storage_space,
u64 *remaining_space,
u64 *max_variable_size)
{
if (!__efivars->ops->query_variable_info)
return EFI_UNSUPPORTED;
return __efivars->ops->query_variable_info(attr, storage_space,
remaining_space, max_variable_size);
}
EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, EFIVAR);
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/ucs2_string.h> #include <linux/ucs2_string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/statfs.h>
#include "internal.h" #include "internal.h"
...@@ -23,8 +24,44 @@ static void efivarfs_evict_inode(struct inode *inode) ...@@ -23,8 +24,44 @@ static void efivarfs_evict_inode(struct inode *inode)
clear_inode(inode); clear_inode(inode);
} }
static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
const u32 attr = EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
u64 storage_space, remaining_space, max_variable_size;
efi_status_t status;
status = efivar_query_variable_info(attr, &storage_space, &remaining_space,
&max_variable_size);
if (status != EFI_SUCCESS)
return efi_status_to_err(status);
/*
* This is not a normal filesystem, so no point in pretending it has a block
* size; we declare f_bsize to 1, so that we can then report the exact value
* sent by EFI QueryVariableInfo in f_blocks and f_bfree
*/
buf->f_bsize = 1;
buf->f_namelen = NAME_MAX;
buf->f_blocks = storage_space;
buf->f_bfree = remaining_space;
buf->f_type = dentry->d_sb->s_magic;
/*
* In f_bavail we declare the free space that the kernel will allow writing
* when the storage_paranoia x86 quirk is active. To use more, users
* should boot the kernel with efi_no_storage_paranoia.
*/
if (remaining_space > efivar_reserved_space())
buf->f_bavail = remaining_space - efivar_reserved_space();
else
buf->f_bavail = 0;
return 0;
}
static const struct super_operations efivarfs_ops = { static const struct super_operations efivarfs_ops = {
.statfs = simple_statfs, .statfs = efivarfs_statfs,
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.evict_inode = efivarfs_evict_inode, .evict_inode = efivarfs_evict_inode,
}; };
......
...@@ -1056,6 +1056,7 @@ struct efivar_operations { ...@@ -1056,6 +1056,7 @@ struct efivar_operations {
efi_set_variable_t *set_variable; efi_set_variable_t *set_variable;
efi_set_variable_t *set_variable_nonblocking; efi_set_variable_t *set_variable_nonblocking;
efi_query_variable_store_t *query_variable_store; efi_query_variable_store_t *query_variable_store;
efi_query_variable_info_t *query_variable_info;
}; };
struct efivars { struct efivars {
...@@ -1063,6 +1064,12 @@ struct efivars { ...@@ -1063,6 +1064,12 @@ struct efivars {
const struct efivar_operations *ops; const struct efivar_operations *ops;
}; };
#ifdef CONFIG_X86
u64 __attribute_const__ efivar_reserved_space(void);
#else
static inline u64 efivar_reserved_space(void) { return 0; }
#endif
/* /*
* The maximum size of VariableName + Data = 1024 * The maximum size of VariableName + Data = 1024
* Therefore, it's reasonable to save that much * Therefore, it's reasonable to save that much
...@@ -1101,6 +1108,10 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor, ...@@ -1101,6 +1108,10 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor, efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
u32 attr, unsigned long data_size, void *data); u32 attr, unsigned long data_size, void *data);
efi_status_t efivar_query_variable_info(u32 attr, u64 *storage_space,
u64 *remaining_space,
u64 *max_variable_size);
#if IS_ENABLED(CONFIG_EFI_CAPSULE_LOADER) #if IS_ENABLED(CONFIG_EFI_CAPSULE_LOADER)
extern bool efi_capsule_pending(int *reset_type); extern bool efi_capsule_pending(int *reset_type);
......
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