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