18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Export the iSCSI boot info to userland via sysfs.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010 Red Hat, Inc.  All rights reserved.
68c2ecf20Sopenharmony_ci * Copyright (C) 2010 Mike Christie
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/string.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
138c2ecf20Sopenharmony_ci#include <linux/capability.h>
148c2ecf20Sopenharmony_ci#include <linux/iscsi_boot_sysfs.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
188c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information");
198c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
208c2ecf20Sopenharmony_ci/*
218c2ecf20Sopenharmony_ci * The kobject and attribute structures.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_cistruct iscsi_boot_attr {
248c2ecf20Sopenharmony_ci	struct attribute attr;
258c2ecf20Sopenharmony_ci	int type;
268c2ecf20Sopenharmony_ci	ssize_t (*show) (void *data, int type, char *buf);
278c2ecf20Sopenharmony_ci};
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/*
308c2ecf20Sopenharmony_ci * The routine called for all sysfs attributes.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_cistatic ssize_t iscsi_boot_show_attribute(struct kobject *kobj,
338c2ecf20Sopenharmony_ci					 struct attribute *attr, char *buf)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
368c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
378c2ecf20Sopenharmony_ci	struct iscsi_boot_attr *boot_attr =
388c2ecf20Sopenharmony_ci			container_of(attr, struct iscsi_boot_attr, attr);
398c2ecf20Sopenharmony_ci	ssize_t ret = -EIO;
408c2ecf20Sopenharmony_ci	char *str = buf;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (!capable(CAP_SYS_ADMIN))
438c2ecf20Sopenharmony_ci		return -EACCES;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (boot_kobj->show)
468c2ecf20Sopenharmony_ci		ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str);
478c2ecf20Sopenharmony_ci	return ret;
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic const struct sysfs_ops iscsi_boot_attr_ops = {
518c2ecf20Sopenharmony_ci	.show = iscsi_boot_show_attribute,
528c2ecf20Sopenharmony_ci};
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic void iscsi_boot_kobj_release(struct kobject *kobj)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
578c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	if (boot_kobj->release)
608c2ecf20Sopenharmony_ci		boot_kobj->release(boot_kobj->data);
618c2ecf20Sopenharmony_ci	kfree(boot_kobj);
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic struct kobj_type iscsi_boot_ktype = {
658c2ecf20Sopenharmony_ci	.release = iscsi_boot_kobj_release,
668c2ecf20Sopenharmony_ci	.sysfs_ops = &iscsi_boot_attr_ops,
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type)		\
708c2ecf20Sopenharmony_cistatic struct iscsi_boot_attr iscsi_boot_attr_##fnname = {	\
718c2ecf20Sopenharmony_ci	.attr	= { .name = __stringify(sysfs_name), .mode = 0444 },	\
728c2ecf20Sopenharmony_ci	.type	= attr_type,						\
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/* Target attrs */
768c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX);
778c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS);
788c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR);
798c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT);
808c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN);
818c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE);
828c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC);
838c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME);
848c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME);
858c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET);
868c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name,
878c2ecf20Sopenharmony_ci		   ISCSI_BOOT_TGT_REV_CHAP_NAME);
888c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret,
898c2ecf20Sopenharmony_ci		   ISCSI_BOOT_TGT_REV_CHAP_SECRET);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic struct attribute *target_attrs[] = {
928c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_index.attr,
938c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_flags.attr,
948c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_ip.attr,
958c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_port.attr,
968c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_lun.attr,
978c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_chap.attr,
988c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_nic.attr,
998c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_name.attr,
1008c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_chap_name.attr,
1018c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_chap_secret.attr,
1028c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_chap_rev_name.attr,
1038c2ecf20Sopenharmony_ci	&iscsi_boot_attr_tgt_chap_rev_secret.attr,
1048c2ecf20Sopenharmony_ci	NULL
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic umode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj,
1088c2ecf20Sopenharmony_ci					     struct attribute *attr, int i)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
1118c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_tgt_index.attr)
1148c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1158c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_INDEX);
1168c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_flags.attr)
1178c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1188c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_FLAGS);
1198c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_ip.attr)
1208c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1218c2ecf20Sopenharmony_ci					      ISCSI_BOOT_TGT_IP_ADDR);
1228c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_port.attr)
1238c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1248c2ecf20Sopenharmony_ci					      ISCSI_BOOT_TGT_PORT);
1258c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_lun.attr)
1268c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1278c2ecf20Sopenharmony_ci					      ISCSI_BOOT_TGT_LUN);
1288c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_chap.attr)
1298c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1308c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_CHAP_TYPE);
1318c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_nic.attr)
1328c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1338c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_NIC_ASSOC);
1348c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_name.attr)
1358c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1368c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_NAME);
1378c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_chap_name.attr)
1388c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1398c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_CHAP_NAME);
1408c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr)
1418c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1428c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_CHAP_SECRET);
1438c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr)
1448c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1458c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_REV_CHAP_NAME);
1468c2ecf20Sopenharmony_ci	else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr)
1478c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1488c2ecf20Sopenharmony_ci					     ISCSI_BOOT_TGT_REV_CHAP_SECRET);
1498c2ecf20Sopenharmony_ci	return 0;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic struct attribute_group iscsi_boot_target_attr_group = {
1538c2ecf20Sopenharmony_ci	.attrs = target_attrs,
1548c2ecf20Sopenharmony_ci	.is_visible = iscsi_boot_tgt_attr_is_visible,
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/* Ethernet attrs */
1588c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
1598c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
1608c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
1618c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
1628c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
1638c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
1648c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
1658c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS);
1668c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_secondary_dns, secondary-dns,
1678c2ecf20Sopenharmony_ci		   ISCSI_BOOT_ETH_SECONDARY_DNS);
1688c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP);
1698c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN);
1708c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC);
1718c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic struct attribute *ethernet_attrs[] = {
1748c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_index.attr,
1758c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_flags.attr,
1768c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_ip.attr,
1778c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_prefix.attr,
1788c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_subnet.attr,
1798c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_origin.attr,
1808c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_gateway.attr,
1818c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_primary_dns.attr,
1828c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_secondary_dns.attr,
1838c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_dhcp.attr,
1848c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_vlan.attr,
1858c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_mac.attr,
1868c2ecf20Sopenharmony_ci	&iscsi_boot_attr_eth_hostname.attr,
1878c2ecf20Sopenharmony_ci	NULL
1888c2ecf20Sopenharmony_ci};
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic umode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
1918c2ecf20Sopenharmony_ci					     struct attribute *attr, int i)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
1948c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_eth_index.attr)
1978c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
1988c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_INDEX);
1998c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_flags.attr)
2008c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2018c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_FLAGS);
2028c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
2038c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2048c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_IP_ADDR);
2058c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_prefix.attr)
2068c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2078c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_PREFIX_LEN);
2088c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
2098c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2108c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_SUBNET_MASK);
2118c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_origin.attr)
2128c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2138c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_ORIGIN);
2148c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_gateway.attr)
2158c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2168c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_GATEWAY);
2178c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_primary_dns.attr)
2188c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2198c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_PRIMARY_DNS);
2208c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_secondary_dns.attr)
2218c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2228c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_SECONDARY_DNS);
2238c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_dhcp.attr)
2248c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2258c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_DHCP);
2268c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_vlan.attr)
2278c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2288c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_VLAN);
2298c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_mac.attr)
2308c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2318c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_MAC);
2328c2ecf20Sopenharmony_ci	else if (attr ==  &iscsi_boot_attr_eth_hostname.attr)
2338c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2348c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ETH_HOSTNAME);
2358c2ecf20Sopenharmony_ci	return 0;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic struct attribute_group iscsi_boot_ethernet_attr_group = {
2398c2ecf20Sopenharmony_ci	.attrs = ethernet_attrs,
2408c2ecf20Sopenharmony_ci	.is_visible = iscsi_boot_eth_attr_is_visible,
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/* Initiator attrs */
2448c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX);
2458c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS);
2468c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER);
2478c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER);
2488c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_primary_radius, pri-radius-server,
2498c2ecf20Sopenharmony_ci		   ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
2508c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server,
2518c2ecf20Sopenharmony_ci		   ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
2528c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic struct attribute *initiator_attrs[] = {
2558c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_index.attr,
2568c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_flags.attr,
2578c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_isns.attr,
2588c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_slp.attr,
2598c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_primary_radius.attr,
2608c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_secondary_radius.attr,
2618c2ecf20Sopenharmony_ci	&iscsi_boot_attr_ini_name.attr,
2628c2ecf20Sopenharmony_ci	NULL
2638c2ecf20Sopenharmony_ci};
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic umode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj,
2668c2ecf20Sopenharmony_ci					     struct attribute *attr, int i)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
2698c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_index.attr)
2728c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2738c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_INDEX);
2748c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_flags.attr)
2758c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2768c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_FLAGS);
2778c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_isns.attr)
2788c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2798c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_ISNS_SERVER);
2808c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_slp.attr)
2818c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2828c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_SLP_SERVER);
2838c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_primary_radius.attr)
2848c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2858c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_PRI_RADIUS_SERVER);
2868c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_secondary_radius.attr)
2878c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2888c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_SEC_RADIUS_SERVER);
2898c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_ini_name.attr)
2908c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
2918c2ecf20Sopenharmony_ci					     ISCSI_BOOT_INI_INITIATOR_NAME);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	return 0;
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic struct attribute_group iscsi_boot_initiator_attr_group = {
2978c2ecf20Sopenharmony_ci	.attrs = initiator_attrs,
2988c2ecf20Sopenharmony_ci	.is_visible = iscsi_boot_ini_attr_is_visible,
2998c2ecf20Sopenharmony_ci};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci/* iBFT ACPI Table attributes */
3028c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(acpitbl_signature, signature, ISCSI_BOOT_ACPITBL_SIGNATURE);
3038c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(acpitbl_oem_id, oem_id, ISCSI_BOOT_ACPITBL_OEM_ID);
3048c2ecf20Sopenharmony_ciiscsi_boot_rd_attr(acpitbl_oem_table_id, oem_table_id,
3058c2ecf20Sopenharmony_ci		   ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic struct attribute *acpitbl_attrs[] = {
3088c2ecf20Sopenharmony_ci	&iscsi_boot_attr_acpitbl_signature.attr,
3098c2ecf20Sopenharmony_ci	&iscsi_boot_attr_acpitbl_oem_id.attr,
3108c2ecf20Sopenharmony_ci	&iscsi_boot_attr_acpitbl_oem_table_id.attr,
3118c2ecf20Sopenharmony_ci	NULL
3128c2ecf20Sopenharmony_ci};
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic umode_t iscsi_boot_acpitbl_attr_is_visible(struct kobject *kobj,
3158c2ecf20Sopenharmony_ci					     struct attribute *attr, int i)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj =
3188c2ecf20Sopenharmony_ci			container_of(kobj, struct iscsi_boot_kobj, kobj);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_acpitbl_signature.attr)
3218c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
3228c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ACPITBL_SIGNATURE);
3238c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_acpitbl_oem_id.attr)
3248c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
3258c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ACPITBL_OEM_ID);
3268c2ecf20Sopenharmony_ci	if (attr ==  &iscsi_boot_attr_acpitbl_oem_table_id.attr)
3278c2ecf20Sopenharmony_ci		return boot_kobj->is_visible(boot_kobj->data,
3288c2ecf20Sopenharmony_ci					     ISCSI_BOOT_ACPITBL_OEM_TABLE_ID);
3298c2ecf20Sopenharmony_ci	return 0;
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic struct attribute_group iscsi_boot_acpitbl_attr_group = {
3338c2ecf20Sopenharmony_ci	.attrs = acpitbl_attrs,
3348c2ecf20Sopenharmony_ci	.is_visible = iscsi_boot_acpitbl_attr_is_visible,
3358c2ecf20Sopenharmony_ci};
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic struct iscsi_boot_kobj *
3388c2ecf20Sopenharmony_ciiscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
3398c2ecf20Sopenharmony_ci		       struct attribute_group *attr_group,
3408c2ecf20Sopenharmony_ci		       const char *name, int index, void *data,
3418c2ecf20Sopenharmony_ci		       ssize_t (*show) (void *data, int type, char *buf),
3428c2ecf20Sopenharmony_ci		       umode_t (*is_visible) (void *data, int type),
3438c2ecf20Sopenharmony_ci		       void (*release) (void *data))
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL);
3488c2ecf20Sopenharmony_ci	if (!boot_kobj)
3498c2ecf20Sopenharmony_ci		return NULL;
3508c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&boot_kobj->list);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	boot_kobj->kobj.kset = boot_kset->kset;
3538c2ecf20Sopenharmony_ci	if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
3548c2ecf20Sopenharmony_ci				 NULL, name, index)) {
3558c2ecf20Sopenharmony_ci		kobject_put(&boot_kobj->kobj);
3568c2ecf20Sopenharmony_ci		return NULL;
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci	boot_kobj->data = data;
3598c2ecf20Sopenharmony_ci	boot_kobj->show = show;
3608c2ecf20Sopenharmony_ci	boot_kobj->is_visible = is_visible;
3618c2ecf20Sopenharmony_ci	boot_kobj->release = release;
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
3648c2ecf20Sopenharmony_ci		/*
3658c2ecf20Sopenharmony_ci		 * We do not want to free this because the caller
3668c2ecf20Sopenharmony_ci		 * will assume that since the creation call failed
3678c2ecf20Sopenharmony_ci		 * the boot kobj was not setup and the normal release
3688c2ecf20Sopenharmony_ci		 * path is not being run.
3698c2ecf20Sopenharmony_ci		 */
3708c2ecf20Sopenharmony_ci		boot_kobj->release = NULL;
3718c2ecf20Sopenharmony_ci		kobject_put(&boot_kobj->kobj);
3728c2ecf20Sopenharmony_ci		return NULL;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci	boot_kobj->attr_group = attr_group;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	kobject_uevent(&boot_kobj->kobj, KOBJ_ADD);
3778c2ecf20Sopenharmony_ci	/* Nothing broke so lets add it to the list. */
3788c2ecf20Sopenharmony_ci	list_add_tail(&boot_kobj->list, &boot_kset->kobj_list);
3798c2ecf20Sopenharmony_ci	return boot_kobj;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	list_del(&boot_kobj->list);
3858c2ecf20Sopenharmony_ci	sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group);
3868c2ecf20Sopenharmony_ci	kobject_put(&boot_kobj->kobj);
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci/**
3908c2ecf20Sopenharmony_ci * iscsi_boot_create_target() - create boot target sysfs dir
3918c2ecf20Sopenharmony_ci * @boot_kset: boot kset
3928c2ecf20Sopenharmony_ci * @index: the target id
3938c2ecf20Sopenharmony_ci * @data: driver specific data for target
3948c2ecf20Sopenharmony_ci * @show: attr show function
3958c2ecf20Sopenharmony_ci * @is_visible: attr visibility function
3968c2ecf20Sopenharmony_ci * @release: release function
3978c2ecf20Sopenharmony_ci *
3988c2ecf20Sopenharmony_ci * Note: The boot sysfs lib will free the data passed in for the caller
3998c2ecf20Sopenharmony_ci * when all refs to the target kobject have been released.
4008c2ecf20Sopenharmony_ci */
4018c2ecf20Sopenharmony_cistruct iscsi_boot_kobj *
4028c2ecf20Sopenharmony_ciiscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
4038c2ecf20Sopenharmony_ci			 void *data,
4048c2ecf20Sopenharmony_ci			 ssize_t (*show) (void *data, int type, char *buf),
4058c2ecf20Sopenharmony_ci			 umode_t (*is_visible) (void *data, int type),
4068c2ecf20Sopenharmony_ci			 void (*release) (void *data))
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
4098c2ecf20Sopenharmony_ci				      "target%d", index, data, show, is_visible,
4108c2ecf20Sopenharmony_ci				      release);
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_target);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci/**
4158c2ecf20Sopenharmony_ci * iscsi_boot_create_initiator() - create boot initiator sysfs dir
4168c2ecf20Sopenharmony_ci * @boot_kset: boot kset
4178c2ecf20Sopenharmony_ci * @index: the initiator id
4188c2ecf20Sopenharmony_ci * @data: driver specific data
4198c2ecf20Sopenharmony_ci * @show: attr show function
4208c2ecf20Sopenharmony_ci * @is_visible: attr visibility function
4218c2ecf20Sopenharmony_ci * @release: release function
4228c2ecf20Sopenharmony_ci *
4238c2ecf20Sopenharmony_ci * Note: The boot sysfs lib will free the data passed in for the caller
4248c2ecf20Sopenharmony_ci * when all refs to the initiator kobject have been released.
4258c2ecf20Sopenharmony_ci */
4268c2ecf20Sopenharmony_cistruct iscsi_boot_kobj *
4278c2ecf20Sopenharmony_ciiscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
4288c2ecf20Sopenharmony_ci			    void *data,
4298c2ecf20Sopenharmony_ci			    ssize_t (*show) (void *data, int type, char *buf),
4308c2ecf20Sopenharmony_ci			    umode_t (*is_visible) (void *data, int type),
4318c2ecf20Sopenharmony_ci			    void (*release) (void *data))
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	return iscsi_boot_create_kobj(boot_kset,
4348c2ecf20Sopenharmony_ci				      &iscsi_boot_initiator_attr_group,
4358c2ecf20Sopenharmony_ci				      "initiator", index, data, show,
4368c2ecf20Sopenharmony_ci				      is_visible, release);
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci/**
4418c2ecf20Sopenharmony_ci * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir
4428c2ecf20Sopenharmony_ci * @boot_kset: boot kset
4438c2ecf20Sopenharmony_ci * @index: the ethernet device id
4448c2ecf20Sopenharmony_ci * @data: driver specific data
4458c2ecf20Sopenharmony_ci * @show: attr show function
4468c2ecf20Sopenharmony_ci * @is_visible: attr visibility function
4478c2ecf20Sopenharmony_ci * @release: release function
4488c2ecf20Sopenharmony_ci *
4498c2ecf20Sopenharmony_ci * Note: The boot sysfs lib will free the data passed in for the caller
4508c2ecf20Sopenharmony_ci * when all refs to the ethernet kobject have been released.
4518c2ecf20Sopenharmony_ci */
4528c2ecf20Sopenharmony_cistruct iscsi_boot_kobj *
4538c2ecf20Sopenharmony_ciiscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
4548c2ecf20Sopenharmony_ci			   void *data,
4558c2ecf20Sopenharmony_ci			   ssize_t (*show) (void *data, int type, char *buf),
4568c2ecf20Sopenharmony_ci			   umode_t (*is_visible) (void *data, int type),
4578c2ecf20Sopenharmony_ci			   void (*release) (void *data))
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	return iscsi_boot_create_kobj(boot_kset,
4608c2ecf20Sopenharmony_ci				      &iscsi_boot_ethernet_attr_group,
4618c2ecf20Sopenharmony_ci				      "ethernet%d", index, data, show,
4628c2ecf20Sopenharmony_ci				      is_visible, release);
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci/**
4678c2ecf20Sopenharmony_ci * iscsi_boot_create_acpitbl() - create boot acpi table sysfs dir
4688c2ecf20Sopenharmony_ci * @boot_kset: boot kset
4698c2ecf20Sopenharmony_ci * @index: not used
4708c2ecf20Sopenharmony_ci * @data: driver specific data
4718c2ecf20Sopenharmony_ci * @show: attr show function
4728c2ecf20Sopenharmony_ci * @is_visible: attr visibility function
4738c2ecf20Sopenharmony_ci * @release: release function
4748c2ecf20Sopenharmony_ci *
4758c2ecf20Sopenharmony_ci * Note: The boot sysfs lib will free the data passed in for the caller
4768c2ecf20Sopenharmony_ci * when all refs to the acpitbl kobject have been released.
4778c2ecf20Sopenharmony_ci */
4788c2ecf20Sopenharmony_cistruct iscsi_boot_kobj *
4798c2ecf20Sopenharmony_ciiscsi_boot_create_acpitbl(struct iscsi_boot_kset *boot_kset, int index,
4808c2ecf20Sopenharmony_ci			   void *data,
4818c2ecf20Sopenharmony_ci			   ssize_t (*show)(void *data, int type, char *buf),
4828c2ecf20Sopenharmony_ci			   umode_t (*is_visible)(void *data, int type),
4838c2ecf20Sopenharmony_ci			   void (*release)(void *data))
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	return iscsi_boot_create_kobj(boot_kset,
4868c2ecf20Sopenharmony_ci				      &iscsi_boot_acpitbl_attr_group,
4878c2ecf20Sopenharmony_ci				      "acpi_header", index, data, show,
4888c2ecf20Sopenharmony_ci				      is_visible, release);
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_acpitbl);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/**
4938c2ecf20Sopenharmony_ci * iscsi_boot_create_kset() - creates root sysfs tree
4948c2ecf20Sopenharmony_ci * @set_name: name of root dir
4958c2ecf20Sopenharmony_ci */
4968c2ecf20Sopenharmony_cistruct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct iscsi_boot_kset *boot_kset;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL);
5018c2ecf20Sopenharmony_ci	if (!boot_kset)
5028c2ecf20Sopenharmony_ci		return NULL;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj);
5058c2ecf20Sopenharmony_ci	if (!boot_kset->kset) {
5068c2ecf20Sopenharmony_ci		kfree(boot_kset);
5078c2ecf20Sopenharmony_ci		return NULL;
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&boot_kset->kobj_list);
5118c2ecf20Sopenharmony_ci	return boot_kset;
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_kset);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci/**
5168c2ecf20Sopenharmony_ci * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host
5178c2ecf20Sopenharmony_ci * @hostno: host number of scsi host
5188c2ecf20Sopenharmony_ci */
5198c2ecf20Sopenharmony_cistruct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	struct iscsi_boot_kset *boot_kset;
5228c2ecf20Sopenharmony_ci	char *set_name;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno);
5258c2ecf20Sopenharmony_ci	if (!set_name)
5268c2ecf20Sopenharmony_ci		return NULL;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	boot_kset = iscsi_boot_create_kset(set_name);
5298c2ecf20Sopenharmony_ci	kfree(set_name);
5308c2ecf20Sopenharmony_ci	return boot_kset;
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci/**
5358c2ecf20Sopenharmony_ci * iscsi_boot_destroy_kset() - destroy kset and kobjects under it
5368c2ecf20Sopenharmony_ci * @boot_kset: boot kset
5378c2ecf20Sopenharmony_ci *
5388c2ecf20Sopenharmony_ci * This will remove the kset and kobjects and attrs under it.
5398c2ecf20Sopenharmony_ci */
5408c2ecf20Sopenharmony_civoid iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	if (!boot_kset)
5458c2ecf20Sopenharmony_ci		return;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	list_for_each_entry_safe(boot_kobj, tmp_kobj,
5488c2ecf20Sopenharmony_ci				 &boot_kset->kobj_list, list)
5498c2ecf20Sopenharmony_ci		iscsi_boot_remove_kobj(boot_kobj);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	kset_unregister(boot_kset->kset);
5528c2ecf20Sopenharmony_ci	kfree(boot_kset);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
555