xref: /linux/drivers/scsi/iscsi_boot_sysfs.c (revision 0267ffce)
1d9523678SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2aab7a8fdSMike Christie /*
3aab7a8fdSMike Christie  * Export the iSCSI boot info to userland via sysfs.
4aab7a8fdSMike Christie  *
5aab7a8fdSMike Christie  * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
6aab7a8fdSMike Christie  * Copyright (C) 2010 Mike Christie
7aab7a8fdSMike Christie  */
8aab7a8fdSMike Christie 
9aab7a8fdSMike Christie #include <linux/module.h>
10aab7a8fdSMike Christie #include <linux/string.h>
11aab7a8fdSMike Christie #include <linux/slab.h>
12aab7a8fdSMike Christie #include <linux/sysfs.h>
13aab7a8fdSMike Christie #include <linux/capability.h>
14aab7a8fdSMike Christie #include <linux/iscsi_boot_sysfs.h>
15aab7a8fdSMike Christie 
16aab7a8fdSMike Christie 
17aab7a8fdSMike Christie MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
18aab7a8fdSMike Christie MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
19aab7a8fdSMike Christie MODULE_LICENSE("GPL");
20aab7a8fdSMike Christie /*
21aab7a8fdSMike Christie  * The kobject and attribute structures.
22aab7a8fdSMike Christie  */
23aab7a8fdSMike Christie struct iscsi_boot_attr {
24aab7a8fdSMike Christie 	struct attribute attr;
25aab7a8fdSMike Christie 	int type;
26aab7a8fdSMike Christie 	ssize_t (*show) (void *data, int type, char *buf);
27aab7a8fdSMike Christie };
28aab7a8fdSMike Christie 
29aab7a8fdSMike Christie /*
30aab7a8fdSMike Christie  * The routine called for all sysfs attributes.
31aab7a8fdSMike Christie  */
iscsi_boot_show_attribute(struct kobject * kobj,struct attribute * attr,char * buf)32aab7a8fdSMike Christie static ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
33aab7a8fdSMike Christie 					 struct attribute *attr, char *buf)
34aab7a8fdSMike Christie {
35aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj =
36aab7a8fdSMike Christie 			container_of(kobj, struct iscsi_boot_kobj, kobj);
37aab7a8fdSMike Christie 	struct iscsi_boot_attr *boot_attr =
38aab7a8fdSMike Christie 			container_of(attr, struct iscsi_boot_attr, attr);
39aab7a8fdSMike Christie 	ssize_t ret = -EIO;
40aab7a8fdSMike Christie 	char *str = buf;
41aab7a8fdSMike Christie 
42aab7a8fdSMike Christie 	if (!capable(CAP_SYS_ADMIN))
43aab7a8fdSMike Christie 		return -EACCES;
44aab7a8fdSMike Christie 
45aab7a8fdSMike Christie 	if (boot_kobj->show)
46aab7a8fdSMike Christie 		ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
47aab7a8fdSMike Christie 	return ret;
48aab7a8fdSMike Christie }
49aab7a8fdSMike Christie 
50aab7a8fdSMike Christie static const struct sysfs_ops iscsi_boot_attr_ops = {
51aab7a8fdSMike Christie 	.show = iscsi_boot_show_attribute,
52aab7a8fdSMike Christie };
53aab7a8fdSMike Christie 
iscsi_boot_kobj_release(struct kobject * kobj)54aab7a8fdSMike Christie static void iscsi_boot_kobj_release(struct kobject *kobj)
55aab7a8fdSMike Christie {
56aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj =
57aab7a8fdSMike Christie 			container_of(kobj, struct iscsi_boot_kobj, kobj);
58aab7a8fdSMike Christie 
59f457a46fSMike Christie 	if (boot_kobj->release)
60f457a46fSMike Christie 		boot_kobj->release(boot_kobj->data);
61aab7a8fdSMike Christie 	kfree(boot_kobj);
62aab7a8fdSMike Christie }
63aab7a8fdSMike Christie 
64aab7a8fdSMike Christie static struct kobj_type iscsi_boot_ktype = {
65aab7a8fdSMike Christie 	.release = iscsi_boot_kobj_release,
66aab7a8fdSMike Christie 	.sysfs_ops = &iscsi_boot_attr_ops,
67aab7a8fdSMike Christie };
68aab7a8fdSMike Christie 
69aab7a8fdSMike Christie #define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type)		\
70aab7a8fdSMike Christie static struct iscsi_boot_attr iscsi_boot_attr_##fnname = {	\
71aab7a8fdSMike Christie 	.attr	= { .name = __stringify(sysfs_name), .mode = 0444 },	\
72aab7a8fdSMike Christie 	.type	= attr_type,						\
73aab7a8fdSMike Christie }
74aab7a8fdSMike Christie 
75aab7a8fdSMike Christie /* Target attrs */
76aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
77aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
78aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
79aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
80aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
81aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
82aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
83aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
84aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
85aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
86aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
87aab7a8fdSMike Christie 		   ISCSI_BOOT_TGT_REV_CHAP_NAME);
88aab7a8fdSMike Christie iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
89aab7a8fdSMike Christie 		   ISCSI_BOOT_TGT_REV_CHAP_SECRET);
90aab7a8fdSMike Christie 
91aab7a8fdSMike Christie static struct attribute *target_attrs[] = {
92aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_index.attr,
93aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_flags.attr,
94aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_ip.attr,
95aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_port.attr,
96aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_lun.attr,
97aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_chap.attr,
98aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_nic.attr,
99aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_name.attr,
100aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_chap_name.attr,
101aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_chap_secret.attr,
102aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_chap_rev_name.attr,
103aab7a8fdSMike Christie 	&iscsi_boot_attr_tgt_chap_rev_secret.attr,
104aab7a8fdSMike Christie 	NULL
105aab7a8fdSMike Christie };
106aab7a8fdSMike Christie 
iscsi_boot_tgt_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)107587a1f16SAl Viro static umode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
108aab7a8fdSMike Christie 					     struct attribute *attr, int i)
109aab7a8fdSMike Christie {
110aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj =
111aab7a8fdSMike Christie 			container_of(kobj, struct iscsi_boot_kobj, kobj);
112aab7a8fdSMike Christie 
113aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_tgt_index.attr)
114aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
115aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_INDEX);
116aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_flags.attr)
117aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
118aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_FLAGS);
119aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_ip.attr)
120aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
121aab7a8fdSMike Christie 					      ISCSI_BOOT_TGT_IP_ADDR);
122aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_port.attr)
123aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
124aab7a8fdSMike Christie 					      ISCSI_BOOT_TGT_PORT);
125aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_lun.attr)
126aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
127aab7a8fdSMike Christie 					      ISCSI_BOOT_TGT_LUN);
128aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_chap.attr)
129aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
130aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_CHAP_TYPE);
131aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_nic.attr)
132aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
133aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_NIC_ASSOC);
134aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_name.attr)
135aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
136aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_NAME);
137aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
138aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
139aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_CHAP_NAME);
140aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
141aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
142aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_CHAP_SECRET);
143aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
144aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
145aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_REV_CHAP_NAME);
146aab7a8fdSMike Christie 	else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
147aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
148aab7a8fdSMike Christie 					     ISCSI_BOOT_TGT_REV_CHAP_SECRET);
149aab7a8fdSMike Christie 	return 0;
150aab7a8fdSMike Christie }
151aab7a8fdSMike Christie 
152aab7a8fdSMike Christie static struct attribute_group iscsi_boot_target_attr_group = {
153aab7a8fdSMike Christie 	.attrs = target_attrs,
154aab7a8fdSMike Christie 	.is_visible = iscsi_boot_tgt_attr_is_visible,
155aab7a8fdSMike Christie };
156aab7a8fdSMike Christie 
157aab7a8fdSMike Christie /* Ethernet attrs */
158aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
159aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
160aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
1619a99425fSHannes Reinecke iscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
162aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
163aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
164aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
165aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
166aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
167aab7a8fdSMike Christie 		   ISCSI_BOOT_ETH_SECONDARY_DNS);
168aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
169aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
170aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
171aab7a8fdSMike Christie iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
172aab7a8fdSMike Christie 
173aab7a8fdSMike Christie static struct attribute *ethernet_attrs[] = {
174aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_index.attr,
175aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_flags.attr,
176aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_ip.attr,
1779a99425fSHannes Reinecke 	&iscsi_boot_attr_eth_prefix.attr,
178aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_subnet.attr,
179aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_origin.attr,
180aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_gateway.attr,
181aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_primary_dns.attr,
182aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_secondary_dns.attr,
183aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_dhcp.attr,
184aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_vlan.attr,
185aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_mac.attr,
186aab7a8fdSMike Christie 	&iscsi_boot_attr_eth_hostname.attr,
187aab7a8fdSMike Christie 	NULL
188aab7a8fdSMike Christie };
189aab7a8fdSMike Christie 
iscsi_boot_eth_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)190587a1f16SAl Viro static umode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
191aab7a8fdSMike Christie 					     struct attribute *attr, int i)
192aab7a8fdSMike Christie {
193aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj =
194aab7a8fdSMike Christie 			container_of(kobj, struct iscsi_boot_kobj, kobj);
195aab7a8fdSMike Christie 
196aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_eth_index.attr)
197aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
198aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_INDEX);
199aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_flags.attr)
200aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
201aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_FLAGS);
202aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
203aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
204aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_IP_ADDR);
2059a99425fSHannes Reinecke 	else if (attr ==  &iscsi_boot_attr_eth_prefix.attr)
2069a99425fSHannes Reinecke 		return boot_kobj->is_visible(boot_kobj->data,
2079a99425fSHannes Reinecke 					     ISCSI_BOOT_ETH_PREFIX_LEN);
208aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
209aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
210aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_SUBNET_MASK);
211aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_origin.attr)
212aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
213aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_ORIGIN);
214aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_gateway.attr)
215aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
216aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_GATEWAY);
217aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_primary_dns.attr)
218aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
219aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_PRIMARY_DNS);
220aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_secondary_dns.attr)
221aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
222aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_SECONDARY_DNS);
223aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_dhcp.attr)
224aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
225aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_DHCP);
226aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_vlan.attr)
227aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
228aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_VLAN);
229aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_mac.attr)
230aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
231aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_MAC);
232aab7a8fdSMike Christie 	else if (attr ==  &iscsi_boot_attr_eth_hostname.attr)
233aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
234aab7a8fdSMike Christie 					     ISCSI_BOOT_ETH_HOSTNAME);
235aab7a8fdSMike Christie 	return 0;
236aab7a8fdSMike Christie }
237aab7a8fdSMike Christie 
238aab7a8fdSMike Christie static struct attribute_group iscsi_boot_ethernet_attr_group = {
239aab7a8fdSMike Christie 	.attrs = ethernet_attrs,
240aab7a8fdSMike Christie 	.is_visible = iscsi_boot_eth_attr_is_visible,
241aab7a8fdSMike Christie };
242aab7a8fdSMike Christie 
243aab7a8fdSMike Christie /* Initiator attrs */
244aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
245aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
246aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
247aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
248aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
249aab7a8fdSMike Christie 		   ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
250aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
251aab7a8fdSMike Christie 		   ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
252aab7a8fdSMike Christie iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
253aab7a8fdSMike Christie 
254aab7a8fdSMike Christie static struct attribute *initiator_attrs[] = {
255aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_index.attr,
256aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_flags.attr,
257aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_isns.attr,
258aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_slp.attr,
259aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_primary_radius.attr,
260aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_secondary_radius.attr,
261aab7a8fdSMike Christie 	&iscsi_boot_attr_ini_name.attr,
262aab7a8fdSMike Christie 	NULL
263aab7a8fdSMike Christie };
264aab7a8fdSMike Christie 
iscsi_boot_ini_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)265587a1f16SAl Viro static umode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
266aab7a8fdSMike Christie 					     struct attribute *attr, int i)
267aab7a8fdSMike Christie {
268aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj =
269aab7a8fdSMike Christie 			container_of(kobj, struct iscsi_boot_kobj, kobj);
270aab7a8fdSMike Christie 
271aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_index.attr)
272aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
273aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_INDEX);
274aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_flags.attr)
275aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
276aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_FLAGS);
277aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_isns.attr)
278aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
279aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_ISNS_SERVER);
280aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_slp.attr)
281aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
282aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_SLP_SERVER);
283aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_primary_radius.attr)
284aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
285aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
286aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_secondary_radius.attr)
287aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
288aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
289aab7a8fdSMike Christie 	if (attr ==  &iscsi_boot_attr_ini_name.attr)
290aab7a8fdSMike Christie 		return boot_kobj->is_visible(boot_kobj->data,
291aab7a8fdSMike Christie 					     ISCSI_BOOT_INI_INITIATOR_NAME);
292aab7a8fdSMike Christie 
293aab7a8fdSMike Christie 	return 0;
294aab7a8fdSMike Christie }
295aab7a8fdSMike Christie 
296aab7a8fdSMike Christie static struct attribute_group iscsi_boot_initiator_attr_group = {
297aab7a8fdSMike Christie 	.attrs = initiator_attrs,
298aab7a8fdSMike Christie 	.is_visible = iscsi_boot_ini_attr_is_visible,
299aab7a8fdSMike Christie };
300aab7a8fdSMike Christie 
301b3c8eb50SDavid Bond /* iBFT ACPI Table attributes */
302b3c8eb50SDavid Bond iscsi_boot_rd_attr(acpitbl_signature, signature, ISCSI_BOOT_ACPITBL_SIGNATURE);
303b3c8eb50SDavid Bond iscsi_boot_rd_attr(acpitbl_oem_id, oem_id, ISCSI_BOOT_ACPITBL_OEM_ID);
304b3c8eb50SDavid Bond iscsi_boot_rd_attr(acpitbl_oem_table_id, oem_table_id,
305b3c8eb50SDavid Bond 		   ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
306b3c8eb50SDavid Bond 
307b3c8eb50SDavid Bond static struct attribute *acpitbl_attrs[] = {
308b3c8eb50SDavid Bond 	&iscsi_boot_attr_acpitbl_signature.attr,
309b3c8eb50SDavid Bond 	&iscsi_boot_attr_acpitbl_oem_id.attr,
310b3c8eb50SDavid Bond 	&iscsi_boot_attr_acpitbl_oem_table_id.attr,
311b3c8eb50SDavid Bond 	NULL
312b3c8eb50SDavid Bond };
313b3c8eb50SDavid Bond 
iscsi_boot_acpitbl_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)314b3c8eb50SDavid Bond static umode_t iscsi_boot_acpitbl_attr_is_visible(struct kobject *kobj,
315b3c8eb50SDavid Bond 					     struct attribute *attr, int i)
316b3c8eb50SDavid Bond {
317b3c8eb50SDavid Bond 	struct iscsi_boot_kobj *boot_kobj =
318b3c8eb50SDavid Bond 			container_of(kobj, struct iscsi_boot_kobj, kobj);
319b3c8eb50SDavid Bond 
320b3c8eb50SDavid Bond 	if (attr ==  &iscsi_boot_attr_acpitbl_signature.attr)
321b3c8eb50SDavid Bond 		return boot_kobj->is_visible(boot_kobj->data,
322b3c8eb50SDavid Bond 					     ISCSI_BOOT_ACPITBL_SIGNATURE);
323b3c8eb50SDavid Bond 	if (attr ==  &iscsi_boot_attr_acpitbl_oem_id.attr)
324b3c8eb50SDavid Bond 		return boot_kobj->is_visible(boot_kobj->data,
325b3c8eb50SDavid Bond 					     ISCSI_BOOT_ACPITBL_OEM_ID);
326b3c8eb50SDavid Bond 	if (attr ==  &iscsi_boot_attr_acpitbl_oem_table_id.attr)
327b3c8eb50SDavid Bond 		return boot_kobj->is_visible(boot_kobj->data,
328b3c8eb50SDavid Bond 					     ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
329b3c8eb50SDavid Bond 	return 0;
330b3c8eb50SDavid Bond }
331b3c8eb50SDavid Bond 
332b3c8eb50SDavid Bond static struct attribute_group iscsi_boot_acpitbl_attr_group = {
333b3c8eb50SDavid Bond 	.attrs = acpitbl_attrs,
334b3c8eb50SDavid Bond 	.is_visible = iscsi_boot_acpitbl_attr_is_visible,
335b3c8eb50SDavid Bond };
336b3c8eb50SDavid Bond 
337aab7a8fdSMike Christie static struct iscsi_boot_kobj *
iscsi_boot_create_kobj(struct iscsi_boot_kset * boot_kset,struct attribute_group * attr_group,const char * name,int index,void * data,ssize_t (* show)(void * data,int type,char * buf),umode_t (* is_visible)(void * data,int type),void (* release)(void * data))338aab7a8fdSMike Christie iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
339aab7a8fdSMike Christie 		       struct attribute_group *attr_group,
340aab7a8fdSMike Christie 		       const char *name, int index, void *data,
341aab7a8fdSMike Christie 		       ssize_t (*show) (void *data, int type, char *buf),
342587a1f16SAl Viro 		       umode_t (*is_visible) (void *data, int type),
343f457a46fSMike Christie 		       void (*release) (void *data))
344aab7a8fdSMike Christie {
345aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj;
346aab7a8fdSMike Christie 
347aab7a8fdSMike Christie 	boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
348aab7a8fdSMike Christie 	if (!boot_kobj)
349aab7a8fdSMike Christie 		return NULL;
350aab7a8fdSMike Christie 	INIT_LIST_HEAD(&boot_kobj->list);
351aab7a8fdSMike Christie 
352aab7a8fdSMike Christie 	boot_kobj->kobj.kset = boot_kset->kset;
353aab7a8fdSMike Christie 	if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
354aab7a8fdSMike Christie 				 NULL, name, index)) {
355*0267ffceSQiushi Wu 		kobject_put(&boot_kobj->kobj);
356aab7a8fdSMike Christie 		return NULL;
357aab7a8fdSMike Christie 	}
358aab7a8fdSMike Christie 	boot_kobj->data = data;
359aab7a8fdSMike Christie 	boot_kobj->show = show;
360aab7a8fdSMike Christie 	boot_kobj->is_visible = is_visible;
361f457a46fSMike Christie 	boot_kobj->release = release;
362aab7a8fdSMike Christie 
363aab7a8fdSMike Christie 	if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
364aab7a8fdSMike Christie 		/*
365aab7a8fdSMike Christie 		 * We do not want to free this because the caller
366aab7a8fdSMike Christie 		 * will assume that since the creation call failed
367aab7a8fdSMike Christie 		 * the boot kobj was not setup and the normal release
368aab7a8fdSMike Christie 		 * path is not being run.
369aab7a8fdSMike Christie 		 */
370f457a46fSMike Christie 		boot_kobj->release = NULL;
371aab7a8fdSMike Christie 		kobject_put(&boot_kobj->kobj);
372aab7a8fdSMike Christie 		return NULL;
373aab7a8fdSMike Christie 	}
374aab7a8fdSMike Christie 	boot_kobj->attr_group = attr_group;
375aab7a8fdSMike Christie 
376aab7a8fdSMike Christie 	kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
377aab7a8fdSMike Christie 	/* Nothing broke so lets add it to the list. */
378aab7a8fdSMike Christie 	list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
379aab7a8fdSMike Christie 	return boot_kobj;
380aab7a8fdSMike Christie }
381aab7a8fdSMike Christie 
iscsi_boot_remove_kobj(struct iscsi_boot_kobj * boot_kobj)382aab7a8fdSMike Christie static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
383aab7a8fdSMike Christie {
384aab7a8fdSMike Christie 	list_del(&boot_kobj->list);
385aab7a8fdSMike Christie 	sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
386aab7a8fdSMike Christie 	kobject_put(&boot_kobj->kobj);
387aab7a8fdSMike Christie }
388aab7a8fdSMike Christie 
389aab7a8fdSMike Christie /**
390aab7a8fdSMike Christie  * iscsi_boot_create_target() - create boot target sysfs dir
391aab7a8fdSMike Christie  * @boot_kset: boot kset
392aab7a8fdSMike Christie  * @index: the target id
393aab7a8fdSMike Christie  * @data: driver specific data for target
394aab7a8fdSMike Christie  * @show: attr show function
395aab7a8fdSMike Christie  * @is_visible: attr visibility function
396f457a46fSMike Christie  * @release: release function
397aab7a8fdSMike Christie  *
398aab7a8fdSMike Christie  * Note: The boot sysfs lib will free the data passed in for the caller
399aab7a8fdSMike Christie  * when all refs to the target kobject have been released.
400aab7a8fdSMike Christie  */
401aab7a8fdSMike Christie struct iscsi_boot_kobj *
iscsi_boot_create_target(struct iscsi_boot_kset * boot_kset,int index,void * data,ssize_t (* show)(void * data,int type,char * buf),umode_t (* is_visible)(void * data,int type),void (* release)(void * data))402aab7a8fdSMike Christie iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
403aab7a8fdSMike Christie 			 void *data,
404aab7a8fdSMike Christie 			 ssize_t (*show) (void *data, int type, char *buf),
405587a1f16SAl Viro 			 umode_t (*is_visible) (void *data, int type),
406f457a46fSMike Christie 			 void (*release) (void *data))
407aab7a8fdSMike Christie {
408aab7a8fdSMike Christie 	return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
409f457a46fSMike Christie 				      "target%d", index, data, show, is_visible,
410f457a46fSMike Christie 				      release);
411aab7a8fdSMike Christie }
412aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
413aab7a8fdSMike Christie 
414aab7a8fdSMike Christie /**
415aab7a8fdSMike Christie  * iscsi_boot_create_initiator() - create boot initiator sysfs dir
416aab7a8fdSMike Christie  * @boot_kset: boot kset
417aab7a8fdSMike Christie  * @index: the initiator id
418aab7a8fdSMike Christie  * @data: driver specific data
419aab7a8fdSMike Christie  * @show: attr show function
420aab7a8fdSMike Christie  * @is_visible: attr visibility function
421f457a46fSMike Christie  * @release: release function
422aab7a8fdSMike Christie  *
423aab7a8fdSMike Christie  * Note: The boot sysfs lib will free the data passed in for the caller
424aab7a8fdSMike Christie  * when all refs to the initiator kobject have been released.
425aab7a8fdSMike Christie  */
426aab7a8fdSMike Christie struct iscsi_boot_kobj *
iscsi_boot_create_initiator(struct iscsi_boot_kset * boot_kset,int index,void * data,ssize_t (* show)(void * data,int type,char * buf),umode_t (* is_visible)(void * data,int type),void (* release)(void * data))427aab7a8fdSMike Christie iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
428aab7a8fdSMike Christie 			    void *data,
429aab7a8fdSMike Christie 			    ssize_t (*show) (void *data, int type, char *buf),
430587a1f16SAl Viro 			    umode_t (*is_visible) (void *data, int type),
431f457a46fSMike Christie 			    void (*release) (void *data))
432aab7a8fdSMike Christie {
433aab7a8fdSMike Christie 	return iscsi_boot_create_kobj(boot_kset,
434aab7a8fdSMike Christie 				      &iscsi_boot_initiator_attr_group,
435aab7a8fdSMike Christie 				      "initiator", index, data, show,
436f457a46fSMike Christie 				      is_visible, release);
437aab7a8fdSMike Christie }
438aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
439aab7a8fdSMike Christie 
440aab7a8fdSMike Christie /**
441aab7a8fdSMike Christie  * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
442aab7a8fdSMike Christie  * @boot_kset: boot kset
443aab7a8fdSMike Christie  * @index: the ethernet device id
444aab7a8fdSMike Christie  * @data: driver specific data
445aab7a8fdSMike Christie  * @show: attr show function
446aab7a8fdSMike Christie  * @is_visible: attr visibility function
447f457a46fSMike Christie  * @release: release function
448aab7a8fdSMike Christie  *
449aab7a8fdSMike Christie  * Note: The boot sysfs lib will free the data passed in for the caller
450aab7a8fdSMike Christie  * when all refs to the ethernet kobject have been released.
451aab7a8fdSMike Christie  */
452aab7a8fdSMike Christie struct iscsi_boot_kobj *
iscsi_boot_create_ethernet(struct iscsi_boot_kset * boot_kset,int index,void * data,ssize_t (* show)(void * data,int type,char * buf),umode_t (* is_visible)(void * data,int type),void (* release)(void * data))453aab7a8fdSMike Christie iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
454aab7a8fdSMike Christie 			   void *data,
455aab7a8fdSMike Christie 			   ssize_t (*show) (void *data, int type, char *buf),
456587a1f16SAl Viro 			   umode_t (*is_visible) (void *data, int type),
457f457a46fSMike Christie 			   void (*release) (void *data))
458aab7a8fdSMike Christie {
459aab7a8fdSMike Christie 	return iscsi_boot_create_kobj(boot_kset,
460aab7a8fdSMike Christie 				      &iscsi_boot_ethernet_attr_group,
461aab7a8fdSMike Christie 				      "ethernet%d", index, data, show,
462f457a46fSMike Christie 				      is_visible, release);
463aab7a8fdSMike Christie }
464aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
465aab7a8fdSMike Christie 
466aab7a8fdSMike Christie /**
467b3c8eb50SDavid Bond  * iscsi_boot_create_acpitbl() - create boot acpi table sysfs dir
468b3c8eb50SDavid Bond  * @boot_kset: boot kset
469b3c8eb50SDavid Bond  * @index: not used
470b3c8eb50SDavid Bond  * @data: driver specific data
471b3c8eb50SDavid Bond  * @show: attr show function
472b3c8eb50SDavid Bond  * @is_visible: attr visibility function
473b3c8eb50SDavid Bond  * @release: release function
474b3c8eb50SDavid Bond  *
475b3c8eb50SDavid Bond  * Note: The boot sysfs lib will free the data passed in for the caller
476b3c8eb50SDavid Bond  * when all refs to the acpitbl kobject have been released.
477b3c8eb50SDavid Bond  */
478b3c8eb50SDavid Bond struct iscsi_boot_kobj *
iscsi_boot_create_acpitbl(struct iscsi_boot_kset * boot_kset,int index,void * data,ssize_t (* show)(void * data,int type,char * buf),umode_t (* is_visible)(void * data,int type),void (* release)(void * data))479b3c8eb50SDavid Bond iscsi_boot_create_acpitbl(struct iscsi_boot_kset *boot_kset, int index,
480b3c8eb50SDavid Bond 			   void *data,
481b3c8eb50SDavid Bond 			   ssize_t (*show)(void *data, int type, char *buf),
482b3c8eb50SDavid Bond 			   umode_t (*is_visible)(void *data, int type),
483b3c8eb50SDavid Bond 			   void (*release)(void *data))
484b3c8eb50SDavid Bond {
485b3c8eb50SDavid Bond 	return iscsi_boot_create_kobj(boot_kset,
486b3c8eb50SDavid Bond 				      &iscsi_boot_acpitbl_attr_group,
487b3c8eb50SDavid Bond 				      "acpi_header", index, data, show,
488b3c8eb50SDavid Bond 				      is_visible, release);
489b3c8eb50SDavid Bond }
490b3c8eb50SDavid Bond EXPORT_SYMBOL_GPL(iscsi_boot_create_acpitbl);
491b3c8eb50SDavid Bond 
492b3c8eb50SDavid Bond /**
493aab7a8fdSMike Christie  * iscsi_boot_create_kset() - creates root sysfs tree
494aab7a8fdSMike Christie  * @set_name: name of root dir
495aab7a8fdSMike Christie  */
iscsi_boot_create_kset(const char * set_name)496aab7a8fdSMike Christie struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
497aab7a8fdSMike Christie {
498aab7a8fdSMike Christie 	struct iscsi_boot_kset *boot_kset;
499aab7a8fdSMike Christie 
500aab7a8fdSMike Christie 	boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
501aab7a8fdSMike Christie 	if (!boot_kset)
502aab7a8fdSMike Christie 		return NULL;
503aab7a8fdSMike Christie 
504aab7a8fdSMike Christie 	boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
505aab7a8fdSMike Christie 	if (!boot_kset->kset) {
506aab7a8fdSMike Christie 		kfree(boot_kset);
507aab7a8fdSMike Christie 		return NULL;
508aab7a8fdSMike Christie 	}
509aab7a8fdSMike Christie 
510aab7a8fdSMike Christie 	INIT_LIST_HEAD(&boot_kset->kobj_list);
511aab7a8fdSMike Christie 	return boot_kset;
512aab7a8fdSMike Christie }
513aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
514aab7a8fdSMike Christie 
515aab7a8fdSMike Christie /**
516aab7a8fdSMike Christie  * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
517aab7a8fdSMike Christie  * @hostno: host number of scsi host
518aab7a8fdSMike Christie  */
iscsi_boot_create_host_kset(unsigned int hostno)519aab7a8fdSMike Christie struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
520aab7a8fdSMike Christie {
521aab7a8fdSMike Christie 	struct iscsi_boot_kset *boot_kset;
522aab7a8fdSMike Christie 	char *set_name;
523aab7a8fdSMike Christie 
524aab7a8fdSMike Christie 	set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
525aab7a8fdSMike Christie 	if (!set_name)
526aab7a8fdSMike Christie 		return NULL;
527aab7a8fdSMike Christie 
528aab7a8fdSMike Christie 	boot_kset = iscsi_boot_create_kset(set_name);
529aab7a8fdSMike Christie 	kfree(set_name);
530aab7a8fdSMike Christie 	return boot_kset;
531aab7a8fdSMike Christie }
532aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
533aab7a8fdSMike Christie 
534aab7a8fdSMike Christie /**
535aab7a8fdSMike Christie  * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
536aab7a8fdSMike Christie  * @boot_kset: boot kset
537aab7a8fdSMike Christie  *
538aab7a8fdSMike Christie  * This will remove the kset and kobjects and attrs under it.
539aab7a8fdSMike Christie  */
iscsi_boot_destroy_kset(struct iscsi_boot_kset * boot_kset)540aab7a8fdSMike Christie void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
541aab7a8fdSMike Christie {
542aab7a8fdSMike Christie 	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
543aab7a8fdSMike Christie 
5449d045163SMike Christie 	if (!boot_kset)
5459d045163SMike Christie 		return;
5469d045163SMike Christie 
547aab7a8fdSMike Christie 	list_for_each_entry_safe(boot_kobj, tmp_kobj,
548aab7a8fdSMike Christie 				 &boot_kset->kobj_list, list)
549aab7a8fdSMike Christie 		iscsi_boot_remove_kobj(boot_kobj);
550aab7a8fdSMike Christie 
551aab7a8fdSMike Christie 	kset_unregister(boot_kset->kset);
5529cb48e7bSEthan Zhao 	kfree(boot_kset);
553aab7a8fdSMike Christie }
554aab7a8fdSMike Christie EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
555