1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2025 IBM Corporation, Srish Srinivasan <ssrish@linux.ibm.com> 4 * 5 * This code exposes PLPKS config to user via sysfs 6 */ 7 8 #define pr_fmt(fmt) "plpks-sysfs: "fmt 9 10 #include <linux/init.h> 11 #include <linux/printk.h> 12 #include <linux/types.h> 13 #include <asm/machdep.h> 14 #include <asm/plpks.h> 15 16 /* config attributes for sysfs */ 17 #define PLPKS_CONFIG_ATTR(name, fmt, func) \ 18 static ssize_t name##_show(struct kobject *kobj, \ 19 struct kobj_attribute *attr, \ 20 char *buf) \ 21 { \ 22 return sysfs_emit(buf, fmt, func()); \ 23 } \ 24 static struct kobj_attribute attr_##name = __ATTR_RO(name) 25 26 PLPKS_CONFIG_ATTR(version, "%u\n", plpks_get_version); 27 PLPKS_CONFIG_ATTR(max_object_size, "%u\n", plpks_get_maxobjectsize); 28 PLPKS_CONFIG_ATTR(total_size, "%u\n", plpks_get_totalsize); 29 PLPKS_CONFIG_ATTR(used_space, "%u\n", plpks_get_usedspace); 30 PLPKS_CONFIG_ATTR(supported_policies, "%08x\n", plpks_get_supportedpolicies); 31 PLPKS_CONFIG_ATTR(signed_update_algorithms, "%016llx\n", 32 plpks_get_signedupdatealgorithms); 33 PLPKS_CONFIG_ATTR(wrapping_features, "%016llx\n", plpks_get_wrappingfeatures); 34 35 static const struct attribute *config_attrs[] = { 36 &attr_version.attr, 37 &attr_max_object_size.attr, 38 &attr_total_size.attr, 39 &attr_used_space.attr, 40 &attr_supported_policies.attr, 41 &attr_signed_update_algorithms.attr, 42 &attr_wrapping_features.attr, 43 NULL, 44 }; 45 46 static struct kobject *plpks_kobj, *plpks_config_kobj; 47 48 int plpks_config_create_softlink(struct kobject *from) 49 { 50 if (!plpks_config_kobj) 51 return -EINVAL; 52 return sysfs_create_link(from, plpks_config_kobj, "config"); 53 } 54 55 static __init int plpks_sysfs_config(struct kobject *kobj) 56 { 57 struct attribute_group config_group = { 58 .name = NULL, 59 .attrs = (struct attribute **)config_attrs, 60 }; 61 62 return sysfs_create_group(kobj, &config_group); 63 } 64 65 static __init int plpks_sysfs_init(void) 66 { 67 int rc; 68 69 if (!plpks_is_available()) 70 return -ENODEV; 71 72 plpks_kobj = kobject_create_and_add("plpks", firmware_kobj); 73 if (!plpks_kobj) { 74 pr_err("Failed to create plpks kobj\n"); 75 return -ENOMEM; 76 } 77 78 plpks_config_kobj = kobject_create_and_add("config", plpks_kobj); 79 if (!plpks_config_kobj) { 80 pr_err("Failed to create plpks config kobj\n"); 81 kobject_put(plpks_kobj); 82 return -ENOMEM; 83 } 84 85 rc = plpks_sysfs_config(plpks_config_kobj); 86 if (rc) { 87 pr_err("Failed to create attribute group for plpks config\n"); 88 kobject_put(plpks_config_kobj); 89 kobject_put(plpks_kobj); 90 return rc; 91 } 92 93 return 0; 94 } 95 96 machine_subsys_initcall(pseries, plpks_sysfs_init); 97