The /sys/firmware/secvar/config directory represents Power LPAR Platform
KeyStore (PLPKS) configuration properties such as max_object_size, signed_
update_algorithms, supported_policies, total_size, used_space, and version.
These attributes describe the PLPKS, and not the secure boot variables
(secvars).

Create /sys/firmware/plpks directory and move the PLPKS config inside this
directory. For backwards compatibility, create a soft link from the secvar
sysfs directory to this config and emit a warning stating that the older
sysfs path has been deprecated. Separate out the plpks specific
documentation from secvar.

Signed-off-by: Srish Srinivasan <[email protected]>
---
 .../ABI/testing/sysfs-firmware-plpks          | 50 ++++++++++
 Documentation/ABI/testing/sysfs-secvar        | 65 -------------
 arch/powerpc/include/asm/plpks.h              |  4 +
 arch/powerpc/include/asm/secvar.h             |  1 -
 arch/powerpc/kernel/secvar-sysfs.c            | 21 ++---
 arch/powerpc/platforms/pseries/Makefile       |  2 +-
 arch/powerpc/platforms/pseries/plpks-secvar.c | 29 ------
 arch/powerpc/platforms/pseries/plpks-sysfs.c  | 94 +++++++++++++++++++
 8 files changed, 155 insertions(+), 111 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-plpks
 create mode 100644 arch/powerpc/platforms/pseries/plpks-sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-firmware-plpks 
b/Documentation/ABI/testing/sysfs-firmware-plpks
new file mode 100644
index 000000000000..af0353f34115
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-plpks
@@ -0,0 +1,50 @@
+What:          /sys/firmware/plpks/config
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   This optional directory contains read-only config attributes as
+               defined by the PLPKS implementation. All data is in ASCII
+               format.
+
+What:          /sys/firmware/plpks/config/version
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Config version as reported by the hypervisor in ASCII decimal
+               format.
+
+What:          /sys/firmware/plpks/config/max_object_size
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Maximum allowed size of objects in the keystore in bytes,
+               represented in ASCII decimal format.
+
+               This is not necessarily the same as the max size that can be
+               written to an update file as writes can contain more than
+               object data, you should use the size of the update file for
+               that purpose.
+
+What:          /sys/firmware/plpks/config/total_size
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Total size of the PLPKS in bytes, represented in ASCII decimal
+               format.
+
+What:          /sys/firmware/plpks/config/used_space
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Current space consumed by the key store, in bytes, represented
+               in ASCII decimal format.
+
+What:          /sys/firmware/plpks/config/supported_policies
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Bitmask of supported policy flags by the hypervisor, represented
+               as an 8 byte hexadecimal ASCII string. Consult the hypervisor
+               documentation for what these flags are.
+
+What:          /sys/firmware/plpks/config/signed_update_algorithms
+Date:          February 2023
+Contact:       Nayna Jain <[email protected]>
+Description:   Bitmask of flags indicating which algorithms the hypervisor
+               supports for signed update of objects, represented as a 16 byte
+               hexadecimal ASCII string. Consult the hypervisor documentation
+               for what these flags mean.
diff --git a/Documentation/ABI/testing/sysfs-secvar 
b/Documentation/ABI/testing/sysfs-secvar
index 1016967a730f..c52a5fd15709 100644
--- a/Documentation/ABI/testing/sysfs-secvar
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -63,68 +63,3 @@ Contact:     Nayna Jain <[email protected]>
 Description:   A write-only file that is used to submit the new value for the
                variable. The size of the file represents the maximum size of
                the variable data that can be written.
