lib/efi: Add new struct efi_mount
authorGeoff Levand <geoff@infradead.org>
Fri, 10 Aug 2018 17:29:14 +0000 (17:29 +0000)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 14 Aug 2018 01:12:02 +0000 (11:12 +1000)
To make it easier to manage EFI variables add a new struct efi_mount
that holds the path to the EFI file system mount and the EFI variable
name GUID. Update the lib/efi routines to use struct efi_mount.  Add
a new routine efi_check_mount based on the checks done in
platform-arm64.

This change to using struct efi_mount removes the static variable
efivarfs_path making the lib/efi routines stateless.

Signed-off-by: Geoff Levand <geoff@infradead.org>
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
lib/efi/efivar.c
lib/efi/efivar.h

index a0c21b5b5d345f3717981a9a8dba67b78382e8e8..f1dd0021cea0c8070a8da86ac303ac07723b82ee 100644 (file)
@@ -17,6 +17,7 @@
  *  Author: Ge Song <ge.song@hxt-semitech.com>
  */
 
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 
 #include "efivar.h"
 #include "log/log.h"
 #include "talloc/talloc.h"
 
-static const char *efivarfs_path;
-
-inline void set_efivarfs_path(const char *path)
+void efi_init_mount(struct efi_mount *efi_mount, const char *path,
+       const char *guid)
 {
-       efivarfs_path = path;
+       assert(efi_mount);
+
+       efi_mount->path = path;
+       efi_mount->guid = guid;
+
+       pb_debug_fn("%s--%s", efi_mount->path, efi_mount->guid);
 }
 
-inline const char *get_efivarfs_path(void)
+bool efi_check_mount_magic(const struct efi_mount *efi_mount, bool check_magic)
 {
+       struct statfs s;
 
-       return efivarfs_path;
+       assert(efi_mount);
+
+       if (!efi_mount->guid) {
+               pb_debug_fn("guid not set\n");
+               return false;
+       }
+
+       if (access(efi_mount->path, R_OK | W_OK)) {
+               pb_debug_fn("Can't access %s\n", efi_mount->path);
+               return false;
+       }
+
+       memset(&s, '\0', sizeof(s));
+       if (statfs(efi_mount->path, &s)) {
+               pb_debug_fn("statfs failed: %s: (%d) %s\n", efi_mount->path,
+                       errno, strerror(errno));
+               return false;
+       }
+
+       if (check_magic && s.f_type != EFIVARFS_MAGIC) {
+               pb_debug_fn("Bad magic = 0x%lx\n", (unsigned long)s.f_type);
+               return false;
+       }
+
+       return true;
 }
 
