efi: Restructure EFI varstore driver
Subsystems (7)
Ard Biesheuvel
maintainerv3 cover efi: Restructure EFI varstore driver
Currently, efi-pstore, efivarfs and the efivars sysfs interface all share a common support layer which manages a linked list containing efivar_entry items describing each EFI variable that this support layer assumes to be present in the EFI variable store managed by the firmware.
This shared layer also contains an efivars_operations pointer, which carries function pointers that refer to the underlying EFI get/set variable routines, but can be superseded by other implementations (currently, this is only implemented for Google x86 systems that implement the GSMI interface)
Each user of this shared layer has its own linked list, which means they all have a different view of the underlying variable store, even though they might operate on the same variables. For EFI pstore related variables in particular, manipulating these behind the back of the other drivers is likely to result in fun.
This shared layer as well as its 3 different users all use a single semaphore to mediate access to the individual linked lists and the ops pointer.
The shared layer carries a substantial amount of 'business logic' related to which EFI variables are relevant to the firmware, to limit whether and how they may be manipulated. This aspect of the code is only relevant when such variables can be manipulated arbitrarily, e.g. by user space, but EFI pstore, for example, has no need for this, as it uses its own GUIDed namespace for EFI variables, and does not permit other variables to be manipulated.
The two remaining users are efivars sysfs and efivarfs, both of which provide a cached view of these 'important' variables. Given that the former has been deprecated for a long time, and given the potential concerns around using both concurrently, let's get rid of the sysfs based one.
Then, we can restructure the efivars API so that this business logic can be incorporated into the efivarfs driver, leaving only a minimal wrapper around the get/set variable calls, allowing the GSMI replacement to remain in use, as well as mediate access to the different services using the existing semaphore. This is mainly useful to ensure that set_variable() calls do no invalidate an enumeration of the EFI variables that is in progress using get_next_variable() by another task.
Some of the prerequisites of this work have been posted separately and have been queued up in efi/next already, mainly to move other users away from the efivar API which they were using in the wrong way, or without a good reason.
Changes since v2:
- add a pstore_record::priv field and use it to record the EFI variable name exactly as it was used to retrieve the entry;
- drop another pstore patch related to the ECC field that is no longer needed;
- drop some remaining EXPORT_SYMBOL()s of the efivar API symbols that are now private to efivarfs
Ard Biesheuvel (9):
pstore: Add priv field to pstore_record for backend specific use
efi: vars: Don't drop lock in the middle of efivar_init()
efi: vars: Add thin wrapper around EFI get/set variable interface
efi: pstore: Omit efivars caching EFI varstore access layer
efi: vars: Use locking version to iterate over efivars linked lists
efi: vars: Drop __efivar_entry_iter() helper which is no longer used
efi: vars: Remove deprecated 'efivars' sysfs interface
efi: vars: Switch to new wrapper layer
efi: vars: Move efivar caching layer into efivarfs
Documentation/x86/x86_64/uefi.rst | 2 +- arch/arm/configs/milbeaut_m10v_defconfig | 1 - arch/ia64/configs/bigsur_defconfig | 1 - arch/ia64/configs/generic_defconfig | 1 - arch/ia64/configs/gensparse_defconfig | 1 - arch/ia64/configs/tiger_defconfig | 1 - arch/ia64/configs/zx1_defconfig | 1 - arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - drivers/firmware/efi/Kconfig | 13 +- drivers/firmware/efi/Makefile | 1 - drivers/firmware/efi/efi-pstore.c | 377 ++---- drivers/firmware/efi/efi.c | 1 + drivers/firmware/efi/efivars.c | 671 ----------- drivers/firmware/efi/vars.c | 1219 +++----------------- fs/efivarfs/Makefile | 2 +- fs/efivarfs/internal.h | 40 + fs/efivarfs/super.c | 15 +- fs/efivarfs/vars.c | 738 ++++++++++++ fs/pstore/inode.c | 1 + fs/pstore/platform.c | 1 + include/linux/efi.h | 80 +- include/linux/pstore.h | 4 + 23 files changed, 1031 insertions(+), 2142 deletions(-) delete mode 100644 drivers/firmware/efi/efivars.c create mode 100644 fs/efivarfs/vars.c
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 1/9 pstore: Add priv field to pstore_record for backend specific use
The EFI pstore backend will need to store per-record variable name data when we switch away from the efivars layer. Add a priv field to struct pstore_record, and document it as holding a backend specific pointer that is assumed to be a kmalloc()d buffer, and will be kfree()d when the entire record is freed.
--- fs/pstore/inode.c | 1 + fs/pstore/platform.c | 1 + include/linux/pstore.h | 4 ++++ 3 files changed, 6 insertions(+)
fs/pstore/inode.c +1 -0
@@ -55,6 +55,7 @@ static void free_pstore_private(struct pstore_private *private)return ;if (private->record) {kfree (private->record->buf); +kfree (private->record->priv);kfree (private->record); }kfree (private);
fs/pstore/platform.c +1 -0
@@ -769,6 +769,7 @@ void pstore_get_backend_records(struct pstore_info *psi,if (rc) {/* pstore_mkfile() did not take record, so free it. */ kfree (record->buf); +kfree (record->priv);kfree (record);if (rc != -EEXIST || !quiet) failed++;
include/linux/pstore.h +4 -0
@@ -57,6 +57,9 @@ struct pstore_info;* @size: size of @buf * @ecc_notice_size: * ECC information for @buf +* @priv: pointer for backend specific use, will be +* kfree()d by the pstore core if non-NULL +* when the record is freed. * * Valid for PSTORE_TYPE_DMESG @type: *
@@ -74,6 +77,7 @@ struct pstore_record {char *buf;ssize_t size;ssize_t ecc_notice_size; +void *priv;int count;enum kmsg_dump_reason reason;
Signature · 1 line
2.35.1
Re: [PATCH v3 1/9] pstore: Add priv field to pstore_record for backend specific use
Quoted 7 lines · Ard Biesheuvel
The EFI pstore backend will need to store per-record variable name data when we switch away from the efivars layer. Add a priv field to struct
pstore_record, and document it as holding a backend specific pointer that is assumed to be a kmalloc()d buffer, and will be kfree()d when the entire record is freed.Signed-off-by Ard Biesheuvel <[email protected]>
I'm a fan! This is useful, and I'll likely try to use it for some of the RAM-specific things too. :)
Signature · 1 line
Kees Cook
Ard Biesheuvel
maintainerPATCH v3 2/9 efi: vars: Don't drop lock in the middle of efivar_init()
In reply to Ard BiesheuvelEven though the efivars_lock lock is documented as protecting the efivars->ops pointer (among other things), efivar_init() happily releases and reacquires the lock for every EFI variable that it enumerates. This used to be needed because the lock was originally a spinlock, which prevented the callback that is invoked for every variable from being able to sleep. However, releasing the lock could potentially invalidate the ops pointer, but more importantly, it might allow a SetVariable() runtime service call to take place concurrently, and the UEFI spec does not define how this affects an enumeration that is running in parallel using the GetNextVariable() runtime service, which is what efivar_init() uses.
In the meantime, the lock has been converted into a semaphore, and the only reason we need to drop the lock is because the efivarfs pseudo filesystem driver will otherwise deadlock when it invokes the efivars API from the callback to create the efivar_entry items and insert them into the linked list. (EFI pstore is affected in a similar way)
So let's switch to helpers that can be used while the lock is already taken. This way, we can hold on to the lock throughout the enumeration.
--- drivers/firmware/efi/efi-pstore.c | 7 ++----- drivers/firmware/efi/efivars.c | 5 +---- drivers/firmware/efi/vars.c | 22 ++++++++++---------- fs/efivarfs/super.c | 6 ++---- include/linux/efi.h | 1 + 5 files changed, 17 insertions(+), 24 deletions(-)
drivers/firmware/efi/efi-pstore.c +2 -5
@@ -364,7 +364,6 @@ static int efi_pstore_callback(efi_char16_t *name, efi_guid_t vendor, unsigned long name_size, void *data) { struct efivar_entry *entry; -int ret; entry =kzalloc (sizeof (*entry),GFP_KERNEL );if (!entry)
@@ -373,11 +372,9 @@ static int efi_pstore_callback(efi_char16_t *name, efi_guid_t vendor,memcpy (entry->var.VariableName, name, name_size); entry->var.VendorGuid = vendor; - ret =efivar_entry_add (entry, &efi_pstore_list); -if (ret) -kfree (entry); +__efivar_entry_add (entry, &efi_pstore_list); -return ret; +return 0 ; } static int efi_pstore_update_entry(efi_char16_t *name, efi_guid_t vendor,
drivers/firmware/efi/efivars.c +1 -4
@@ -527,10 +527,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) }kobject_uevent (&new_var->kobj,KOBJ_ADD ); -if (efivar_entry_add (new_var, &efivar_sysfs_list)) { -efivar_unregister (new_var); -return -EINTR ; - } +__efivar_entry_add (new_var, &efivar_sysfs_list);return 0 ; }
drivers/firmware/efi/vars.c +11 -11
@@ -450,9 +450,6 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), &vendor_guid);switch (status) {case EFI_SUCCESS : -if (duplicates) -up (&efivars_lock); - variable_name_size =var_name_strnsize (variable_name, variable_name_size);
@@ -476,14 +473,6 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),if (err) status =EFI_NOT_FOUND ; } - -if (duplicates) { -if (down_interruptible (&efivars_lock)) { - err = -EINTR ; - goto free; - } - } -break ;case EFI_UNSUPPORTED : err = -EOPNOTSUPP ;
@@ -526,6 +515,17 @@ int efivar_entry_add(struct efivar_entry *entry, struct list_head *head) }EXPORT_SYMBOL_GPL (efivar_entry_add); +/** +* __efivar_entry_add - add entry to variable list +* @entry: entry to add to list +* @head: list head +*/ +void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head) +{ +list_add (&entry->list, head); +} +EXPORT_SYMBOL_GPL (__efivar_entry_add); +/** * efivar_entry_remove - remove entry from variable list * @entry: entry to remove from list
fs/efivarfs/super.c +2 -4
@@ -155,10 +155,8 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, goto fail_inode; } -efivar_entry_size (entry, &size); - err =efivar_entry_add (entry, &efivarfs_list); -if (err) - goto fail_inode; +__efivar_entry_get (entry,NULL , &size,NULL ); +__efivar_entry_add (entry, &efivarfs_list);/* copied by the above to local storage in the dentry. */ kfree (name);
include/linux/efi.h +1 -0
@@ -1064,6 +1064,7 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), void *data, bool duplicates, struct list_head *head);int efivar_entry_add (struct efivar_entry *entry,struct list_head *head); +void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head);int efivar_entry_remove (struct efivar_entry *entry);int __efivar_entry_delete (struct efivar_entry *entry);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 3/9 efi: vars: Add thin wrapper around EFI get/set variable interface
In reply to Ard BiesheuvelThe current efivars layer is a jumble of list iterators, shadow data structures and safe variable manipulation helpers that really belong in the efivarfs pseudo file system once the obsolete sysfs access method to EFI variables is removed.
So split off a minimal efivar get/set variable API that reuses the existing efivars_lock semaphore to mediate access to the various runtime services, primarily to ensure that performing a SetVariable() on one CPU while another is calling GetNextVariable() in a loop to enumerate the contents of the EFI variable store does not result in surprises.
--- drivers/firmware/efi/vars.c | 154 ++++++++++++++++++-- include/linux/efi.h | 20 +++ 2 files changed, 164 insertions(+), 10 deletions(-)
drivers/firmware/efi/vars.c +144 -10
@@ -298,14 +298,10 @@ efivar_variable_is_removable(efi_guid_t vendor, const char *var_name, }EXPORT_SYMBOL_GPL (efivar_variable_is_removable); -static efi_status_t -check_var_size (u32 attributes,unsigned long size) +efi_status_t check_var_size (u32 attributes,unsigned long size) {const struct efivar_operations *fops; -if (!__efivars) -return EFI_UNSUPPORTED ; - fops = __efivars->ops;if (!fops->query_variable_store)
@@ -313,15 +309,12 @@ check_var_size(u32 attributes, unsigned long size)return fops->query_variable_store (attributes, size, false); } +EXPORT_SYMBOL_NS_GPL (check_var_size,EFIVAR ); -static efi_status_t -check_var_size_nonblocking (u32 attributes,unsigned long size) +efi_status_t check_var_size_nonblocking (u32 attributes,unsigned long size) {const struct efivar_operations *fops; -if (!__efivars) -return EFI_UNSUPPORTED ; - fops = __efivars->ops;if (!fops->query_variable_store)
@@ -329,6 +322,7 @@ check_var_size_nonblocking(u32 attributes, unsigned long size)return fops->query_variable_store (attributes, size, true); } +EXPORT_SYMBOL_NS_GPL (check_var_size_nonblocking,EFIVAR );static bool variable_is_present (efi_char16_t *variable_name,efi_guid_t *vendor,struct list_head *head)
@@ -1220,3 +1214,143 @@ int efivar_supports_writes(void)return __efivars && __efivars->ops->set_variable; }EXPORT_SYMBOL_GPL (efivar_supports_writes); + +/* +* efivar_lock() - obtain the efivar lock, wait for it if needed +* @return 0 on success, error code on failure +*/ +int efivar_lock (void ) +{ +if (down_interruptible (&efivars_lock)) +return -EINTR ; +if (!__efivars->ops) { +up (&efivars_lock); +return -ENODEV ; + } +return 0 ; +} +EXPORT_SYMBOL_NS_GPL (efivar_lock,EFIVAR ); + +/* +* efivar_lock() - obtain the efivar lock if it is free +* @return 0 on success, error code on failure +*/ +int efivar_trylock (void ) +{ +if (down_trylock (&efivars_lock)) +return -EBUSY ; +if (!__efivars->ops) { +up (&efivars_lock); +return -ENODEV ; + } +return 0 ; +} +EXPORT_SYMBOL_NS_GPL (efivar_trylock,EFIVAR ); + +/* +* efivar_unlock() - release the efivar lock +*/ +void efivar_unlock (void ) +{ +up (&efivars_lock); +} +EXPORT_SYMBOL_NS_GPL (efivar_unlock,EFIVAR ); + +/* +* efivar_get_variable() - retrieve a variable identified by name/vendor +* +* Must be called with efivars_lock held. +*/ +efi_status_t efivar_get_variable (efi_char16_t *name,efi_guid_t *vendor, +u32 *attr,unsigned long *size,void *data) +{ +return __efivars->ops->get_variable (name, vendor, attr, size, data); +} +EXPORT_SYMBOL_NS_GPL (efivar_get_variable,EFIVAR ); + +/* +* efivar_get_next_variable() - enumerate the next name/vendor pair +* +* Must be called with efivars_lock held. +*/ +efi_status_t efivar_get_next_variable (unsigned long *name_size, +efi_char16_t *name,efi_guid_t *vendor) +{ +return __efivars->ops->get_next_variable (name_size, name, vendor); +} +EXPORT_SYMBOL_NS_GPL (efivar_get_next_variable,EFIVAR ); + +/* +* efivar_set_variable_blocking() - local helper function for set_variable +* +* Must be called with efivars_lock held. +*/ +static efi_status_t +efivar_set_variable_blocking (efi_char16_t *name,efi_guid_t *vendor, +u32 attr,unsigned long data_size,void *data) +{ +efi_status_t status; + +if (data_size >0 ) { + status =check_var_size (attr, data_size + +ucs2_strsize (name,1024 )); +if (status !=EFI_SUCCESS ) +return status; + } +return __efivars->ops->set_variable (name, vendor, attr, data_size, data); +} + +/* +* efivar_set_variable_locked() - set a variable identified by name/vendor +* +* Must be called with efivars_lock held. If @nonblocking is set, it will use +* non-blocking primitives so it is guaranteed not to sleep. +*/ +efi_status_t efivar_set_variable_locked (efi_char16_t *name,efi_guid_t *vendor, +u32 attr,unsigned long data_size, +void *data,bool nonblocking) +{ +efi_set_variable_t *setvar; +efi_status_t status; + +if (!nonblocking) +return efivar_set_variable_blocking (name, vendor, attr, + data_size, data); + +/* +* If no _nonblocking variant exists, the ordinary one +* is assumed to be non-blocking. +*/ + setvar = __efivars->ops->set_variable_nonblocking ?: + __efivars->ops->set_variable; + +if (data_size >0 ) { + status =check_var_size_nonblocking (attr, data_size + +ucs2_strsize (name,1024 )); +if (status !=EFI_SUCCESS ) +return status; + } +return setvar (name, vendor, attr, data_size, data); +} +EXPORT_SYMBOL_NS_GPL (efivar_set_variable_locked,EFIVAR ); + +/* +* efivar_set_variable() - set a variable identified by name/vendor +* +* Can be called without holding the efivars_lock. Will sleep on obtaining the +* lock, or on obtaining other locks that are needed in order to complete the +* call. +*/ +efi_status_t efivar_set_variable (efi_char16_t *name,efi_guid_t *vendor, +u32 attr,unsigned long data_size,void *data) +{ +efi_status_t status; + +if (efivar_lock ()) +return EFI_ABORTED ; + + status =efivar_set_variable_blocking (name, vendor, attr, data_size, data); +efivar_unlock (); +return status; +} +EXPORT_SYMBOL_NS_GPL (efivar_set_variable,EFIVAR );
include/linux/efi.h +20 -0
@@ -1099,6 +1099,26 @@ bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,bool efivar_variable_is_removable (efi_guid_t vendor,const char *name,size_t len); +int efivar_lock (void ); +int efivar_trylock (void ); +void efivar_unlock (void ); + +efi_status_t efivar_get_variable (efi_char16_t *name,efi_guid_t *vendor, +u32 *attr,unsigned long *size,void *data); + +efi_status_t efivar_get_next_variable (unsigned long *name_size, +efi_char16_t *name,efi_guid_t *vendor); + +efi_status_t efivar_set_variable_locked (efi_char16_t *name,efi_guid_t *vendor, +u32 attr,unsigned long data_size, +void *data,bool nonblocking); + +efi_status_t efivar_set_variable (efi_char16_t *name,efi_guid_t *vendor, +u32 attr,unsigned long data_size,void *data); + +efi_status_t check_var_size (u32 attributes,unsigned long size); +efi_status_t check_var_size_nonblocking (u32 attributes,unsigned long size); +#if IS_ENABLED (CONFIG_EFI_CAPSULE_LOADER )extern bool efi_capsule_pending (int *reset_type);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 4/9 efi: pstore: Omit efivars caching EFI varstore access layer
In reply to Ard BiesheuvelAvoid the efivars layer and simply call the newly introduced EFI varstore helpers instead. This simplifies the code substantially, and also allows us to remove some hacks in the shared efivars layer that were added for efi-pstore specifically.
In order to be able to delete the EFI variable associated with a record, store the UTF-16 name of the variable in the pstore record's priv field. That way, we don't have to make guesses regarding which variable the record may have been loaded from.
--- drivers/firmware/efi/Kconfig | 1 + drivers/firmware/efi/efi-pstore.c | 374 +++++--------------- drivers/firmware/efi/efivars.c | 12 +- drivers/firmware/efi/vars.c | 12 +- include/linux/efi.h | 2 - 5 files changed, 91 insertions(+), 310 deletions(-)
drivers/firmware/efi/Kconfig +1 -0
@@ -22,6 +22,7 @@ config EFI_ESRT config EFI_VARS_PSTORE tristate "Register efivars backend for pstore" depends on PSTORE + select UCS2_STRING default y help Say Y here to enable use efivars as a backend to pstore. This
drivers/firmware/efi/efi-pstore.c +84 -290
461 lines not on this page · raw message
drivers/firmware/efi/efivars.c +4 -8
@@ -467,16 +467,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,else if (__efivar_entry_delete (entry)) err = -EIO ; -if (err) { -efivar_entry_iter_end (); +efivar_entry_iter_end (); + +if (err)return err; - } -if (!entry->scanning) { -efivar_entry_iter_end (); -efivar_unregister (entry); - }else -efivar_entry_iter_end (); +efivar_unregister (entry);/* It's dead Jim.... */ return count;
drivers/firmware/efi/vars.c +2 -10
@@ -821,16 +821,8 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,if (!found)return NULL ; -if (remove) { -if (entry->scanning) { -/* -* The entry will be deleted -* after scanning is completed. -*/ - entry->deleting = true; - }else -list_del (&entry->list); - } +if (remove) +list_del (&entry->list);return entry; }
include/linux/efi.h +0 -2
@@ -1043,8 +1043,6 @@ struct efivar_entry {struct efi_variable var;struct list_head list;struct kobject kobj; -bool scanning; -bool deleting; }; static inline void
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 5/9 efi: vars: Use locking version to iterate over efivars linked lists
In reply to Ard BiesheuvelBoth efivars and efivarfs uses __efivar_entry_iter() to go over the linked list that shadows the list of EFI variables held by the firmware, but fail to call the begin/end helpers that are documented as a prerequisite.
So switch to the proper version, which is efivar_entry_iter(). Given that in both cases, efivar_entry_remove() is invoked with the lock held already, don't take the lock there anymore.
--- drivers/firmware/efi/efivars.c | 8 ++------ drivers/firmware/efi/vars.c | 9 +-------- fs/efivarfs/super.c | 9 +++------ include/linux/efi.h | 2 +- 4 files changed, 7 insertions(+), 21 deletions(-)
drivers/firmware/efi/efivars.c +2 -6
@@ -602,10 +602,7 @@ static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,static int efivar_sysfs_destroy (struct efivar_entry *entry,void *data) { -int err =efivar_entry_remove (entry); - -if (err) -return err; +efivar_entry_remove (entry);efivar_unregister (entry);return 0 ; }
@@ -615,8 +612,7 @@ static void efivars_sysfs_exit(void)/* Remove all entries and destroy */ int err; - err =__efivar_entry_iter (efivar_sysfs_destroy, &efivar_sysfs_list, -NULL ,NULL ); + err =efivar_entry_iter (efivar_sysfs_destroy, &efivar_sysfs_list,NULL );if (err) {pr_err ("efivars: Failed to destroy sysfs entries\n" );return ;
drivers/firmware/efi/vars.c +1 -8
@@ -523,17 +523,10 @@ EXPORT_SYMBOL_GPL(__efivar_entry_add);/** * efivar_entry_remove - remove entry from variable list * @entry: entry to remove from list -* -* Returns 0 on success, or a kernel error code on failure. */ -int efivar_entry_remove (struct efivar_entry *entry) +void efivar_entry_remove (struct efivar_entry *entry) { -if (down_interruptible (&efivars_lock)) -return -EINTR ;list_del (&entry->list); -up (&efivars_lock); - -return 0 ; }EXPORT_SYMBOL_GPL (efivar_entry_remove);
fs/efivarfs/super.c +3 -6
@@ -180,10 +180,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,static int efivarfs_destroy (struct efivar_entry *entry,void *data) { -int err =efivar_entry_remove (entry); - -if (err) -return err; +efivar_entry_remove (entry);kfree (entry);return 0 ; }
@@ -219,7 +216,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc) err =efivar_init (efivarfs_callback, (void *)sb, true, &efivarfs_list);if (err) -__efivar_entry_iter (efivarfs_destroy, &efivarfs_list,NULL ,NULL ); +efivar_entry_iter (efivarfs_destroy, &efivarfs_list,NULL );return err; }
@@ -244,7 +241,7 @@ static void efivarfs_kill_sb(struct super_block *sb)kill_litter_super (sb);/* Remove all entries and destroy */ -__efivar_entry_iter (efivarfs_destroy, &efivarfs_list,NULL ,NULL ); +efivar_entry_iter (efivarfs_destroy, &efivarfs_list,NULL ); }static struct file_system_type efivarfs_type = {
include/linux/efi.h +1 -1
@@ -1063,7 +1063,7 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),int efivar_entry_add (struct efivar_entry *entry,struct list_head *head);void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head); -int efivar_entry_remove (struct efivar_entry *entry); +void efivar_entry_remove (struct efivar_entry *entry);int __efivar_entry_delete (struct efivar_entry *entry);int efivar_entry_delete (struct efivar_entry *entry);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 6/9 efi: vars: Drop __efivar_entry_iter() helper which is no longer used
In reply to Ard Biesheuvel__efivar_entry_iter() uses a list iterator in a dubious way, i.e., it assumes that the iteration variable always points to an object of the appropriate type, even if the list traversal exhausts the list completely, in which case it will point somewhere in the vicinity of the list's anchor instead.
Fortunately, we no longer use this function so we can just get rid of it entirely.
--- drivers/firmware/efi/vars.c | 61 +++----------------- include/linux/efi.h | 3 - 2 files changed, 7 insertions(+), 57 deletions(-)
drivers/firmware/efi/vars.c +7 -54
@@ -1034,59 +1034,6 @@ void efivar_entry_iter_end(void) }EXPORT_SYMBOL_GPL (efivar_entry_iter_end); -/** -* __efivar_entry_iter - iterate over variable list -* @func: callback function -* @head: head of the variable list -* @data: function-specific data to pass to callback -* @prev: entry to begin iterating from -* -* Iterate over the list of EFI variables and call @func with every -* entry on the list. It is safe for @func to remove entries in the -* list via efivar_entry_delete(). -* -* You MUST call efivar_entry_iter_begin() before this function, and -* efivar_entry_iter_end() afterwards. -* -* It is possible to begin iteration from an arbitrary entry within -* the list by passing @prev. @prev is updated on return to point to -* the last entry passed to @func. To begin iterating from the -* beginning of the list @prev must be %NULL. -* -* The restrictions for @func are the same as documented for -* efivar_entry_iter(). -*/ -int __efivar_entry_iter (int (*func)(struct efivar_entry *,void *), -struct list_head *head,void *data, -struct efivar_entry **prev) -{ -struct efivar_entry *entry, *n; -int err =0 ; - -if (!prev || !*prev) { -list_for_each_entry_safe (entry, n, head, list) { - err =func (entry, data); -if (err) -break ; - } - -if (prev) - *prev = entry; - -return err; - } - - -list_for_each_entry_safe_continue ((*prev), n, head, list) { - err =func (*prev, data); -if (err) -break ; - } - -return err; -} -EXPORT_SYMBOL_GPL (__efivar_entry_iter); -/** * efivar_entry_iter - iterate over variable list * @func: callback function
@@ -1104,12 +1051,18 @@ EXPORT_SYMBOL_GPL(__efivar_entry_iter);int efivar_entry_iter (int (*func)(struct efivar_entry *,void *),struct list_head *head,void *data) { +struct efivar_entry *entry, *n;int err =0 ; err =efivar_entry_iter_begin ();if (err)return err; - err =__efivar_entry_iter (func, head, data,NULL ); + +list_for_each_entry_safe (entry, n, head, list) { + err =func (entry, data); +if (err) +break ; + }efivar_entry_iter_end ();return err;
include/linux/efi.h +0 -3
@@ -1083,9 +1083,6 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,int efivar_entry_iter_begin (void );void efivar_entry_iter_end (void ); -int __efivar_entry_iter (int (*func)(struct efivar_entry *,void *), -struct list_head *head,void *data, -struct efivar_entry **prev);int efivar_entry_iter (int (*func)(struct efivar_entry *,void *),struct list_head *head,void *data);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 7/9 efi: vars: Remove deprecated 'efivars' sysfs interface
In reply to Ard BiesheuvelCommit 5d9db883761a ("efi: Add support for a UEFI variable filesystem") dated Oct 5, 2012, introduced a new efivarfs pseudo-filesystem to replace the efivars sysfs interface that was used up to that point to expose EFI variables to user space.
The main problem with the sysfs interface was that it only supported up to 1024 bytes of payload per file, whereas the underlying variables themselves are only bounded by a platform specific per-variable and global limit that is typically much higher than 1024 bytes.
The deprecated sysfs interface is only enabled on x86 and Itanium, other EFI enabled architectures only support the efivarfs pseudo-filesystem.
So let's finally rip off the band aid, and drop the old interface entirely. This will make it easier to refactor and clean up the underlying infrastructure that is shared between efivars, efivarfs and efi-pstore, and is long overdue for a makeover.
--- Documentation/x86/x86_64/uefi.rst | 2 +- arch/arm/configs/milbeaut_m10v_defconfig | 1 - arch/ia64/configs/bigsur_defconfig | 1 - arch/ia64/configs/generic_defconfig | 1 - arch/ia64/configs/gensparse_defconfig | 1 - arch/ia64/configs/tiger_defconfig | 1 - arch/ia64/configs/zx1_defconfig | 1 - arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - drivers/firmware/efi/Kconfig | 12 - drivers/firmware/efi/Makefile | 1 - drivers/firmware/efi/efivars.c | 660 -------------------- drivers/firmware/efi/vars.c | 265 +------- include/linux/efi.h | 18 - 14 files changed, 3 insertions(+), 963 deletions(-)
Documentation/x86/x86_64/uefi.rst +1 -1
@@ -29,7 +29,7 @@ Mechanics be selected:: CONFIG_EFI=y - CONFIG_EFI_VARS=y or m # optional + CONFIG_EFIVAR_FS=y or m # optional - Create a VFAT partition on the disk - Copy the following to the VFAT partition:
arch/arm/configs/milbeaut_m10v_defconfig +0 -1
@@ -44,7 +44,6 @@ CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_KERNEL_MODE_NEON=y -CONFIG_EFI_VARS=m CONFIG_EFI_CAPSULE_LOADER=m CONFIG_ARM_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM_NEON=m
arch/ia64/configs/bigsur_defconfig +0 -1
@@ -10,7 +10,6 @@ CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m
arch/ia64/configs/generic_defconfig +0 -1
@@ -21,7 +21,6 @@ CONFIG_IA64_MCA_RECOVERY=y CONFIG_IA64_PALINFO=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y -CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m
arch/ia64/configs/gensparse_defconfig +0 -1
@@ -18,7 +18,6 @@ CONFIG_HOTPLUG_CPU=y CONFIG_SPARSEMEM_MANUAL=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m
arch/ia64/configs/tiger_defconfig +0 -1
@@ -23,7 +23,6 @@ CONFIG_FORCE_CPEI_RETARGET=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_IA64_PALINFO=y CONFIG_KEXEC=y -CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m
arch/ia64/configs/zx1_defconfig +0 -1
@@ -12,7 +12,6 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_IA64_PALINFO=y CONFIG_CRASH_DUMP=y -CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_ACPI=y
arch/x86/configs/i386_defconfig +0 -1
@@ -135,7 +135,6 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y -CONFIG_EFI_VARS=y CONFIG_EFI_CAPSULE_LOADER=y CONFIG_BLK_DEV_LOOP=y CONFIG_VIRTIO_BLK=y
arch/x86/configs/x86_64_defconfig +0 -1
@@ -134,7 +134,6 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y -CONFIG_EFI_VARS=y CONFIG_BLK_DEV_LOOP=y CONFIG_VIRTIO_BLK=y CONFIG_BLK_DEV_SD=y
drivers/firmware/efi/Kconfig +0 -12
@@ -2,18 +2,6 @@ menu "EFI (Extensible Firmware Interface) Support" depends on EFI -config EFI_VARS - tristate "EFI Variable Support via sysfs" - depends on EFI && (X86 || IA64) - default n - help - If you say Y here, you are able to get EFI (Extensible Firmware - Interface) variable information via sysfs. You may read, - write, create, and destroy EFI variables through this interface. - Note that this driver is only retained for compatibility with - legacy users: new users should use the efivarfs filesystem - instead. - config EFI_ESRT bool depends on EFI && !IA64
drivers/firmware/efi/Makefile +0 -1
@@ -17,7 +17,6 @@ ifneq ($(CONFIG_EFI_CAPSULE_LOADER),) obj-$(CONFIG_EFI) += capsule.o endif obj-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdtparams.o -obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_ESRT) += esrt.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o obj-$(CONFIG_UEFI_CPER) += cper.o
drivers/firmware/efi/efivars.c deleted +0 -660
660 lines not on this page · raw message
drivers/firmware/efi/vars.c +2 -263
295 lines not on this page · raw message
include/linux/efi.h +0 -18
@@ -1045,12 +1045,6 @@ struct efivar_entry {struct kobject kobj; }; -static inline void -efivar_unregister (struct efivar_entry *var) -{ -kobject_put (&var->kobj); -} -int efivars_register (struct efivars *efivars,const struct efivar_operations *ops,struct kobject *kobject);
@@ -1064,8 +1058,6 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),int efivar_entry_add (struct efivar_entry *entry,struct list_head *head);void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head);void efivar_entry_remove (struct efivar_entry *entry); - -int __efivar_entry_delete (struct efivar_entry *entry);int efivar_entry_delete (struct efivar_entry *entry);int efivar_entry_size (struct efivar_entry *entry,unsigned long *size);
@@ -1073,22 +1065,12 @@ int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes, unsigned long *size, void *data);int efivar_entry_get (struct efivar_entry *entry,u32 *attributes,unsigned long *size,void *data); -int efivar_entry_set (struct efivar_entry *entry,u32 attributes, -unsigned long size,void *data,struct list_head *head);int efivar_entry_set_get_size (struct efivar_entry *entry,u32 attributes,unsigned long *size,void *data,bool *set); -int efivar_entry_set_safe (efi_char16_t *name,efi_guid_t vendor,u32 attributes, -bool block,unsigned long size,void *data); - -int efivar_entry_iter_begin (void ); -void efivar_entry_iter_end (void );int efivar_entry_iter (int (*func)(struct efivar_entry *,void *),struct list_head *head,void *data); -struct efivar_entry *efivar_entry_find (efi_char16_t *name,efi_guid_t guid, -struct list_head *head,bool remove); -bool efivar_validate (efi_guid_t vendor,efi_char16_t *var_name,u8 *data,unsigned long data_size); bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 8/9 efi: vars: Switch to new wrapper layer
In reply to Ard BiesheuvelSwitch the caching linked-list efivars layer implementation to the newly introduced efivar get/set variable wrappers, instead of accessing the lock and the ops pointer directly. This will permit us to move this code out of the public efivars API, and into efivarfs once the obsolete sysfs access method is finally removed.
--- drivers/firmware/efi/vars.c | 133 ++++++++------------ 1 file changed, 52 insertions(+), 81 deletions(-)
drivers/firmware/efi/vars.c +52 -81
@@ -408,28 +408,21 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,int efivar_init (int (*func)(efi_char16_t *,efi_guid_t ,unsigned long ,void *),void *data,bool duplicates,struct list_head *head) { -const struct efivar_operations *ops;unsigned long variable_name_size =1024 ;efi_char16_t *variable_name;efi_status_t status;efi_guid_t vendor_guid;int err =0 ; -if (!__efivars) -return -EFAULT ; - - ops = __efivars->ops; - variable_name =kzalloc (variable_name_size,GFP_KERNEL );if (!variable_name) {printk (KERN_ERR "efivars: Memory allocation failed.\n" );return -ENOMEM ; } -if (down_interruptible (&efivars_lock)) { - err = -EINTR ; + err =efivar_lock (); +if (err) goto free; - }/* * Per EFI spec, the maximum storage allocated for both
@@ -439,9 +432,9 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), do { variable_name_size = 1024; - status = ops->get_next_variable(&variable_name_size, - variable_name, - &vendor_guid); + status = efivar_get_next_variable(&variable_name_size, + variable_name, + &vendor_guid); switch (status) { case EFI_SUCCESS: variable_name_size = var_name_strnsize(variable_name,
@@ -483,7 +476,7 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), }while (status !=EFI_NOT_FOUND ); -up (&efivars_lock); +efivar_unlock (); free:kfree (variable_name);
@@ -500,10 +493,13 @@ EXPORT_SYMBOL_GPL(efivar_init);*/ int efivar_entry_add (struct efivar_entry *entry,struct list_head *head) { -if (down_interruptible (&efivars_lock)) -return -EINTR ; +int err; + + err =efivar_lock (); +if (err) +return err;list_add (&entry->list, head); -up (&efivars_lock); +efivar_unlock ();return 0 ; }
@@ -544,7 +540,7 @@ EXPORT_SYMBOL_GPL(efivar_entry_remove);static void efivar_entry_list_del_unlock (struct efivar_entry *entry) {list_del (&entry->list); -up (&efivars_lock); +efivar_unlock (); }/**
@@ -560,22 +556,18 @@ static void efivar_entry_list_del_unlock(struct efivar_entry *entry)*/ int efivar_entry_delete (struct efivar_entry *entry) { -const struct efivar_operations *ops;efi_status_t status; +int err; -if (down_interruptible (&efivars_lock)) -return -EINTR ; + err =efivar_lock (); +if (err) +return err; -if (!__efivars) { -up (&efivars_lock); -return -EINVAL ; - } - ops = __efivars->ops; - status = ops->set_variable (entry->var.VariableName, - &entry->var.VendorGuid, -0 ,0 ,NULL ); + status =efivar_set_variable_locked (entry->var.VariableName, + &entry->var.VendorGuid, +0 ,0 ,NULL , false);if (!(status ==EFI_SUCCESS || status ==EFI_NOT_FOUND )) { -up (&efivars_lock); +efivar_unlock ();return efi_status_to_err (status); }
@@ -591,21 +583,18 @@ EXPORT_SYMBOL_GPL(efivar_entry_delete);*/ int efivar_entry_size (struct efivar_entry *entry,unsigned long *size) { -const struct efivar_operations *ops;efi_status_t status; +int err; *size =0 ; -if (down_interruptible (&efivars_lock)) -return -EINTR ; -if (!__efivars) { -up (&efivars_lock); -return -EINVAL ; - } - ops = __efivars->ops; - status = ops->get_variable (entry->var.VariableName, - &entry->var.VendorGuid,NULL , size,NULL ); -up (&efivars_lock); + err =efivar_lock (); +if (err) +return err; + + status =efivar_get_variable (entry->var.VariableName, + &entry->var.VendorGuid,NULL , size,NULL ); +efivar_unlock ();if (status !=EFI_BUFFER_TOO_SMALL )return efi_status_to_err (status);
@@ -621,21 +610,16 @@ EXPORT_SYMBOL_GPL(efivar_entry_size);* @size: size of @data buffer * @data: buffer to store variable data * -* The caller MUST call efivar_entry_iter_begin() and -* efivar_entry_iter_end() before and after the invocation of this -* function, respectively. +* The caller MUST hold the efivar lock when calling this function. */ int __efivar_entry_get (struct efivar_entry *entry,u32 *attributes,unsigned long *size,void *data) {efi_status_t status; -if (!__efivars) -return -EINVAL ; - - status = __efivars->ops->get_variable (entry->var.VariableName, - &entry->var.VendorGuid, - attributes, size, data); + status =efivar_get_variable (entry->var.VariableName, + &entry->var.VendorGuid, + attributes, size, data);return efi_status_to_err (status); }
@@ -651,22 +635,15 @@ EXPORT_SYMBOL_GPL(__efivar_entry_get);int efivar_entry_get (struct efivar_entry *entry,u32 *attributes,unsigned long *size,void *data) { -efi_status_t status; - -if (down_interruptible (&efivars_lock)) -return -EINTR ; - -if (!__efivars) { -up (&efivars_lock); -return -EINVAL ; - } +int err; - status = __efivars->ops->get_variable (entry->var.VariableName, - &entry->var.VendorGuid, - attributes, size, data); -up (&efivars_lock); + err =efivar_lock (); +if (err) +return err; + err =__efivar_entry_get (entry, attributes, size, data); +efivar_unlock (); -return efi_status_to_err (status); +return err; }EXPORT_SYMBOL_GPL (efivar_entry_get);
@@ -695,7 +672,6 @@ EXPORT_SYMBOL_GPL(efivar_entry_get);int efivar_entry_set_get_size (struct efivar_entry *entry,u32 attributes,unsigned long *size,void *data,bool *set) { -const struct efivar_operations *ops;efi_char16_t *name = entry->var.VariableName;efi_guid_t *vendor = &entry->var.VendorGuid;efi_status_t status;
@@ -711,13 +687,9 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,* set_variable call, and removal of the variable from the efivars * list (in the case of an authenticated delete). */ -if (down_interruptible (&efivars_lock)) -return -EINTR ; - -if (!__efivars) { - err = -EINVAL ; - goto out; - } + err =efivar_lock (); +if (err) +return err;/* * Ensure that the available space hasn't shrunk below the safe level
@@ -735,9 +707,8 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes, } } - ops = __efivars->ops; - - status = ops->set_variable (name, vendor, attributes, *size, data); + status =efivar_set_variable_locked (name, vendor, attributes, *size, + data, false);if (status !=EFI_SUCCESS ) { err =efi_status_to_err (status); goto out;
@@ -752,14 +723,14 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,* happened. */ *size =0 ; - status = ops->get_variable (entry->var.VariableName, - &entry->var.VendorGuid, -NULL , size,NULL ); + status =efivar_get_variable (entry->var.VariableName, + &entry->var.VendorGuid, +NULL , size,NULL );if (status ==EFI_NOT_FOUND )efivar_entry_list_del_unlock (entry);else -up (&efivars_lock); +efivar_unlock ();if (status && status !=EFI_BUFFER_TOO_SMALL )return efi_status_to_err (status);
@@ -767,7 +738,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,return 0 ; out: -up (&efivars_lock); +efivar_unlock ();return err; }
@@ -793,7 +764,7 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),struct efivar_entry *entry, *n;int err =0 ; - err =down_interruptible (&efivars_lock); + err =efivar_lock ();if (err)return err;
@@ -802,7 +773,7 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),if (err)break ; } -up (&efivars_lock); +efivar_unlock ();return err; }
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH v3 9/9 efi: vars: Move efivar caching layer into efivarfs
In reply to Ard BiesheuvelMove the fiddly bits of the efivar layer into its only remaining user, efivarfs, and confine its use to that particular module. All other uses of the EFI variable store have no need for this additional layer of complexity, given that they either only read variables, or read and write variables into a separate GUIDed namespace, and cannot be used to manipulate EFI variables that are covered by the EFI spec and/or affect the boot flow.
--- drivers/firmware/efi/efi.c | 1 + drivers/firmware/efi/vars.c | 733 ------------------- fs/efivarfs/Makefile | 2 +- fs/efivarfs/internal.h | 40 ++ fs/efivarfs/vars.c | 738 ++++++++++++++++++++ include/linux/efi.h | 38 - 6 files changed, 780 insertions(+), 772 deletions(-)
drivers/firmware/efi/efi.c +1 -0
@@ -899,6 +899,7 @@ int efi_status_to_err(efi_status_t status)return err; } +EXPORT_SYMBOL_GPL (efi_status_to_err);static DEFINE_SPINLOCK (efi_mem_reserve_persistent_lock);static struct linux_efi_memreserve *efi_memreserve_root__ro_after_init ;
drivers/firmware/efi/vars.c +0 -733
759 lines not on this page · raw message
fs/efivarfs/Makefile +1 -1
@@ -5,4 +5,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs.o -efivarfs-objs := inode.o file.o super.o +efivarfs-objs := inode.o file.o super.o vars.o
fs/efivarfs/internal.h +40 -0
@@ -7,6 +7,46 @@#define EFIVAR_FS_INTERNAL_H #include <linux/list.h> +#include <linux/efi.h> + +struct efi_variable { +efi_char16_t VariableName[EFI_VAR_NAME_LEN /sizeof (efi_char16_t)]; +efi_guid_t VendorGuid; +unsigned long DataSize; +__u8 Data[1024 ]; +efi_status_t Status; +__u32 Attributes; +} __attribute__((packed)); + +struct efivar_entry { +struct efi_variable var; +struct list_head list; +struct kobject kobj; +}; + +int efivar_init (int (*func)(efi_char16_t *,efi_guid_t ,unsigned long ,void *), +void *data,bool duplicates,struct list_head *head); + +int efivar_entry_add (struct efivar_entry *entry,struct list_head *head); +void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head); +void efivar_entry_remove (struct efivar_entry *entry); +int efivar_entry_delete (struct efivar_entry *entry); + +int efivar_entry_size (struct efivar_entry *entry,unsigned long *size); +int __efivar_entry_get (struct efivar_entry *entry,u32 *attributes, +unsigned long *size,void *data); +int efivar_entry_get (struct efivar_entry *entry,u32 *attributes, +unsigned long *size,void *data); +int efivar_entry_set_get_size (struct efivar_entry *entry,u32 attributes, +unsigned long *size,void *data,bool *set); + +int efivar_entry_iter (int (*func)(struct efivar_entry *,void *), +struct list_head *head,void *data); + +bool efivar_validate (efi_guid_t vendor,efi_char16_t *var_name,u8 *data, +unsigned long data_size); +bool efivar_variable_is_removable (efi_guid_t vendor,const char *name, +size_t len);extern const struct file_operations efivarfs_file_operations;extern const struct inode_operations efivarfs_dir_inode_operations;
fs/efivarfs/vars.c new file +738 -0
738 lines not on this page · raw message
include/linux/efi.h +0 -38
@@ -1030,21 +1030,6 @@ struct efivars {#define EFI_VAR_NAME_LEN 1024 -struct efi_variable { -efi_char16_t VariableName[EFI_VAR_NAME_LEN /sizeof (efi_char16_t)]; -efi_guid_t VendorGuid; -unsigned long DataSize; -__u8 Data[1024 ]; -efi_status_t Status; -__u32 Attributes; -} __attribute__((packed)); - -struct efivar_entry { -struct efi_variable var; -struct list_head list; -struct kobject kobj; -}; -int efivars_register (struct efivars *efivars,const struct efivar_operations *ops,struct kobject *kobject);
@@ -1052,29 +1037,6 @@ int efivars_unregister(struct efivars *efivars);struct kobject *efivars_kobject (void );int efivar_supports_writes (void ); -int efivar_init (int (*func)(efi_char16_t *,efi_guid_t ,unsigned long ,void *), -void *data,bool duplicates,struct list_head *head); - -int efivar_entry_add (struct efivar_entry *entry,struct list_head *head); -void __efivar_entry_add (struct efivar_entry *entry,struct list_head *head); -void efivar_entry_remove (struct efivar_entry *entry); -int efivar_entry_delete (struct efivar_entry *entry); - -int efivar_entry_size (struct efivar_entry *entry,unsigned long *size); -int __efivar_entry_get (struct efivar_entry *entry,u32 *attributes, -unsigned long *size,void *data); -int efivar_entry_get (struct efivar_entry *entry,u32 *attributes, -unsigned long *size,void *data); -int efivar_entry_set_get_size (struct efivar_entry *entry,u32 attributes, -unsigned long *size,void *data,bool *set); - -int efivar_entry_iter (int (*func)(struct efivar_entry *,void *), -struct list_head *head,void *data); - -bool efivar_validate (efi_guid_t vendor,efi_char16_t *var_name,u8 *data, -unsigned long data_size); -bool efivar_variable_is_removable (efi_guid_t vendor,const char *name, -size_t len);int efivar_lock (void );int efivar_trylock (void );
Signature · 1 line
2.35.1