-
-What:          /sys/firmware/secvar/config
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   This optional directory contains read-only config attributes as
-               defined by the secure variable implementation.  All data is in
-               ASCII format. The directory is only created if the backing
-               implementation provides variables to populate it, which at
-               present is only PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/version
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Config version as reported by the hypervisor in ASCII decimal
-               format.
-
-               Currently only provided by PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/max_object_size
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Maximum allowed size of objects in the keystore in bytes,
-               represented in ASCII decimal format.
-
-               This is not necessarily the same as the max size that can be
-               written to an update file as writes can contain more than
-               object data, you should use the size of the update file for
-               that purpose.
-
-               Currently only provided by PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/total_size
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Total size of the PLPKS in bytes, represented in ASCII decimal
-               format.
-
-               Currently only provided by PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/used_space
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Current space consumed by the key store, in bytes, represented
-               in ASCII decimal format.
-
-               Currently only provided by PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/supported_policies
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Bitmask of supported policy flags by the hypervisor,
-               represented as an 8 byte hexadecimal ASCII string. Consult the
-               hypervisor documentation for what these flags are.
-
-               Currently only provided by PLPKS on the pseries platform.
-
-What:          /sys/firmware/secvar/config/signed_update_algorithms
-Date:          February 2023
-Contact:       Nayna Jain <[email protected]>
-Description:   Bitmask of flags indicating which algorithms the hypervisor
-               supports for signed update of objects, represented as a 16 byte
-               hexadecimal ASCII string. Consult the hypervisor documentation
-               for what these flags mean.
-
-               Currently only provided by PLPKS on the pseries platform.
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index f303922bf622..53e5839b0cbe 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/kobject.h>
 
 // Object policy flags from supported_policies
 #define PLPKS_OSSECBOOTAUDIT   PPC_BIT32(1) // OS secure boot must be 
audit/enforce
@@ -107,11 +108,14 @@ u16 plpks_get_passwordlen(void);
 void plpks_early_init_devtree(void);
 
 int plpks_populate_fdt(void *fdt);
+
+int plpks_config_create_softlink(struct kobject *from);
 #else // CONFIG_PSERIES_PLPKS
 static inline bool plpks_is_available(void) { return false; }
 static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
 static inline void plpks_early_init_devtree(void) { }
 static inline int plpks_populate_fdt(void *fdt) { BUILD_BUG(); }
+static int plpks_config_create_softlink(struct kobject *from) { return 0; }
 #endif // CONFIG_PSERIES_PLPKS
 
 #endif // _ASM_POWERPC_PLPKS_H
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
index 4828e0ab7e3c..fd5006307f2a 100644
--- a/arch/powerpc/include/asm/secvar.h
+++ b/arch/powerpc/include/asm/secvar.h
@@ -20,7 +20,6 @@ struct secvar_operations {
        int (*set)(const char *key, u64 key_len, u8 *data, u64 data_size);
        ssize_t (*format)(char *buf, size_t bufsize);
        int (*max_size)(u64 *max_size);
-       const struct attribute **config_attrs;
 
        // NULL-terminated array of fixed variable names
        // Only used if get_next() isn't provided
diff --git a/arch/powerpc/kernel/secvar-sysfs.c 
b/arch/powerpc/kernel/secvar-sysfs.c
index ec900bce0257..4111b21962eb 100644
--- a/arch/powerpc/kernel/secvar-sysfs.c
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/of.h>
 #include <asm/secvar.h>
+#include <asm/plpks.h>
 
 #define NAME_MAX_SIZE     1024
 
@@ -145,19 +146,6 @@ static __init int update_kobj_size(void)
        return 0;
 }
 
-static __init int secvar_sysfs_config(struct kobject *kobj)
-{
-       struct attribute_group config_group = {
-               .name = "config",
-               .attrs = (struct attribute **)secvar_ops->config_attrs,
-       };
-
-       if (secvar_ops->config_attrs)
-               return sysfs_create_group(kobj, &config_group);
-
-       return 0;
-}
-
 static __init int add_var(const char *name)
 {
        struct kobject *kobj;
@@ -260,12 +248,15 @@ static __init int secvar_sysfs_init(void)
                goto err;
        }
 
