cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iscsi_boot_sysfs.c (18687B)


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