| Joel Stanley | 6a0ced9 | 2017-05-03 13:41:44 +0930 | [diff] [blame] | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | 
 | 2 | From: Matt Brown <matthew.brown.dev@gmail.com> | 
 | 3 | Date: Thu, 30 Mar 2017 10:28:01 +1100 | 
 | 4 | Subject: [PATCH 3/4] powerpc/powernv: Add OPAL exports attributes to sysfs | 
 | 5 |  | 
 | 6 | New versions of OPAL have a device node /ibm,opal/firmware/exports, each | 
 | 7 | property of which describes a range of memory in OPAL that Linux might | 
 | 8 | want to export to userspace for debugging. | 
 | 9 |  | 
 | 10 | This patch adds a sysfs file under 'opal/exports' for each property | 
 | 11 | found there, and makes it read-only by root. | 
 | 12 |  | 
 | 13 | Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com> | 
 | 14 | [mpe: Drop counting of props, rename to attr, free on sysfs error, c'log] | 
 | 15 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | 
 | 16 | (cherry picked from commit 11fe909d236263f62808dc3c73caf798e026d7aa) | 
 | 17 | Signed-off-by: Joel Stanley <joel@jms.id.au> | 
 | 18 |  | 
 | 19 | Signed-off-by: Joel Stanley <joel@jms.id.au> | 
 | 20 | --- | 
 | 21 |  arch/powerpc/platforms/powernv/opal.c | 76 +++++++++++++++++++++++++++++++++++ | 
 | 22 |  1 file changed, 76 insertions(+) | 
 | 23 |  | 
 | 24 | diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c | 
 | 25 | index e0f856bfbfe8..25ea8f6fe7f8 100644 | 
 | 26 | --- a/arch/powerpc/platforms/powernv/opal.c | 
 | 27 | +++ b/arch/powerpc/platforms/powernv/opal.c | 
 | 28 | @@ -595,6 +595,79 @@ static void opal_export_symmap(void) | 
 | 29 |  		pr_warn("Error %d creating OPAL symbols file\n", rc); | 
 | 30 |  } | 
 | 31 |   | 
 | 32 | +static ssize_t export_attr_read(struct file *fp, struct kobject *kobj, | 
 | 33 | +				struct bin_attribute *bin_attr, char *buf, | 
 | 34 | +				loff_t off, size_t count) | 
 | 35 | +{ | 
 | 36 | +	return memory_read_from_buffer(buf, count, &off, bin_attr->private, | 
 | 37 | +				       bin_attr->size); | 
 | 38 | +} | 
 | 39 | + | 
 | 40 | +/* | 
 | 41 | + * opal_export_attrs: creates a sysfs node for each property listed in | 
 | 42 | + * the device-tree under /ibm,opal/firmware/exports/ | 
 | 43 | + * All new sysfs nodes are created under /opal/exports/. | 
 | 44 | + * This allows for reserved memory regions (e.g. HDAT) to be read. | 
 | 45 | + * The new sysfs nodes are only readable by root. | 
 | 46 | + */ | 
 | 47 | +static void opal_export_attrs(void) | 
 | 48 | +{ | 
 | 49 | +	struct bin_attribute *attr; | 
 | 50 | +	struct device_node *np; | 
 | 51 | +	struct property *prop; | 
 | 52 | +	struct kobject *kobj; | 
 | 53 | +	u64 vals[2]; | 
 | 54 | +	int rc; | 
 | 55 | + | 
 | 56 | +	np = of_find_node_by_path("/ibm,opal/firmware/exports"); | 
 | 57 | +	if (!np) | 
 | 58 | +		return; | 
 | 59 | + | 
 | 60 | +	/* Create new 'exports' directory - /sys/firmware/opal/exports */ | 
 | 61 | +	kobj = kobject_create_and_add("exports", opal_kobj); | 
 | 62 | +	if (!kobj) { | 
 | 63 | +		pr_warn("kobject_create_and_add() of exports failed\n"); | 
 | 64 | +		return; | 
 | 65 | +	} | 
 | 66 | + | 
 | 67 | +	for_each_property_of_node(np, prop) { | 
 | 68 | +		if (!strcmp(prop->name, "name") || !strcmp(prop->name, "phandle")) | 
 | 69 | +			continue; | 
 | 70 | + | 
 | 71 | +		if (of_property_read_u64_array(np, prop->name, &vals[0], 2)) | 
 | 72 | +			continue; | 
 | 73 | + | 
 | 74 | +		attr = kmalloc(sizeof(*attr), GFP_KERNEL); | 
 | 75 | + | 
 | 76 | +		if (attr == NULL) { | 
 | 77 | +			pr_warn("Failed kmalloc for bin_attribute!"); | 
 | 78 | +			continue; | 
 | 79 | +		} | 
 | 80 | + | 
 | 81 | +		attr->attr.name = kstrdup(prop->name, GFP_KERNEL); | 
 | 82 | +		attr->attr.mode = 0400; | 
 | 83 | +		attr->read = export_attr_read; | 
 | 84 | +		attr->private = __va(vals[0]); | 
 | 85 | +		attr->size = vals[1]; | 
 | 86 | + | 
 | 87 | +		if (attr->attr.name == NULL) { | 
 | 88 | +			pr_warn("Failed kstrdup for bin_attribute attr.name"); | 
 | 89 | +			kfree(attr); | 
 | 90 | +			continue; | 
 | 91 | +		} | 
 | 92 | + | 
 | 93 | +		rc = sysfs_create_bin_file(kobj, attr); | 
 | 94 | +		if (rc) { | 
 | 95 | +			pr_warn("Error %d creating OPAL sysfs exports/%s file\n", | 
 | 96 | +				 rc, prop->name); | 
 | 97 | +			kfree(attr->attr.name); | 
 | 98 | +			kfree(attr); | 
 | 99 | +		} | 
 | 100 | +	} | 
 | 101 | + | 
 | 102 | +	of_node_put(np); | 
 | 103 | +} | 
 | 104 | + | 
 | 105 |  static void __init opal_dump_region_init(void) | 
 | 106 |  { | 
 | 107 |  	void *addr; | 
 | 108 | @@ -733,6 +806,9 @@ static int __init opal_init(void) | 
 | 109 |  		opal_msglog_sysfs_init(); | 
 | 110 |  	} | 
 | 111 |   | 
 | 112 | +	/* Export all properties */ | 
 | 113 | +	opal_export_attrs(); | 
 | 114 | + | 
 | 115 |  	/* Initialize platform devices: IPMI backend, PRD & flash interface */ | 
 | 116 |  	opal_pdev_init("ibm,opal-ipmi"); | 
 | 117 |  	opal_pdev_init("ibm,opal-flash"); | 
 | 118 | --  | 
 | 119 | 2.11.0 | 
 | 120 |  |