-       rc = secvar_sysfs_config(secvar_kobj);
+       rc = plpks_config_create_softlink(secvar_kobj);
        if (rc) {
-               pr_err("Failed to create config directory\n");
+               pr_err("Failed to create softlink to PLPKS config directory");
                goto err;
        }
 
+       pr_info("/sys/firmware/secvar/config is now deprecated.\n");
+       pr_info("Will be removed in future versions.\n");
+
        if (secvar_ops->get_next)
                rc = secvar_sysfs_load();
        else
diff --git a/arch/powerpc/platforms/pseries/Makefile 
b/arch/powerpc/platforms/pseries/Makefile
index 931ebaa474c8..3ced289a675b 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -30,7 +30,7 @@ obj-$(CONFIG_PAPR_SCM)                += papr_scm.o
 obj-$(CONFIG_PPC_SPLPAR)       += vphn.o
 obj-$(CONFIG_PPC_SVM)          += svm.o
 obj-$(CONFIG_FA_DUMP)          += rtas-fadump.o
-obj-$(CONFIG_PSERIES_PLPKS)    += plpks.o
+obj-$(CONFIG_PSERIES_PLPKS)    += plpks.o plpks-sysfs.o
 obj-$(CONFIG_PPC_SECURE_BOOT)  += plpks-secvar.o
 obj-$(CONFIG_PSERIES_PLPKS_SED)        += plpks_sed_ops.o
 obj-$(CONFIG_SUSPEND)          += suspend.o
diff --git a/arch/powerpc/platforms/pseries/plpks-secvar.c 
b/arch/powerpc/platforms/pseries/plpks-secvar.c
index f9e9cc40c9d0..a50ff6943d80 100644
--- a/arch/powerpc/platforms/pseries/plpks-secvar.c
+++ b/arch/powerpc/platforms/pseries/plpks-secvar.c
@@ -20,33 +20,6 @@
 #include <asm/secvar.h>
 #include <asm/plpks.h>
 