-static int efi_open(const char *name, const char *guidstr, int flags,
-       mode_t mode, char **path)
+static int efi_open(const struct efi_mount *efi_mount, const char *name,
+       int flags, mode_t mode, char **path)
 {
        int fd;
 
+       assert(efi_mount);
+
        *path = NULL;
 
-       if (!get_efivarfs_path())
+       if (!efi_mount->path || !efi_mount->guid)
                return -1;
 
-       *path = talloc_asprintf(NULL, "%s%s-%s", get_efivarfs_path(), name, guidstr);
+       *path = talloc_asprintf(NULL, "%s/%s-%s", efi_mount->path, name,
+               efi_mount->guid);
        if (!*path)
                return -1;
 
@@ -62,8 +96,8 @@ static int efi_open(const char *name, const char *guidstr, int flags,
        fd = open(*path, flags, mode);
 
        if (fd < 0) {
-               pb_log("%s: open failed %s: %s\n", __func__, *path,
-                       strerror(errno));
+               pb_log("%s: open failed '%s': (%d) %s\n", __func__, *path,
+                       errno, strerror(errno));
                talloc_free(*path);
                *path = NULL;
                return -1;
@@ -72,20 +106,22 @@ static int efi_open(const char *name, const char *guidstr, int flags,
        return fd;
 }
 
-int efi_del_variable(const char *guidstr, const char *name)
+int efi_del_variable(const struct efi_mount *efi_mount, const char *name)
 {
        int fd, flag;
        int rc = -1;
        char *path;
 
-       fd = efi_open(name, guidstr, 0, 0, &path);
+       assert(efi_mount);
+
+       fd = efi_open(efi_mount, name, 0, 0, &path);
        if (fd < 0)
                return -1;
 
        rc = ioctl(fd, FS_IOC_GETFLAGS, &flag);
        if (rc == -1 && errno == ENOTTY) {
                pb_debug_fn("'%s' does not support ioctl_iflags.\n",
-                       efivarfs_path);
+                       efi_mount->path);
                goto delete;
        } else if (rc == -1) {
                pb_log_fn("FS_IOC_GETFLAGS failed: (%d) %s\n", errno,
@@ -116,8 +152,8 @@ exit:
        return rc;
 }
 
-int efi_get_variable(void *ctx, const char *guidstr, const char *name,
-               struct efi_data **efi_data)
+int efi_get_variable(void *ctx, const struct efi_mount *efi_mount,
+       const char *name, struct efi_data **efi_data)
 {
        int fd;
        int rc = -1;
@@ -127,9 +163,11 @@ int efi_get_variable(void *ctx, const char *guidstr, const char *name,
        ssize_t count;
        char *path;
 
+       assert(efi_mount);
+
        *efi_data = NULL;
 
-       fd = efi_open(name, guidstr, 0, 0, &path);
+       fd = efi_open(efi_mount, name, 0, 0, &path);
        if (fd < 0)
                return -1;
 
@@ -139,8 +177,8 @@ int efi_get_variable(void *ctx, const char *guidstr, const char *name,
                        if (errno == EAGAIN || errno == EWOULDBLOCK)
                                continue;
 
-                       pb_log("%s: read failed %s: (%ld) %s\n", __func__, path,
-                               count, strerror(errno));
+                       pb_log("%s: read failed %s: (%ld) (%d) %s\n", __func__, path,
+                               count, errno, strerror(errno));
                        goto exit;
                }
                if (p >= (buf + sizeof(buf))) {
@@ -169,7 +207,7 @@ exit:
        return rc;
 }
 
-int efi_set_variable(const char *guidstr, const char *name,
+int efi_set_variable(const struct efi_mount *efi_mount, const char *name,
                const struct efi_data *efi_data)
 {
        int rc = -1;
@@ -179,9 +217,11 @@ int efi_set_variable(const char *guidstr, const char *name,
        size_t bufsize;
        char *path;
 
-       efi_del_variable(guidstr, name);
+       assert(efi_mount);
+
+       efi_del_variable(efi_mount, name);
 
-       fd = efi_open(name, guidstr, O_CREAT | O_WRONLY,
+       fd = efi_open(efi_mount, name, O_CREAT | O_WRONLY,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &path);
        if (fd < 0)
                return -1;
@@ -196,8 +236,8 @@ int efi_set_variable(const char *guidstr, const char *name,
 
        count = write(fd, buf, bufsize);
        if ((size_t)count != bufsize) {
-               pb_log("%s: write failed %s: (%ld) %s\n", __func__, name,
-                       count, strerror(errno));
+               pb_log("%s: write failed %s: (%ld) (%d) %s\n", __func__, name,
+                       count, errno, strerror(errno));
                goto exit;
        }
        rc = 0;
index 48edd17a2b0231eacd8649a1566453151b55ed59..b74ab64d254c377d7da6b39766ba29fb398a3157 100644 (file)
 #ifndef EFIVAR_H
 #define EFIVAR_H
 
-#include <linux/magic.h>
+#include <stdbool.h>
 #include <stdint.h>
 
+#include <linux/magic.h>
+
 #define EFI_VARIABLE_NON_VOLATILE                           0x00000001
 #define EFI_VARIABLE_BOOTSERVICE_ACCESS                     0x00000002
 #define EFI_VARIABLE_RUNTIME_ACCESS                         0x00000004
@@ -47,13 +49,23 @@ struct efi_data {
        uint8_t fill[0];
 };
 
-void set_efivarfs_path(const char *path);
-const char *get_efivarfs_path(void);
+struct efi_mount {
+       const char *path;
+       const char *guid;
+};
+
+void efi_init_mount(struct efi_mount *efi_mount, const char *path,
+       const char *guid);
+bool efi_check_mount_magic(const struct efi_mount *efi_mount, bool check_magic);
+static inline bool efi_check_mount(const struct efi_mount *efi_mount)
+{
+       return efi_check_mount_magic(efi_mount, true);
+}
 
-int efi_get_variable(void *ctx, const char *guidstr, const char *name,
-               struct efi_data **efi_data);
-int efi_set_variable(const char *guidstr, const char *name,
-               const struct efi_data *efi_data);
-int efi_del_variable(const char *guidstr, const char *name);
+int efi_get_variable(void *ctx, const struct efi_mount *efi_mount,
+       const char *name, struct efi_data **efi_data);
+int efi_set_variable(const struct efi_mount *efi_mount, const char *name,
+       const struct efi_data *efi_data);
+int efi_del_variable(const struct efi_mount *efi_mount, const char *name);
 
 #endif /* EFIVAR_H */