The barebox efivarfs is currently only registered when barebox is an EFI payload. It hardcodes use of RT to access the runtime services and the efivarfs is mounted on every startup.
Replace this with an automount and rework the file system slightly, so the file system can be mounted later outside of payload once barebox activates the upcoming EFI loader support. Signed-off-by: Ahmad Fatoum <[email protected]> --- common/startup.c | 4 ++-- efi/efivar.c | 1 + fs/Kconfig | 2 +- fs/efivarfs.c | 38 ++++++++++++++++++++++++++++---------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/common/startup.c b/common/startup.c index 602233345a25..c48adb42f953 100644 --- a/common/startup.c +++ b/common/startup.c @@ -62,9 +62,9 @@ static int mount_root(void) mkdir("/mnt", 0); devfs_init(); - if (IS_ENABLED(CONFIG_FS_EFIVARFS) && efi_is_payload()) { + if (IS_ENABLED(CONFIG_FS_EFIVARFS)) { mkdir("/efivars", 0); - mount("none", "efivarfs", "/efivars", NULL); + automount_add("/efivars", "mount -t efivarfs none /efivars"); } if (IS_ENABLED(CONFIG_FS_PSTORE)) { diff --git a/efi/efivar.c b/efi/efivar.c index a51f3b2d1d8e..808693a7a746 100644 --- a/efi/efivar.c +++ b/efi/efivar.c @@ -14,6 +14,7 @@ #include <efi/variable.h> #include <wchar.h> #include <xfuncs.h> +#include <errno.h> #include <linux/sprintf.h> void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size) diff --git a/fs/Kconfig b/fs/Kconfig index e86420f9c259..c0c634bb419d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -94,7 +94,7 @@ config FS_EFI by the EFI Firmware via the EFI Simple File System Protocol. config FS_EFIVARFS - depends on EFI_PAYLOAD + depends on EFI select FS_LEGACY select FS_WRITABLE bool diff --git a/fs/efivarfs.c b/fs/efivarfs.c index 7b80e703f2d9..3641dd92917d 100644 --- a/fs/efivarfs.c +++ b/fs/efivarfs.c @@ -25,6 +25,7 @@ #include <xfuncs.h> #include <fcntl.h> #include <efi.h> +#include <efi/efi-mode.h> #include <wchar.h> #include <linux/err.h> #include <linux/ctype.h> @@ -45,12 +46,14 @@ struct efivarfs_dir { struct efivarfs_priv { struct list_head inodes; + struct efi_runtime_services *rt; }; static int efivars_create(struct device *dev, const char *pathname, mode_t mode) { struct efivarfs_priv *priv = dev->priv; + struct efi_runtime_services *rt = priv->rt; struct efivarfs_inode *inode; efi_guid_t vendor; efi_status_t efiret; @@ -79,7 +82,7 @@ static int efivars_create(struct device *dev, const char *pathname, inode->full_name = basprintf("%s-%pUl", name8, &inode->vendor); free(name8); - efiret = RT->set_variable(inode->name, &inode->vendor, + efiret = rt->set_variable(inode->name, &inode->vendor, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, @@ -97,6 +100,7 @@ static int efivars_create(struct device *dev, const char *pathname, static int efivars_unlink(struct device *dev, const char *pathname) { struct efivarfs_priv *priv = dev->priv; + struct efi_runtime_services *rt = priv->rt; struct efivarfs_inode *inode, *tmp; efi_status_t efiret; @@ -105,7 +109,7 @@ static int efivars_unlink(struct device *dev, const char *pathname) list_for_each_entry_safe(inode, tmp, &priv->inodes, node) { if (!strcmp(inode->full_name, pathname)) { - efiret = RT->set_variable(inode->name, &inode->vendor, + efiret = rt->set_variable(inode->name, &inode->vendor, 0, 0, NULL); if (EFI_ERROR(efiret)) return -efi_errno(efiret); @@ -123,10 +127,13 @@ struct efivars_file { efi_guid_t vendor; s16 *name; u32 attributes; + struct efivarfs_priv *priv; }; static int efivarfs_open(struct device *dev, struct file *f, const char *filename) { + struct efivarfs_priv *priv = dev->priv; + struct efi_runtime_services *rt = priv->rt; struct efivars_file *efile; efi_status_t efiret; int ret; @@ -137,7 +144,7 @@ static int efivarfs_open(struct device *dev, struct file *f, const char *filenam if (ret) return -ENOENT; - efiret = RT->get_variable(efile->name, &efile->vendor, + efiret = rt->get_variable(efile->name, &efile->vendor, NULL, &efile->size, NULL); if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) { ret = -efi_errno(efiret); @@ -150,7 +157,7 @@ static int efivarfs_open(struct device *dev, struct file *f, const char *filenam goto out; } - efiret = RT->get_variable(efile->name, &efile->vendor, + efiret = rt->get_variable(efile->name, &efile->vendor, &efile->attributes, &efile->size, efile->buf); if (EFI_ERROR(efiret)) { @@ -158,6 +165,8 @@ static int efivarfs_open(struct device *dev, struct file *f, const char *filenam goto out; } + efile->priv = priv; + f->f_size = efile->size; f->private_data = efile; @@ -192,6 +201,7 @@ static int efivarfs_read(struct file *f, void *buf, size_t insize) static int efivarfs_write(struct file *f, const void *buf, size_t insize) { struct efivars_file *efile = f->private_data; + struct efi_runtime_services *rt = efile->priv->rt; efi_status_t efiret; if (efile->size < f->f_pos + insize) { @@ -201,7 +211,7 @@ static int efivarfs_write(struct file *f, const void *buf, size_t insize) memcpy(efile->buf + f->f_pos, buf, insize); - efiret = RT->set_variable(efile->name, &efile->vendor, + efiret = rt->set_variable(efile->name, &efile->vendor, efile->attributes, efile->size ? efile->size : 1, efile->buf); if (EFI_ERROR(efiret)) @@ -213,12 +223,13 @@ static int efivarfs_write(struct file *f, const void *buf, size_t insize) static int efivarfs_truncate(struct file *f, loff_t size) { struct efivars_file *efile = f->private_data; + struct efi_runtime_services *rt = efile->priv->rt; efi_status_t efiret; efile->size = size; efile->buf = realloc(efile->buf, efile->size + sizeof(uint32_t)); - efiret = RT->set_variable(efile->name, &efile->vendor, + efiret = rt->set_variable(efile->name, &efile->vendor, efile->attributes, efile->size ? efile->size : 1, efile->buf); if (EFI_ERROR(efiret)) @@ -268,6 +279,8 @@ static int efivarfs_closedir(struct device *dev, DIR *dir) static int efivarfs_stat(struct device *dev, const char *filename, struct stat *s) { + struct efivarfs_priv *priv = dev->priv; + struct efi_runtime_services *rt = priv->rt; efi_guid_t vendor; s16 *name; efi_status_t efiret; @@ -278,7 +291,7 @@ static int efivarfs_stat(struct device *dev, const char *filename, if (ret) return -ENOENT; - efiret = RT->get_variable(name, &vendor, NULL, &size, NULL); + efiret = rt->get_variable(name, &vendor, NULL, &size, NULL); free(name); @@ -299,17 +312,23 @@ static int efivarfs_probe(struct device *dev) char *name8; size_t size; struct efivarfs_priv *priv; + struct efi_runtime_services *rt; + + rt = efi_get_runtime_services(); + if (!rt) + return -ENODEV; name[0] = 0; priv = xzalloc(sizeof(*priv)); + priv->rt = rt; INIT_LIST_HEAD(&priv->inodes); while (1) { struct efivarfs_inode *inode; size = sizeof(name); - efiret = RT->get_next_variable(&size, name, &vendor); + efiret = rt->get_next_variable(&size, name, &vendor); if (EFI_ERROR(efiret)) break; @@ -370,5 +389,4 @@ static int efivarfs_init(void) { return register_fs_driver(&efivarfs_driver); } - -coredevice_efi_initcall(efivarfs_init); +coredevice_initcall(efivarfs_init); -- 2.47.3