-// Config attributes for sysfs
-#define PLPKS_CONFIG_ATTR(name, fmt, func)                     \
-       static ssize_t name##_show(struct kobject *kobj,        \
-                                  struct kobj_attribute *attr, \
-                                  char *buf)                   \
-       {                                                       \
-               return sysfs_emit(buf, fmt, func());            \
-       }                                                       \
-       static struct kobj_attribute attr_##name = __ATTR_RO(name)
-
-PLPKS_CONFIG_ATTR(version, "%u\n", plpks_get_version);
-PLPKS_CONFIG_ATTR(max_object_size, "%u\n", plpks_get_maxobjectsize);
-PLPKS_CONFIG_ATTR(total_size, "%u\n", plpks_get_totalsize);
-PLPKS_CONFIG_ATTR(used_space, "%u\n", plpks_get_usedspace);
-PLPKS_CONFIG_ATTR(supported_policies, "%08x\n", plpks_get_supportedpolicies);
-PLPKS_CONFIG_ATTR(signed_update_algorithms, "%016llx\n", 
plpks_get_signedupdatealgorithms);
-
-static const struct attribute *config_attrs[] = {
-       &attr_version.attr,
-       &attr_max_object_size.attr,
-       &attr_total_size.attr,
-       &attr_used_space.attr,
-       &attr_supported_policies.attr,
-       &attr_signed_update_algorithms.attr,
-       NULL,
-};
-
 static u32 get_policy(const char *name)
 {
        if ((strcmp(name, "db") == 0) ||
@@ -225,7 +198,6 @@ static const struct secvar_operations 
plpks_secvar_ops_static = {
        .set = plpks_set_variable,
        .format = plpks_secvar_format,
        .max_size = plpks_max_size,
-       .config_attrs = config_attrs,
        .var_names = plpks_var_names_static,
 };
 
@@ -234,7 +206,6 @@ static const struct secvar_operations 
plpks_secvar_ops_dynamic = {
        .set = plpks_set_variable,
        .format = plpks_secvar_format,
        .max_size = plpks_max_size,
-       .config_attrs = config_attrs,
        .var_names = plpks_var_names_dynamic,
 };
 
diff --git a/arch/powerpc/platforms/pseries/plpks-sysfs.c 
b/arch/powerpc/platforms/pseries/plpks-sysfs.c
new file mode 100644
index 000000000000..01d526185783
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks-sysfs.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 IBM Corporation, Srish Srinivasan <[email protected]>
+ *
+ * This code exposes PLPKS config to user via sysfs
+ */
+
+#define pr_fmt(fmt) "plpks-sysfs: "fmt
+
+#include <linux/init.h>
+#include <linux/printk.h>
+#include <linux/types.h>
+#include <asm/machdep.h>
+#include <asm/plpks.h>
+
+/* config attributes for sysfs */
+#define PLPKS_CONFIG_ATTR(name, fmt, func)                     \
+       static ssize_t name##_show(struct kobject *kobj,        \
+                                  struct kobj_attribute *attr, \
+                                  char *buf)                   \
+       {                                                       \
+               return sysfs_emit(buf, fmt, func());            \
+       }                                                       \
+       static struct kobj_attribute attr_##name = __ATTR_RO(name)
+
+PLPKS_CONFIG_ATTR(version, "%u\n", plpks_get_version);
+PLPKS_CONFIG_ATTR(max_object_size, "%u\n", plpks_get_maxobjectsize);
+PLPKS_CONFIG_ATTR(total_size, "%u\n", plpks_get_totalsize);
+PLPKS_CONFIG_ATTR(used_space, "%u\n", plpks_get_usedspace);
+PLPKS_CONFIG_ATTR(supported_policies, "%08x\n", plpks_get_supportedpolicies);
+PLPKS_CONFIG_ATTR(signed_update_algorithms, "%016llx\n",
+                 plpks_get_signedupdatealgorithms);
+
+static const struct attribute *config_attrs[] = {
+       &attr_version.attr,
+       &attr_max_object_size.attr,
+       &attr_total_size.attr,
+       &attr_used_space.attr,
+       &attr_supported_policies.attr,
+       &attr_signed_update_algorithms.attr,
+       NULL,
+};
+
+static struct kobject *plpks_kobj, *plpks_config_kobj;
+
+int plpks_config_create_softlink(struct kobject *from)
+{
+       if (!plpks_config_kobj)
+               return -EINVAL;
+       return sysfs_create_link(from, plpks_config_kobj, "config");
+}
+
+static __init int plpks_sysfs_config(struct kobject *kobj)
+{
+       struct attribute_group config_group = {
+               .name = NULL,
+               .attrs = (struct attribute **)config_attrs,
+       };
+
+       return sysfs_create_group(kobj, &config_group);
+}
+
+static __init int plpks_sysfs_init(void)
+{
+       int rc;
+
+       if (!plpks_is_available())
+               return -ENODEV;
+
+       plpks_kobj = kobject_create_and_add("plpks", firmware_kobj);
+       if (!plpks_kobj) {
+               pr_err("Failed to create plpks kobj\n");
+               return -ENOMEM;
+       }
+
+       plpks_config_kobj = kobject_create_and_add("config", plpks_kobj);
+       if (!plpks_config_kobj) {
+               pr_err("Failed to create plpks config kobj\n");
+               kobject_put(plpks_kobj);
+               return -ENOMEM;
+       }
+
+       rc = plpks_sysfs_config(plpks_config_kobj);
+       if (rc) {
+               pr_err("Failed to create attribute group for plpks config\n");
+               kobject_put(plpks_config_kobj);
+               kobject_put(plpks_kobj);
+               return rc;
+       }
+
+       return 0;
+}
+
+machine_subsys_initcall(pseries, plpks_sysfs_init);
-- 
2.47.3


Reply via email to