From: Daniel Axtens <dja@axtens.net>
To: nayna@linux.ibm.com, cclaudio@linux.ibm.com,
linux-fsdevel@vger.kernel.org, greg@kroah.com,
linuxppc-dev@lists.ozlabs.org
Cc: Daniel Axtens <dja@axtens.net>
Subject: [WIP RFC PATCH 6/6] fwvarfs: Add opal_secvar backend
Date: Mon, 20 May 2019 16:25:53 +1000 [thread overview]
Message-ID: <20190520062553.14947-7-dja@axtens.net> (raw)
In-Reply-To: <20190520062553.14947-1-dja@axtens.net>
COMPILE TESTED ONLY.
mount -t fwvarfs opal_secvar /fw
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
Documentation/filesystems/fwvarfs.txt | 3 +
fs/fwvarfs/Kconfig | 11 ++
fs/fwvarfs/Makefile | 1 +
fs/fwvarfs/fwvarfs.c | 3 +
fs/fwvarfs/fwvarfs.h | 4 +
fs/fwvarfs/opal_secvar.c | 218 ++++++++++++++++++++++++++
6 files changed, 240 insertions(+)
create mode 100644 fs/fwvarfs/opal_secvar.c
diff --git a/Documentation/filesystems/fwvarfs.txt b/Documentation/filesystems/fwvarfs.txt
index 7c1e921e5c50..3ecc4b4428a5 100644
--- a/Documentation/filesystems/fwvarfs.txt
+++ b/Documentation/filesystems/fwvarfs.txt
@@ -36,6 +36,9 @@ Supported backends
backend. Read-only with no creation or deletion, but sufficient that
efivar --print --name <whatever> works the same as efivarfs.
+ * opal_secvar - COMPILE-TESTED ONLY implementation against PowerNV
+ OPAL Secure Variable storage.
+
Usage
-----
diff --git a/fs/fwvarfs/Kconfig b/fs/fwvarfs/Kconfig
index e4474da11dbc..cb9cbc6f8fb3 100644
--- a/fs/fwvarfs/Kconfig
+++ b/fs/fwvarfs/Kconfig
@@ -34,3 +34,14 @@ config FWVAR_FS_EFI_BACKEND
in the same way the do with efivarfs.
Say N here unless you're exploring fwvarfs.
+
+config FWVAR_FS_OPAL_SECVAR_BACKEND
+ bool "OPAL Secure Variable backend"
+ depends on FWVAR_FS
+ depends on OPAL_SECVAR
+ help
+ Include a read-only, compile-tested-only, not up-to-date
+ backend for OPAL Secure Variables. This is really just
+ designed to show how the code would work, and you should
+ only select Y here if you are developing OPAL secure
+ variables.
diff --git a/fs/fwvarfs/Makefile b/fs/fwvarfs/Makefile
index 2ab9dfd650ca..8d258acdfef7 100644
--- a/fs/fwvarfs/Makefile
+++ b/fs/fwvarfs/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_FWVAR_FS) += fwvarfs.o
obj-$(CONFIG_FWVAR_FS_MEM_BACKEND) += mem.o
obj-$(CONFIG_FWVAR_FS_EFI_BACKEND) += efi.o
+obj-$(CONFIG_FWVAR_FS_OPAL_SECVAR_BACKEND) += opal_secvar.o
diff --git a/fs/fwvarfs/fwvarfs.c b/fs/fwvarfs/fwvarfs.c
index 643ec6585b4d..3c93b6442e95 100644
--- a/fs/fwvarfs/fwvarfs.c
+++ b/fs/fwvarfs/fwvarfs.c
@@ -24,6 +24,9 @@ static struct fwvarfs_backend *fwvarfs_backends[] = {
#endif
#ifdef CONFIG_FWVAR_FS_EFI_BACKEND
&fwvarfs_efi_backend,
+#endif
+#ifdef CONFIG_FWVAR_FS_OPAL_SECVAR_BACKEND
+ &fwvarfs_opal_secvar_backend,
#endif
NULL,
};
diff --git a/fs/fwvarfs/fwvarfs.h b/fs/fwvarfs/fwvarfs.h
index 49bde268401f..5780046dafae 100644
--- a/fs/fwvarfs/fwvarfs.h
+++ b/fs/fwvarfs/fwvarfs.h
@@ -117,4 +117,8 @@ extern struct fwvarfs_backend fwvarfs_mem_backend;
extern struct fwvarfs_backend fwvarfs_efi_backend;
#endif
+#if defined(CONFIG_FWVAR_FS_OPAL_SECVAR_BACKEND)
+extern struct fwvarfs_backend fwvarfs_opal_secvar_backend;
+#endif
+
#endif /* FWVARFS_H */
diff --git a/fs/fwvarfs/opal_secvar.c b/fs/fwvarfs/opal_secvar.c
new file mode 100644
index 000000000000..4a1749317ed9
--- /dev/null
+++ b/fs/fwvarfs/opal_secvar.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Daniel Axtens
+ *
+ * Loosely based on efivarfs:
+ * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
+ * and drivers/firmware/efi/vars.c:
+ * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
+ * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
+ *
+ * We cheat by not allowing for case-insensitivity.
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "fwvarfs.h"
+
+#include <linux/uuid.h>
+#include <linux/ucs2_string.h>
+#include <asm/opal-api.h>
+#include <asm/opal-secvar.h>
+
+#define pr_fmt(fmt) "fwvarfs: opal_secvar: " fmt
+
+static LIST_HEAD(opal_secvar_file_list);
+
+struct fwvarfs_opal_secvar_file {
+ struct list_head list;
+ u16 *name;
+ guid_t vendor;
+};
+
+// stolen from efi.h
+static inline char *
+guid_to_str(guid_t *guid, char *out)
+{
+ sprintf(out, "%pUl", guid->b);
+ return out;
+}
+
+// need a forward decl to pass down to register
+struct fwvarfs_backend fwvarfs_opal_secvar_backend;
+
+
+static ssize_t fwvarfs_opal_secvar_read(void *variable, char *buf,
+ size_t count, loff_t off)
+{
+ struct fwvarfs_opal_secvar_file *file_data = variable;
+ unsigned long datasize = 0;
+ u32 attributes;
+ void *data;
+ ssize_t size = 0;
+ loff_t ppos = off;
+ int rc;
+
+ // get size
+ rc = opal_get_secure_variable(file_data->name, &file_data->vendor,
+ NULL, &datasize, NULL);
+ if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL)
+ return -EIO;
+
+ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
+
+ if (!data)
+ return -ENOMEM;
+
+ rc = opal_get_secure_variable(file_data->name, &file_data->vendor,
+ &attributes, &datasize, data + sizeof(attributes));
+ if (rc != OPAL_SUCCESS) {
+ size = -EIO;
+ goto out_free;
+ }
+
+ memcpy(data, &attributes, sizeof(attributes));
+ size = memory_read_from_buffer(buf, count, &ppos, data,
+ datasize + sizeof(attributes));
+out_free:
+ kfree(data);
+
+ return size;
+}
+
+static int fwvarfs_opal_secvar_callback(u16 *name16, guid_t vendor,
+ unsigned long name_size)
+{
+ struct fwvarfs_opal_secvar_file *file_data;
+ char *name;
+ int len;
+ int err = -ENOMEM;
+
+ file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
+ if (!file_data)
+ return err;
+
+ file_data->name = kmemdup(name16, name_size, GFP_KERNEL);
+ if (!file_data->name)
+ goto fail;
+
+ file_data->vendor = vendor;
+
+ len = ucs2_utf8size(name16);
+
+ /* name, plus '-', plus GUID, plus NUL */
+ name = kmalloc(len + 1 + UUID_STRING_LEN + 1, GFP_KERNEL);
+ if (!name)
+ goto fail_embedded_name;
+
+ ucs2_as_utf8(name, name16, len);
+
+ name[len] = '-';
+
+ guid_to_str(&vendor, name + len + 1);
+
+ name[len + UUID_STRING_LEN + 1] = '\0';
+
+ // no convenient way to get size without reading the whole thing,
+ // present size as 0 for now.
+
+ err = fwvarfs_register_var(&fwvarfs_opal_secvar_backend, name,
+ file_data, 0);
+ if (err)
+ goto fail_name;
+
+ INIT_LIST_HEAD(&file_data->list);
+ list_add(&opal_secvar_file_list, &file_data->list);
+
+ /* copied by the above, I think */
+ kfree(name);
+
+ return 0;
+fail_name:
+ kfree(name);
+fail_embedded_name:
+ kfree(file_data->name);
+fail:
+ kfree(file_data);
+ return err;
+}
+
+
+static void fwvarfs_opal_secvar_destroy(void *var)
+{
+ struct fwvarfs_opal_secvar_file *file_data = var;
+
+ kfree(file_data->name);
+ list_del(&file_data->list);
+ kfree(file_data);
+}
+
+
+static int fwvarfs_opal_secvar_enumerate(void)
+{
+ int err;
+ struct fwvarfs_opal_secvar_file *pos, *tmp;
+ unsigned long variable_name_size = 1024;
+ u16 *variable_name;
+ unsigned long status;
+ guid_t vendor_guid;
+
+ variable_name = kzalloc(variable_name_size, GFP_KERNEL);
+ if (!variable_name)
+ return -ENOMEM;
+
+ /*
+ * Assume that as per EFI spec, the maximum storage allocated for both
+ * the variable name and variable data is 1024 bytes.
+ */
+
+ do {
+ variable_name_size = 1024;
+
+ status = opal_get_next_secure_variable(&variable_name_size,
+ variable_name,
+ &vendor_guid);
+ switch (status) {
+ case OPAL_SUCCESS:
+ err = fwvarfs_opal_secvar_callback(variable_name,
+ vendor_guid, variable_name_size);
+ if (err)
+ status = OPAL_EMPTY;
+
+ break;
+ case OPAL_EMPTY:
+ break;
+ case OPAL_UNSUPPORTED:
+ status = OPAL_EMPTY;
+ err = -ENODEV;
+ default:
+ pr_warn("opal_get_next_secure_variable: status=%lx\n",
+ status);
+ status = OPAL_EMPTY;
+ err = -EIO;
+ break;
+ }
+
+ } while (status != OPAL_EMPTY);
+
+ kfree(variable_name);
+
+ if (err) {
+ list_for_each_entry_safe(pos, tmp, &opal_secvar_file_list,
+ list) {
+ fwvarfs_opal_secvar_destroy(pos);
+ }
+ }
+
+ return err;
+}
+
+struct fwvarfs_backend fwvarfs_opal_secvar_backend = {
+ .name = "opal_secvar",
+ .destroy = fwvarfs_opal_secvar_destroy,
+ .enumerate = fwvarfs_opal_secvar_enumerate,
+ .read = fwvarfs_opal_secvar_read,
+};
--
2.19.1
next prev parent reply other threads:[~2019-05-20 6:26 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-20 6:25 [WIP RFC PATCH 0/6] Generic Firmware Variable Filesystem Daniel Axtens
2019-05-20 6:25 ` [WIP RFC PATCH 1/6] kernfs: add create() and unlink() hooks Daniel Axtens
2019-05-20 6:25 ` [WIP RFC PATCH 2/6] fwvarfs: a generic firmware variable filesystem Daniel Axtens
2019-05-20 6:25 ` [WIP RFC PATCH 3/6] fwvarfs: efi backend Daniel Axtens
2019-05-20 6:25 ` [WIP RFC PATCH 4/6] powerpc/powernv: Add support for OPAL secure variables Daniel Axtens
2019-05-20 6:25 ` [WIP RFC PATCH 5/6] powerpc/powernv: Remove EFI " Daniel Axtens
2019-05-20 6:25 ` Daniel Axtens [this message]
2019-05-31 4:04 ` [WIP RFC PATCH 0/6] Generic Firmware Variable Filesystem Nayna
2019-06-03 6:04 ` Daniel Axtens
2019-06-03 7:29 ` Greg KH
2019-06-03 23:56 ` Daniel Axtens
2019-06-04 20:01 ` Nayna
2019-06-04 20:05 ` Matthew Garrett
2019-06-05 8:13 ` Greg KH
2019-06-04 20:33 ` Nayna
2019-06-05 6:14 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190520062553.14947-7-dja@axtens.net \
--to=dja@axtens.net \
--cc=cclaudio@linux.ibm.com \
--cc=greg@kroah.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=nayna@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).