Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft-2.6:
ibft: Use IBFT_SIGN instead of open-coding the search string.
ibft: convert iscsi_ibft module to iscsi boot lib
ibft: separate ibft parsing from sysfs interface
ibft: For UEFI machines actually do scan ACPI for iBFT.
ibft: Update iBFT handling for v1.03 of the spec.

+924 -484
+9
drivers/firmware/Kconfig
··· 122 122 is necessary for iSCSI Boot Firmware Table Attributes module to work 123 123 properly. 124 124 125 + config ISCSI_BOOT_SYSFS 126 + tristate "iSCSI Boot Sysfs Interface" 127 + default n 128 + help 129 + This option enables support for exposing iSCSI boot information 130 + via sysfs to userspace. If you wish to export this information, 131 + say Y. Otherwise, say N. 132 + 125 133 config ISCSI_IBFT 126 134 tristate "iSCSI Boot Firmware Table Attributes module" 135 + select ISCSI_BOOT_SYSFS 127 136 depends on ISCSI_IBFT_FIND 128 137 default n 129 138 help
+1
drivers/firmware/Makefile
··· 10 10 obj-$(CONFIG_DMIID) += dmi-id.o 11 11 obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 12 12 obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o 13 + obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o 13 14 obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
+481
drivers/firmware/iscsi_boot_sysfs.c
··· 1 + /* 2 + * Export the iSCSI boot info to userland via sysfs. 3 + * 4 + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. 5 + * Copyright (C) 2010 Mike Christie 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License v2.0 as published by 9 + * the Free Software Foundation 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #include <linux/module.h> 18 + #include <linux/string.h> 19 + #include <linux/slab.h> 20 + #include <linux/sysfs.h> 21 + #include <linux/capability.h> 22 + #include <linux/iscsi_boot_sysfs.h> 23 + 24 + 25 + MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>"); 26 + MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information"); 27 + MODULE_LICENSE("GPL"); 28 + /* 29 + * The kobject and attribute structures. 30 + */ 31 + struct iscsi_boot_attr { 32 + struct attribute attr; 33 + int type; 34 + ssize_t (*show) (void *data, int type, char *buf); 35 + }; 36 + 37 + /* 38 + * The routine called for all sysfs attributes. 39 + */ 40 + static ssize_t iscsi_boot_show_attribute(struct kobject *kobj, 41 + struct attribute *attr, char *buf) 42 + { 43 + struct iscsi_boot_kobj *boot_kobj = 44 + container_of(kobj, struct iscsi_boot_kobj, kobj); 45 + struct iscsi_boot_attr *boot_attr = 46 + container_of(attr, struct iscsi_boot_attr, attr); 47 + ssize_t ret = -EIO; 48 + char *str = buf; 49 + 50 + if (!capable(CAP_SYS_ADMIN)) 51 + return -EACCES; 52 + 53 + if (boot_kobj->show) 54 + ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str); 55 + return ret; 56 + } 57 + 58 + static const struct sysfs_ops iscsi_boot_attr_ops = { 59 + .show = iscsi_boot_show_attribute, 60 + }; 61 + 62 + static void iscsi_boot_kobj_release(struct kobject *kobj) 63 + { 64 + struct iscsi_boot_kobj *boot_kobj = 65 + container_of(kobj, struct iscsi_boot_kobj, kobj); 66 + 67 + kfree(boot_kobj->data); 68 + kfree(boot_kobj); 69 + } 70 + 71 + static struct kobj_type iscsi_boot_ktype = { 72 + .release = iscsi_boot_kobj_release, 73 + .sysfs_ops = &iscsi_boot_attr_ops, 74 + }; 75 + 76 + #define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type) \ 77 + static struct iscsi_boot_attr iscsi_boot_attr_##fnname = { \ 78 + .attr = { .name = __stringify(sysfs_name), .mode = 0444 }, \ 79 + .type = attr_type, \ 80 + } 81 + 82 + /* Target attrs */ 83 + iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX); 84 + iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS); 85 + iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR); 86 + iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT); 87 + iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN); 88 + iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE); 89 + iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC); 90 + iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME); 91 + iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME); 92 + iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET); 93 + iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name, 94 + ISCSI_BOOT_TGT_REV_CHAP_NAME); 95 + iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret, 96 + ISCSI_BOOT_TGT_REV_CHAP_SECRET); 97 + 98 + static struct attribute *target_attrs[] = { 99 + &iscsi_boot_attr_tgt_index.attr, 100 + &iscsi_boot_attr_tgt_flags.attr, 101 + &iscsi_boot_attr_tgt_ip.attr, 102 + &iscsi_boot_attr_tgt_port.attr, 103 + &iscsi_boot_attr_tgt_lun.attr, 104 + &iscsi_boot_attr_tgt_chap.attr, 105 + &iscsi_boot_attr_tgt_nic.attr, 106 + &iscsi_boot_attr_tgt_name.attr, 107 + &iscsi_boot_attr_tgt_chap_name.attr, 108 + &iscsi_boot_attr_tgt_chap_secret.attr, 109 + &iscsi_boot_attr_tgt_chap_rev_name.attr, 110 + &iscsi_boot_attr_tgt_chap_rev_secret.attr, 111 + NULL 112 + }; 113 + 114 + static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj, 115 + struct attribute *attr, int i) 116 + { 117 + struct iscsi_boot_kobj *boot_kobj = 118 + container_of(kobj, struct iscsi_boot_kobj, kobj); 119 + 120 + if (attr == &iscsi_boot_attr_tgt_index.attr) 121 + return boot_kobj->is_visible(boot_kobj->data, 122 + ISCSI_BOOT_TGT_INDEX); 123 + else if (attr == &iscsi_boot_attr_tgt_flags.attr) 124 + return boot_kobj->is_visible(boot_kobj->data, 125 + ISCSI_BOOT_TGT_FLAGS); 126 + else if (attr == &iscsi_boot_attr_tgt_ip.attr) 127 + return boot_kobj->is_visible(boot_kobj->data, 128 + ISCSI_BOOT_TGT_IP_ADDR); 129 + else if (attr == &iscsi_boot_attr_tgt_port.attr) 130 + return boot_kobj->is_visible(boot_kobj->data, 131 + ISCSI_BOOT_TGT_PORT); 132 + else if (attr == &iscsi_boot_attr_tgt_lun.attr) 133 + return boot_kobj->is_visible(boot_kobj->data, 134 + ISCSI_BOOT_TGT_LUN); 135 + else if (attr == &iscsi_boot_attr_tgt_chap.attr) 136 + return boot_kobj->is_visible(boot_kobj->data, 137 + ISCSI_BOOT_TGT_CHAP_TYPE); 138 + else if (attr == &iscsi_boot_attr_tgt_nic.attr) 139 + return boot_kobj->is_visible(boot_kobj->data, 140 + ISCSI_BOOT_TGT_NIC_ASSOC); 141 + else if (attr == &iscsi_boot_attr_tgt_name.attr) 142 + return boot_kobj->is_visible(boot_kobj->data, 143 + ISCSI_BOOT_TGT_NAME); 144 + else if (attr == &iscsi_boot_attr_tgt_chap_name.attr) 145 + return boot_kobj->is_visible(boot_kobj->data, 146 + ISCSI_BOOT_TGT_CHAP_NAME); 147 + else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr) 148 + return boot_kobj->is_visible(boot_kobj->data, 149 + ISCSI_BOOT_TGT_CHAP_SECRET); 150 + else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr) 151 + return boot_kobj->is_visible(boot_kobj->data, 152 + ISCSI_BOOT_TGT_REV_CHAP_NAME); 153 + else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr) 154 + return boot_kobj->is_visible(boot_kobj->data, 155 + ISCSI_BOOT_TGT_REV_CHAP_SECRET); 156 + return 0; 157 + } 158 + 159 + static struct attribute_group iscsi_boot_target_attr_group = { 160 + .attrs = target_attrs, 161 + .is_visible = iscsi_boot_tgt_attr_is_visible, 162 + }; 163 + 164 + /* Ethernet attrs */ 165 + iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX); 166 + iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS); 167 + iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR); 168 + iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK); 169 + iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN); 170 + iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY); 171 + iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS); 172 + iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns, 173 + ISCSI_BOOT_ETH_SECONDARY_DNS); 174 + iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP); 175 + iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN); 176 + iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC); 177 + iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME); 178 + 179 + static struct attribute *ethernet_attrs[] = { 180 + &iscsi_boot_attr_eth_index.attr, 181 + &iscsi_boot_attr_eth_flags.attr, 182 + &iscsi_boot_attr_eth_ip.attr, 183 + &iscsi_boot_attr_eth_subnet.attr, 184 + &iscsi_boot_attr_eth_origin.attr, 185 + &iscsi_boot_attr_eth_gateway.attr, 186 + &iscsi_boot_attr_eth_primary_dns.attr, 187 + &iscsi_boot_attr_eth_secondary_dns.attr, 188 + &iscsi_boot_attr_eth_dhcp.attr, 189 + &iscsi_boot_attr_eth_vlan.attr, 190 + &iscsi_boot_attr_eth_mac.attr, 191 + &iscsi_boot_attr_eth_hostname.attr, 192 + NULL 193 + }; 194 + 195 + static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj, 196 + struct attribute *attr, int i) 197 + { 198 + struct iscsi_boot_kobj *boot_kobj = 199 + container_of(kobj, struct iscsi_boot_kobj, kobj); 200 + 201 + if (attr == &iscsi_boot_attr_eth_index.attr) 202 + return boot_kobj->is_visible(boot_kobj->data, 203 + ISCSI_BOOT_ETH_INDEX); 204 + else if (attr == &iscsi_boot_attr_eth_flags.attr) 205 + return boot_kobj->is_visible(boot_kobj->data, 206 + ISCSI_BOOT_ETH_FLAGS); 207 + else if (attr == &iscsi_boot_attr_eth_ip.attr) 208 + return boot_kobj->is_visible(boot_kobj->data, 209 + ISCSI_BOOT_ETH_IP_ADDR); 210 + else if (attr == &iscsi_boot_attr_eth_subnet.attr) 211 + return boot_kobj->is_visible(boot_kobj->data, 212 + ISCSI_BOOT_ETH_SUBNET_MASK); 213 + else if (attr == &iscsi_boot_attr_eth_origin.attr) 214 + return boot_kobj->is_visible(boot_kobj->data, 215 + ISCSI_BOOT_ETH_ORIGIN); 216 + else if (attr == &iscsi_boot_attr_eth_gateway.attr) 217 + return boot_kobj->is_visible(boot_kobj->data, 218 + ISCSI_BOOT_ETH_GATEWAY); 219 + else if (attr == &iscsi_boot_attr_eth_primary_dns.attr) 220 + return boot_kobj->is_visible(boot_kobj->data, 221 + ISCSI_BOOT_ETH_PRIMARY_DNS); 222 + else if (attr == &iscsi_boot_attr_eth_secondary_dns.attr) 223 + return boot_kobj->is_visible(boot_kobj->data, 224 + ISCSI_BOOT_ETH_SECONDARY_DNS); 225 + else if (attr == &iscsi_boot_attr_eth_dhcp.attr) 226 + return boot_kobj->is_visible(boot_kobj->data, 227 + ISCSI_BOOT_ETH_DHCP); 228 + else if (attr == &iscsi_boot_attr_eth_vlan.attr) 229 + return boot_kobj->is_visible(boot_kobj->data, 230 + ISCSI_BOOT_ETH_VLAN); 231 + else if (attr == &iscsi_boot_attr_eth_mac.attr) 232 + return boot_kobj->is_visible(boot_kobj->data, 233 + ISCSI_BOOT_ETH_MAC); 234 + else if (attr == &iscsi_boot_attr_eth_hostname.attr) 235 + return boot_kobj->is_visible(boot_kobj->data, 236 + ISCSI_BOOT_ETH_HOSTNAME); 237 + return 0; 238 + } 239 + 240 + static struct attribute_group iscsi_boot_ethernet_attr_group = { 241 + .attrs = ethernet_attrs, 242 + .is_visible = iscsi_boot_eth_attr_is_visible, 243 + }; 244 + 245 + /* Initiator attrs */ 246 + iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX); 247 + iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS); 248 + iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER); 249 + iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER); 250 + iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server, 251 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); 252 + iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server, 253 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); 254 + iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME); 255 + 256 + static struct attribute *initiator_attrs[] = { 257 + &iscsi_boot_attr_ini_index.attr, 258 + &iscsi_boot_attr_ini_flags.attr, 259 + &iscsi_boot_attr_ini_isns.attr, 260 + &iscsi_boot_attr_ini_slp.attr, 261 + &iscsi_boot_attr_ini_primary_radius.attr, 262 + &iscsi_boot_attr_ini_secondary_radius.attr, 263 + &iscsi_boot_attr_ini_name.attr, 264 + NULL 265 + }; 266 + 267 + static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj, 268 + struct attribute *attr, int i) 269 + { 270 + struct iscsi_boot_kobj *boot_kobj = 271 + container_of(kobj, struct iscsi_boot_kobj, kobj); 272 + 273 + if (attr == &iscsi_boot_attr_ini_index.attr) 274 + return boot_kobj->is_visible(boot_kobj->data, 275 + ISCSI_BOOT_INI_INDEX); 276 + if (attr == &iscsi_boot_attr_ini_flags.attr) 277 + return boot_kobj->is_visible(boot_kobj->data, 278 + ISCSI_BOOT_INI_FLAGS); 279 + if (attr == &iscsi_boot_attr_ini_isns.attr) 280 + return boot_kobj->is_visible(boot_kobj->data, 281 + ISCSI_BOOT_INI_ISNS_SERVER); 282 + if (attr == &iscsi_boot_attr_ini_slp.attr) 283 + return boot_kobj->is_visible(boot_kobj->data, 284 + ISCSI_BOOT_INI_SLP_SERVER); 285 + if (attr == &iscsi_boot_attr_ini_primary_radius.attr) 286 + return boot_kobj->is_visible(boot_kobj->data, 287 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); 288 + if (attr == &iscsi_boot_attr_ini_secondary_radius.attr) 289 + return boot_kobj->is_visible(boot_kobj->data, 290 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); 291 + if (attr == &iscsi_boot_attr_ini_name.attr) 292 + return boot_kobj->is_visible(boot_kobj->data, 293 + ISCSI_BOOT_INI_INITIATOR_NAME); 294 + 295 + return 0; 296 + } 297 + 298 + static struct attribute_group iscsi_boot_initiator_attr_group = { 299 + .attrs = initiator_attrs, 300 + .is_visible = iscsi_boot_ini_attr_is_visible, 301 + }; 302 + 303 + static struct iscsi_boot_kobj * 304 + iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, 305 + struct attribute_group *attr_group, 306 + const char *name, int index, void *data, 307 + ssize_t (*show) (void *data, int type, char *buf), 308 + mode_t (*is_visible) (void *data, int type)) 309 + { 310 + struct iscsi_boot_kobj *boot_kobj; 311 + 312 + boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL); 313 + if (!boot_kobj) 314 + return NULL; 315 + INIT_LIST_HEAD(&boot_kobj->list); 316 + 317 + boot_kobj->kobj.kset = boot_kset->kset; 318 + if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype, 319 + NULL, name, index)) { 320 + kfree(boot_kobj); 321 + return NULL; 322 + } 323 + boot_kobj->data = data; 324 + boot_kobj->show = show; 325 + boot_kobj->is_visible = is_visible; 326 + 327 + if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { 328 + /* 329 + * We do not want to free this because the caller 330 + * will assume that since the creation call failed 331 + * the boot kobj was not setup and the normal release 332 + * path is not being run. 333 + */ 334 + boot_kobj->data = NULL; 335 + kobject_put(&boot_kobj->kobj); 336 + return NULL; 337 + } 338 + boot_kobj->attr_group = attr_group; 339 + 340 + kobject_uevent(&boot_kobj->kobj, KOBJ_ADD); 341 + /* Nothing broke so lets add it to the list. */ 342 + list_add_tail(&boot_kobj->list, &boot_kset->kobj_list); 343 + return boot_kobj; 344 + } 345 + 346 + static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) 347 + { 348 + list_del(&boot_kobj->list); 349 + sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group); 350 + kobject_put(&boot_kobj->kobj); 351 + } 352 + 353 + /** 354 + * iscsi_boot_create_target() - create boot target sysfs dir 355 + * @boot_kset: boot kset 356 + * @index: the target id 357 + * @data: driver specific data for target 358 + * @show: attr show function 359 + * @is_visible: attr visibility function 360 + * 361 + * Note: The boot sysfs lib will free the data passed in for the caller 362 + * when all refs to the target kobject have been released. 363 + */ 364 + struct iscsi_boot_kobj * 365 + iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, 366 + void *data, 367 + ssize_t (*show) (void *data, int type, char *buf), 368 + mode_t (*is_visible) (void *data, int type)) 369 + { 370 + return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, 371 + "target%d", index, data, show, is_visible); 372 + } 373 + EXPORT_SYMBOL_GPL(iscsi_boot_create_target); 374 + 375 + /** 376 + * iscsi_boot_create_initiator() - create boot initiator sysfs dir 377 + * @boot_kset: boot kset 378 + * @index: the initiator id 379 + * @data: driver specific data 380 + * @show: attr show function 381 + * @is_visible: attr visibility function 382 + * 383 + * Note: The boot sysfs lib will free the data passed in for the caller 384 + * when all refs to the initiator kobject have been released. 385 + */ 386 + struct iscsi_boot_kobj * 387 + iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, 388 + void *data, 389 + ssize_t (*show) (void *data, int type, char *buf), 390 + mode_t (*is_visible) (void *data, int type)) 391 + { 392 + return iscsi_boot_create_kobj(boot_kset, 393 + &iscsi_boot_initiator_attr_group, 394 + "initiator", index, data, show, 395 + is_visible); 396 + } 397 + EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); 398 + 399 + /** 400 + * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir 401 + * @boot_kset: boot kset 402 + * @index: the ethernet device id 403 + * @data: driver specific data 404 + * @show: attr show function 405 + * @is_visible: attr visibility function 406 + * 407 + * Note: The boot sysfs lib will free the data passed in for the caller 408 + * when all refs to the ethernet kobject have been released. 409 + */ 410 + struct iscsi_boot_kobj * 411 + iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, 412 + void *data, 413 + ssize_t (*show) (void *data, int type, char *buf), 414 + mode_t (*is_visible) (void *data, int type)) 415 + { 416 + return iscsi_boot_create_kobj(boot_kset, 417 + &iscsi_boot_ethernet_attr_group, 418 + "ethernet%d", index, data, show, 419 + is_visible); 420 + } 421 + EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); 422 + 423 + /** 424 + * iscsi_boot_create_kset() - creates root sysfs tree 425 + * @set_name: name of root dir 426 + */ 427 + struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name) 428 + { 429 + struct iscsi_boot_kset *boot_kset; 430 + 431 + boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL); 432 + if (!boot_kset) 433 + return NULL; 434 + 435 + boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj); 436 + if (!boot_kset->kset) { 437 + kfree(boot_kset); 438 + return NULL; 439 + } 440 + 441 + INIT_LIST_HEAD(&boot_kset->kobj_list); 442 + return boot_kset; 443 + } 444 + EXPORT_SYMBOL_GPL(iscsi_boot_create_kset); 445 + 446 + /** 447 + * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host 448 + * @hostno: host number of scsi host 449 + */ 450 + struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno) 451 + { 452 + struct iscsi_boot_kset *boot_kset; 453 + char *set_name; 454 + 455 + set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno); 456 + if (!set_name) 457 + return NULL; 458 + 459 + boot_kset = iscsi_boot_create_kset(set_name); 460 + kfree(set_name); 461 + return boot_kset; 462 + } 463 + EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset); 464 + 465 + /** 466 + * iscsi_boot_destroy_kset() - destroy kset and kobjects under it 467 + * @boot_kset: boot kset 468 + * 469 + * This will remove the kset and kobjects and attrs under it. 470 + */ 471 + void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset) 472 + { 473 + struct iscsi_boot_kobj *boot_kobj, *tmp_kobj; 474 + 475 + list_for_each_entry_safe(boot_kobj, tmp_kobj, 476 + &boot_kset->kobj_list, list) 477 + iscsi_boot_remove_kobj(boot_kobj); 478 + 479 + kset_unregister(boot_kset->kset); 480 + } 481 + EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset);
+264 -462
drivers/firmware/iscsi_ibft.c
··· 1 1 /* 2 - * Copyright 2007 Red Hat, Inc. 2 + * Copyright 2007-2010 Red Hat, Inc. 3 3 * by Peter Jones <pjones@redhat.com> 4 4 * Copyright 2008 IBM, Inc. 5 5 * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> ··· 18 18 * GNU General Public License for more details. 19 19 * 20 20 * Changelog: 21 + * 22 + * 06 Jan 2010 - Peter Jones <pjones@redhat.com> 23 + * New changelog entries are in the git log from now on. Not here. 21 24 * 22 25 * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr@darnok.org> 23 26 * Updated comments and copyrights. (v0.4.9) ··· 81 78 #include <linux/stat.h> 82 79 #include <linux/string.h> 83 80 #include <linux/types.h> 81 + #include <linux/acpi.h> 82 + #include <linux/iscsi_boot_sysfs.h> 84 83 85 - #define IBFT_ISCSI_VERSION "0.4.9" 86 - #define IBFT_ISCSI_DATE "2008-Mar-14" 84 + #define IBFT_ISCSI_VERSION "0.5.0" 85 + #define IBFT_ISCSI_DATE "2010-Feb-25" 87 86 88 87 MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and \ 89 88 Konrad Rzeszutek <ketuzsezr@darnok.org>"); ··· 171 166 }; 172 167 173 168 /* 174 - * We do not support the other types, hence the usage of NULL. 175 - * This maps to the enum ibft_id. 176 - */ 177 - static const char *ibft_id_names[] = 178 - {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL}; 179 - 180 - /* 181 - * The text attributes names for each of the kobjects. 182 - */ 183 - enum ibft_eth_properties_enum { 184 - ibft_eth_index, 185 - ibft_eth_flags, 186 - ibft_eth_ip_addr, 187 - ibft_eth_subnet_mask, 188 - ibft_eth_origin, 189 - ibft_eth_gateway, 190 - ibft_eth_primary_dns, 191 - ibft_eth_secondary_dns, 192 - ibft_eth_dhcp, 193 - ibft_eth_vlan, 194 - ibft_eth_mac, 195 - /* ibft_eth_pci_bdf - this is replaced by link to the device itself. */ 196 - ibft_eth_hostname, 197 - ibft_eth_end_marker, 198 - }; 199 - 200 - static const char *ibft_eth_properties[] = 201 - {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway", 202 - "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname", 203 - NULL}; 204 - 205 - enum ibft_tgt_properties_enum { 206 - ibft_tgt_index, 207 - ibft_tgt_flags, 208 - ibft_tgt_ip_addr, 209 - ibft_tgt_port, 210 - ibft_tgt_lun, 211 - ibft_tgt_chap_type, 212 - ibft_tgt_nic_assoc, 213 - ibft_tgt_name, 214 - ibft_tgt_chap_name, 215 - ibft_tgt_chap_secret, 216 - ibft_tgt_rev_chap_name, 217 - ibft_tgt_rev_chap_secret, 218 - ibft_tgt_end_marker, 219 - }; 220 - 221 - static const char *ibft_tgt_properties[] = 222 - {"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc", 223 - "target-name", "chap-name", "chap-secret", "rev-chap-name", 224 - "rev-chap-name-secret", NULL}; 225 - 226 - enum ibft_initiator_properties_enum { 227 - ibft_init_index, 228 - ibft_init_flags, 229 - ibft_init_isns_server, 230 - ibft_init_slp_server, 231 - ibft_init_pri_radius_server, 232 - ibft_init_sec_radius_server, 233 - ibft_init_initiator_name, 234 - ibft_init_end_marker, 235 - }; 236 - 237 - static const char *ibft_initiator_properties[] = 238 - {"index", "flags", "isns-server", "slp-server", "pri-radius-server", 239 - "sec-radius-server", "initiator-name", NULL}; 240 - 241 - /* 242 169 * The kobject and attribute structures. 243 170 */ 244 171 245 172 struct ibft_kobject { 246 - struct ibft_table_header *header; 173 + struct acpi_table_ibft *header; 247 174 union { 248 175 struct ibft_initiator *initiator; 249 176 struct ibft_nic *nic; 250 177 struct ibft_tgt *tgt; 251 178 struct ibft_hdr *hdr; 252 179 }; 253 - struct kobject kobj; 254 - struct list_head node; 255 180 }; 256 181 257 - struct ibft_attribute { 258 - struct attribute attr; 259 - ssize_t (*show) (struct ibft_kobject *entry, 260 - struct ibft_attribute *attr, char *buf); 261 - union { 262 - struct ibft_initiator *initiator; 263 - struct ibft_nic *nic; 264 - struct ibft_tgt *tgt; 265 - struct ibft_hdr *hdr; 266 - }; 267 - struct kobject *kobj; 268 - int type; /* The enum of the type. This can be any value of: 269 - ibft_eth_properties_enum, ibft_tgt_properties_enum, 270 - or ibft_initiator_properties_enum. */ 271 - struct list_head node; 272 - }; 273 - 274 - static LIST_HEAD(ibft_attr_list); 275 - static LIST_HEAD(ibft_kobject_list); 182 + static struct iscsi_boot_kset *boot_kset; 276 183 277 184 static const char nulls[16]; 278 185 ··· 223 306 static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length) 224 307 { 225 308 if (hdr->id != id) { 226 - printk(KERN_ERR "iBFT error: We expected the " \ 309 + printk(KERN_ERR "iBFT error: We expected the %s " \ 227 310 "field header.id to have %d but " \ 228 - "found %d instead!\n", id, hdr->id); 311 + "found %d instead!\n", t, id, hdr->id); 229 312 return -ENODEV; 230 313 } 231 314 if (hdr->length != length) { 232 - printk(KERN_ERR "iBFT error: We expected the " \ 315 + printk(KERN_ERR "iBFT error: We expected the %s " \ 233 316 "field header.length to have %d but " \ 234 - "found %d instead!\n", length, hdr->length); 317 + "found %d instead!\n", t, length, hdr->length); 235 318 return -ENODEV; 236 319 } 237 320 238 321 return 0; 239 322 } 240 323 241 - static void ibft_release(struct kobject *kobj) 242 - { 243 - struct ibft_kobject *ibft = 244 - container_of(kobj, struct ibft_kobject, kobj); 245 - kfree(ibft); 246 - } 247 - 248 324 /* 249 325 * Routines for parsing the iBFT data to be human readable. 250 326 */ 251 - static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry, 252 - struct ibft_attribute *attr, 253 - char *buf) 327 + static ssize_t ibft_attr_show_initiator(void *data, int type, char *buf) 254 328 { 329 + struct ibft_kobject *entry = data; 255 330 struct ibft_initiator *initiator = entry->initiator; 256 331 void *ibft_loc = entry->header; 257 332 char *str = buf; ··· 251 342 if (!initiator) 252 343 return 0; 253 344 254 - switch (attr->type) { 255 - case ibft_init_index: 345 + switch (type) { 346 + case ISCSI_BOOT_INI_INDEX: 256 347 str += sprintf(str, "%d\n", initiator->hdr.index); 257 348 break; 258 - case ibft_init_flags: 349 + case ISCSI_BOOT_INI_FLAGS: 259 350 str += sprintf(str, "%d\n", initiator->hdr.flags); 260 351 break; 261 - case ibft_init_isns_server: 352 + case ISCSI_BOOT_INI_ISNS_SERVER: 262 353 str += sprintf_ipaddr(str, initiator->isns_server); 263 354 break; 264 - case ibft_init_slp_server: 355 + case ISCSI_BOOT_INI_SLP_SERVER: 265 356 str += sprintf_ipaddr(str, initiator->slp_server); 266 357 break; 267 - case ibft_init_pri_radius_server: 358 + case ISCSI_BOOT_INI_PRI_RADIUS_SERVER: 268 359 str += sprintf_ipaddr(str, initiator->pri_radius_server); 269 360 break; 270 - case ibft_init_sec_radius_server: 361 + case ISCSI_BOOT_INI_SEC_RADIUS_SERVER: 271 362 str += sprintf_ipaddr(str, initiator->sec_radius_server); 272 363 break; 273 - case ibft_init_initiator_name: 364 + case ISCSI_BOOT_INI_INITIATOR_NAME: 274 365 str += sprintf_string(str, initiator->initiator_name_len, 275 366 (char *)ibft_loc + 276 367 initiator->initiator_name_off); ··· 282 373 return str - buf; 283 374 } 284 375 285 - static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, 286 - struct ibft_attribute *attr, 287 - char *buf) 376 + static ssize_t ibft_attr_show_nic(void *data, int type, char *buf) 288 377 { 378 + struct ibft_kobject *entry = data; 289 379 struct ibft_nic *nic = entry->nic; 290 380 void *ibft_loc = entry->header; 291 381 char *str = buf; ··· 293 385 if (!nic) 294 386 return 0; 295 387 296 - switch (attr->type) { 297 - case ibft_eth_index: 388 + switch (type) { 389 + case ISCSI_BOOT_ETH_INDEX: 298 390 str += sprintf(str, "%d\n", nic->hdr.index); 299 391 break; 300 - case ibft_eth_flags: 392 + case ISCSI_BOOT_ETH_FLAGS: 301 393 str += sprintf(str, "%d\n", nic->hdr.flags); 302 394 break; 303 - case ibft_eth_ip_addr: 395 + case ISCSI_BOOT_ETH_IP_ADDR: 304 396 str += sprintf_ipaddr(str, nic->ip_addr); 305 397 break; 306 - case ibft_eth_subnet_mask: 398 + case ISCSI_BOOT_ETH_SUBNET_MASK: 307 399 val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1)); 308 400 str += sprintf(str, "%pI4", &val); 309 401 break; 310 - case ibft_eth_origin: 402 + case ISCSI_BOOT_ETH_ORIGIN: 311 403 str += sprintf(str, "%d\n", nic->origin); 312 404 break; 313 - case ibft_eth_gateway: 405 + case ISCSI_BOOT_ETH_GATEWAY: 314 406 str += sprintf_ipaddr(str, nic->gateway); 315 407 break; 316 - case ibft_eth_primary_dns: 408 + case ISCSI_BOOT_ETH_PRIMARY_DNS: 317 409 str += sprintf_ipaddr(str, nic->primary_dns); 318 410 break; 319 - case ibft_eth_secondary_dns: 411 + case ISCSI_BOOT_ETH_SECONDARY_DNS: 320 412 str += sprintf_ipaddr(str, nic->secondary_dns); 321 413 break; 322 - case ibft_eth_dhcp: 414 + case ISCSI_BOOT_ETH_DHCP: 323 415 str += sprintf_ipaddr(str, nic->dhcp); 324 416 break; 325 - case ibft_eth_vlan: 417 + case ISCSI_BOOT_ETH_VLAN: 326 418 str += sprintf(str, "%d\n", nic->vlan); 327 419 break; 328 - case ibft_eth_mac: 420 + case ISCSI_BOOT_ETH_MAC: 329 421 str += sprintf(str, "%pM\n", nic->mac); 330 422 break; 331 - case ibft_eth_hostname: 423 + case ISCSI_BOOT_ETH_HOSTNAME: 332 424 str += sprintf_string(str, nic->hostname_len, 333 425 (char *)ibft_loc + nic->hostname_off); 334 426 break; ··· 339 431 return str - buf; 340 432 }; 341 433 342 - static ssize_t ibft_attr_show_target(struct ibft_kobject *entry, 343 - struct ibft_attribute *attr, 344 - char *buf) 434 + static ssize_t ibft_attr_show_target(void *data, int type, char *buf) 345 435 { 436 + struct ibft_kobject *entry = data; 346 437 struct ibft_tgt *tgt = entry->tgt; 347 438 void *ibft_loc = entry->header; 348 439 char *str = buf; ··· 350 443 if (!tgt) 351 444 return 0; 352 445 353 - switch (attr->type) { 354 - case ibft_tgt_index: 446 + switch (type) { 447 + case ISCSI_BOOT_TGT_INDEX: 355 448 str += sprintf(str, "%d\n", tgt->hdr.index); 356 449 break; 357 - case ibft_tgt_flags: 450 + case ISCSI_BOOT_TGT_FLAGS: 358 451 str += sprintf(str, "%d\n", tgt->hdr.flags); 359 452 break; 360 - case ibft_tgt_ip_addr: 453 + case ISCSI_BOOT_TGT_IP_ADDR: 361 454 str += sprintf_ipaddr(str, tgt->ip_addr); 362 455 break; 363 - case ibft_tgt_port: 456 + case ISCSI_BOOT_TGT_PORT: 364 457 str += sprintf(str, "%d\n", tgt->port); 365 458 break; 366 - case ibft_tgt_lun: 459 + case ISCSI_BOOT_TGT_LUN: 367 460 for (i = 0; i < 8; i++) 368 461 str += sprintf(str, "%x", (u8)tgt->lun[i]); 369 462 str += sprintf(str, "\n"); 370 463 break; 371 - case ibft_tgt_nic_assoc: 464 + case ISCSI_BOOT_TGT_NIC_ASSOC: 372 465 str += sprintf(str, "%d\n", tgt->nic_assoc); 373 466 break; 374 - case ibft_tgt_chap_type: 467 + case ISCSI_BOOT_TGT_CHAP_TYPE: 375 468 str += sprintf(str, "%d\n", tgt->chap_type); 376 469 break; 377 - case ibft_tgt_name: 470 + case ISCSI_BOOT_TGT_NAME: 378 471 str += sprintf_string(str, tgt->tgt_name_len, 379 472 (char *)ibft_loc + tgt->tgt_name_off); 380 473 break; 381 - case ibft_tgt_chap_name: 474 + case ISCSI_BOOT_TGT_CHAP_NAME: 382 475 str += sprintf_string(str, tgt->chap_name_len, 383 476 (char *)ibft_loc + tgt->chap_name_off); 384 477 break; 385 - case ibft_tgt_chap_secret: 478 + case ISCSI_BOOT_TGT_CHAP_SECRET: 386 479 str += sprintf_string(str, tgt->chap_secret_len, 387 480 (char *)ibft_loc + tgt->chap_secret_off); 388 481 break; 389 - case ibft_tgt_rev_chap_name: 482 + case ISCSI_BOOT_TGT_REV_CHAP_NAME: 390 483 str += sprintf_string(str, tgt->rev_chap_name_len, 391 484 (char *)ibft_loc + 392 485 tgt->rev_chap_name_off); 393 486 break; 394 - case ibft_tgt_rev_chap_secret: 487 + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 395 488 str += sprintf_string(str, tgt->rev_chap_secret_len, 396 489 (char *)ibft_loc + 397 490 tgt->rev_chap_secret_off); ··· 403 496 return str - buf; 404 497 } 405 498 406 - /* 407 - * The routine called for all sysfs attributes. 408 - */ 409 - static ssize_t ibft_show_attribute(struct kobject *kobj, 410 - struct attribute *attr, 411 - char *buf) 412 - { 413 - struct ibft_kobject *dev = 414 - container_of(kobj, struct ibft_kobject, kobj); 415 - struct ibft_attribute *ibft_attr = 416 - container_of(attr, struct ibft_attribute, attr); 417 - ssize_t ret = -EIO; 418 - char *str = buf; 419 - 420 - if (!capable(CAP_SYS_ADMIN)) 421 - return -EACCES; 422 - 423 - if (ibft_attr->show) 424 - ret = ibft_attr->show(dev, ibft_attr, str); 425 - 426 - return ret; 427 - } 428 - 429 - static const struct sysfs_ops ibft_attr_ops = { 430 - .show = ibft_show_attribute, 431 - }; 432 - 433 - static struct kobj_type ibft_ktype = { 434 - .release = ibft_release, 435 - .sysfs_ops = &ibft_attr_ops, 436 - }; 437 - 438 - static struct kset *ibft_kset; 439 - 440 499 static int __init ibft_check_device(void) 441 500 { 442 501 int len; 443 502 u8 *pos; 444 503 u8 csum = 0; 445 504 446 - len = ibft_addr->length; 505 + len = ibft_addr->header.length; 447 506 448 507 /* Sanity checking of iBFT. */ 449 - if (ibft_addr->revision != 1) { 508 + if (ibft_addr->header.revision != 1) { 450 509 printk(KERN_ERR "iBFT module supports only revision 1, " \ 451 - "while this is %d.\n", ibft_addr->revision); 510 + "while this is %d.\n", 511 + ibft_addr->header.revision); 452 512 return -ENOENT; 453 513 } 454 514 for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++) ··· 430 556 } 431 557 432 558 /* 559 + * Helper routiners to check to determine if the entry is valid 560 + * in the proper iBFT structure. 561 + */ 562 + static mode_t ibft_check_nic_for(void *data, int type) 563 + { 564 + struct ibft_kobject *entry = data; 565 + struct ibft_nic *nic = entry->nic; 566 + mode_t rc = 0; 567 + 568 + switch (type) { 569 + case ISCSI_BOOT_ETH_INDEX: 570 + case ISCSI_BOOT_ETH_FLAGS: 571 + rc = S_IRUGO; 572 + break; 573 + case ISCSI_BOOT_ETH_IP_ADDR: 574 + if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr))) 575 + rc = S_IRUGO; 576 + break; 577 + case ISCSI_BOOT_ETH_SUBNET_MASK: 578 + if (nic->subnet_mask_prefix) 579 + rc = S_IRUGO; 580 + break; 581 + case ISCSI_BOOT_ETH_ORIGIN: 582 + rc = S_IRUGO; 583 + break; 584 + case ISCSI_BOOT_ETH_GATEWAY: 585 + if (memcmp(nic->gateway, nulls, sizeof(nic->gateway))) 586 + rc = S_IRUGO; 587 + break; 588 + case ISCSI_BOOT_ETH_PRIMARY_DNS: 589 + if (memcmp(nic->primary_dns, nulls, 590 + sizeof(nic->primary_dns))) 591 + rc = S_IRUGO; 592 + break; 593 + case ISCSI_BOOT_ETH_SECONDARY_DNS: 594 + if (memcmp(nic->secondary_dns, nulls, 595 + sizeof(nic->secondary_dns))) 596 + rc = S_IRUGO; 597 + break; 598 + case ISCSI_BOOT_ETH_DHCP: 599 + if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) 600 + rc = S_IRUGO; 601 + break; 602 + case ISCSI_BOOT_ETH_VLAN: 603 + case ISCSI_BOOT_ETH_MAC: 604 + rc = S_IRUGO; 605 + break; 606 + case ISCSI_BOOT_ETH_HOSTNAME: 607 + if (nic->hostname_off) 608 + rc = S_IRUGO; 609 + break; 610 + default: 611 + break; 612 + } 613 + 614 + return rc; 615 + } 616 + 617 + static mode_t __init ibft_check_tgt_for(void *data, int type) 618 + { 619 + struct ibft_kobject *entry = data; 620 + struct ibft_tgt *tgt = entry->tgt; 621 + mode_t rc = 0; 622 + 623 + switch (type) { 624 + case ISCSI_BOOT_TGT_INDEX: 625 + case ISCSI_BOOT_TGT_FLAGS: 626 + case ISCSI_BOOT_TGT_IP_ADDR: 627 + case ISCSI_BOOT_TGT_PORT: 628 + case ISCSI_BOOT_TGT_LUN: 629 + case ISCSI_BOOT_TGT_NIC_ASSOC: 630 + case ISCSI_BOOT_TGT_CHAP_TYPE: 631 + rc = S_IRUGO; 632 + case ISCSI_BOOT_TGT_NAME: 633 + if (tgt->tgt_name_len) 634 + rc = S_IRUGO; 635 + break; 636 + case ISCSI_BOOT_TGT_CHAP_NAME: 637 + case ISCSI_BOOT_TGT_CHAP_SECRET: 638 + if (tgt->chap_name_len) 639 + rc = S_IRUGO; 640 + break; 641 + case ISCSI_BOOT_TGT_REV_CHAP_NAME: 642 + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 643 + if (tgt->rev_chap_name_len) 644 + rc = S_IRUGO; 645 + break; 646 + default: 647 + break; 648 + } 649 + 650 + return rc; 651 + } 652 + 653 + static mode_t __init ibft_check_initiator_for(void *data, int type) 654 + { 655 + struct ibft_kobject *entry = data; 656 + struct ibft_initiator *init = entry->initiator; 657 + mode_t rc = 0; 658 + 659 + switch (type) { 660 + case ISCSI_BOOT_INI_INDEX: 661 + case ISCSI_BOOT_INI_FLAGS: 662 + rc = S_IRUGO; 663 + break; 664 + case ISCSI_BOOT_INI_ISNS_SERVER: 665 + if (memcmp(init->isns_server, nulls, 666 + sizeof(init->isns_server))) 667 + rc = S_IRUGO; 668 + break; 669 + case ISCSI_BOOT_INI_SLP_SERVER: 670 + if (memcmp(init->slp_server, nulls, 671 + sizeof(init->slp_server))) 672 + rc = S_IRUGO; 673 + break; 674 + case ISCSI_BOOT_INI_PRI_RADIUS_SERVER: 675 + if (memcmp(init->pri_radius_server, nulls, 676 + sizeof(init->pri_radius_server))) 677 + rc = S_IRUGO; 678 + break; 679 + case ISCSI_BOOT_INI_SEC_RADIUS_SERVER: 680 + if (memcmp(init->sec_radius_server, nulls, 681 + sizeof(init->sec_radius_server))) 682 + rc = S_IRUGO; 683 + break; 684 + case ISCSI_BOOT_INI_INITIATOR_NAME: 685 + if (init->initiator_name_len) 686 + rc = S_IRUGO; 687 + break; 688 + default: 689 + break; 690 + } 691 + 692 + return rc; 693 + } 694 + 695 + /* 433 696 * Helper function for ibft_register_kobjects. 434 697 */ 435 - static int __init ibft_create_kobject(struct ibft_table_header *header, 436 - struct ibft_hdr *hdr, 437 - struct list_head *list) 698 + static int __init ibft_create_kobject(struct acpi_table_ibft *header, 699 + struct ibft_hdr *hdr) 438 700 { 701 + struct iscsi_boot_kobj *boot_kobj = NULL; 439 702 struct ibft_kobject *ibft_kobj = NULL; 440 703 struct ibft_nic *nic = (struct ibft_nic *)hdr; 441 704 struct pci_dev *pci_dev; ··· 589 578 case id_initiator: 590 579 rc = ibft_verify_hdr("initiator", hdr, id_initiator, 591 580 sizeof(*ibft_kobj->initiator)); 581 + if (rc) 582 + break; 583 + 584 + boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index, 585 + ibft_kobj, 586 + ibft_attr_show_initiator, 587 + ibft_check_initiator_for); 588 + if (!boot_kobj) { 589 + rc = -ENOMEM; 590 + goto free_ibft_obj; 591 + } 592 592 break; 593 593 case id_nic: 594 594 rc = ibft_verify_hdr("ethernet", hdr, id_nic, 595 595 sizeof(*ibft_kobj->nic)); 596 + if (rc) 597 + break; 598 + 599 + boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index, 600 + ibft_kobj, 601 + ibft_attr_show_nic, 602 + ibft_check_nic_for); 603 + if (!boot_kobj) { 604 + rc = -ENOMEM; 605 + goto free_ibft_obj; 606 + } 596 607 break; 597 608 case id_target: 598 609 rc = ibft_verify_hdr("target", hdr, id_target, 599 610 sizeof(*ibft_kobj->tgt)); 611 + if (rc) 612 + break; 613 + 614 + boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index, 615 + ibft_kobj, 616 + ibft_attr_show_target, 617 + ibft_check_tgt_for); 618 + if (!boot_kobj) { 619 + rc = -ENOMEM; 620 + goto free_ibft_obj; 621 + } 600 622 break; 601 623 case id_reserved: 602 624 case id_control: ··· 640 596 default: 641 597 printk(KERN_ERR "iBFT has unknown structure type (%d). " \ 642 598 "Report this bug to %.6s!\n", hdr->id, 643 - header->oem_id); 599 + header->header.oem_id); 644 600 rc = 1; 645 601 break; 646 602 } 647 603 648 604 if (rc) { 649 605 /* Skip adding this kobject, but exit with non-fatal error. */ 650 - kfree(ibft_kobj); 651 - goto out_invalid_struct; 606 + rc = 0; 607 + goto free_ibft_obj; 652 608 } 653 - 654 - ibft_kobj->kobj.kset = ibft_kset; 655 - 656 - rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype, 657 - NULL, ibft_id_names[hdr->id], hdr->index); 658 - 659 - if (rc) { 660 - kfree(ibft_kobj); 661 - goto out; 662 - } 663 - 664 - kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD); 665 609 666 610 if (hdr->id == id_nic) { 667 611 /* ··· 661 629 pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, 662 630 (nic->pci_bdf & 0xff)); 663 631 if (pci_dev) { 664 - rc = sysfs_create_link(&ibft_kobj->kobj, 632 + rc = sysfs_create_link(&boot_kobj->kobj, 665 633 &pci_dev->dev.kobj, "device"); 666 634 pci_dev_put(pci_dev); 667 635 } 668 636 } 669 - 670 - /* Nothing broke so lets add it to the list. */ 671 - list_add_tail(&ibft_kobj->node, list); 672 - out: 673 - return rc; 674 - out_invalid_struct: 675 - /* Unsupported structs are skipped. */ 676 637 return 0; 638 + 639 + free_ibft_obj: 640 + kfree(ibft_kobj); 641 + return rc; 677 642 } 678 643 679 644 /* ··· 678 649 * found add them on the passed-in list. We do not support the other 679 650 * fields at this point, so they are skipped. 680 651 */ 681 - static int __init ibft_register_kobjects(struct ibft_table_header *header, 682 - struct list_head *list) 652 + static int __init ibft_register_kobjects(struct acpi_table_ibft *header) 683 653 { 684 654 struct ibft_control *control = NULL; 685 655 void *ptr, *end; ··· 688 660 689 661 control = (void *)header + sizeof(*header); 690 662 end = (void *)control + control->hdr.length; 691 - eot_offset = (void *)header + header->length - (void *)control; 663 + eot_offset = (void *)header + header->header.length - (void *)control; 692 664 rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, 693 665 sizeof(*control)); 694 666 ··· 700 672 } 701 673 for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) { 702 674 offset = *(u16 *)ptr; 703 - if (offset && offset < header->length && offset < eot_offset) { 675 + if (offset && offset < header->header.length && 676 + offset < eot_offset) { 704 677 rc = ibft_create_kobject(header, 705 - (void *)header + offset, 706 - list); 678 + (void *)header + offset); 707 679 if (rc) 708 680 break; 709 681 } ··· 712 684 return rc; 713 685 } 714 686 715 - static void ibft_unregister(struct list_head *attr_list, 716 - struct list_head *kobj_list) 687 + static void ibft_unregister(void) 717 688 { 718 - struct ibft_kobject *data = NULL, *n; 719 - struct ibft_attribute *attr = NULL, *m; 689 + struct iscsi_boot_kobj *boot_kobj, *tmp_kobj; 690 + struct ibft_kobject *ibft_kobj; 720 691 721 - list_for_each_entry_safe(attr, m, attr_list, node) { 722 - sysfs_remove_file(attr->kobj, &attr->attr); 723 - list_del(&attr->node); 724 - kfree(attr); 692 + list_for_each_entry_safe(boot_kobj, tmp_kobj, 693 + &boot_kset->kobj_list, list) { 694 + ibft_kobj = boot_kobj->data; 695 + if (ibft_kobj->hdr->id == id_nic) 696 + sysfs_remove_link(&boot_kobj->kobj, "device"); 725 697 }; 726 - list_del_init(attr_list); 727 - 728 - list_for_each_entry_safe(data, n, kobj_list, node) { 729 - list_del(&data->node); 730 - if (data->hdr->id == id_nic) 731 - sysfs_remove_link(&data->kobj, "device"); 732 - kobject_put(&data->kobj); 733 - }; 734 - list_del_init(kobj_list); 735 698 } 736 699 737 - static int __init ibft_create_attribute(struct ibft_kobject *kobj_data, 738 - int type, 739 - const char *name, 740 - ssize_t (*show)(struct ibft_kobject *, 741 - struct ibft_attribute*, 742 - char *buf), 743 - struct list_head *list) 700 + static void ibft_cleanup(void) 744 701 { 745 - struct ibft_attribute *attr = NULL; 746 - struct ibft_hdr *hdr = kobj_data->hdr; 747 - 748 - attr = kmalloc(sizeof(*attr), GFP_KERNEL); 749 - if (!attr) 750 - return -ENOMEM; 751 - 752 - attr->attr.name = name; 753 - attr->attr.mode = S_IRUSR; 754 - 755 - attr->hdr = hdr; 756 - attr->show = show; 757 - attr->kobj = &kobj_data->kobj; 758 - attr->type = type; 759 - 760 - list_add_tail(&attr->node, list); 761 - 762 - return 0; 702 + ibft_unregister(); 703 + iscsi_boot_destroy_kset(boot_kset); 763 704 } 764 705 765 - /* 766 - * Helper routiners to check to determine if the entry is valid 767 - * in the proper iBFT structure. 768 - */ 769 - static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry) 706 + static void __exit ibft_exit(void) 770 707 { 771 - int rc = 0; 772 - 773 - switch (entry) { 774 - case ibft_eth_index: 775 - case ibft_eth_flags: 776 - rc = 1; 777 - break; 778 - case ibft_eth_ip_addr: 779 - if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr))) 780 - rc = 1; 781 - break; 782 - case ibft_eth_subnet_mask: 783 - if (nic->subnet_mask_prefix) 784 - rc = 1; 785 - break; 786 - case ibft_eth_origin: 787 - rc = 1; 788 - break; 789 - case ibft_eth_gateway: 790 - if (memcmp(nic->gateway, nulls, sizeof(nic->gateway))) 791 - rc = 1; 792 - break; 793 - case ibft_eth_primary_dns: 794 - if (memcmp(nic->primary_dns, nulls, 795 - sizeof(nic->primary_dns))) 796 - rc = 1; 797 - break; 798 - case ibft_eth_secondary_dns: 799 - if (memcmp(nic->secondary_dns, nulls, 800 - sizeof(nic->secondary_dns))) 801 - rc = 1; 802 - break; 803 - case ibft_eth_dhcp: 804 - if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) 805 - rc = 1; 806 - break; 807 - case ibft_eth_vlan: 808 - case ibft_eth_mac: 809 - rc = 1; 810 - break; 811 - case ibft_eth_hostname: 812 - if (nic->hostname_off) 813 - rc = 1; 814 - break; 815 - default: 816 - break; 817 - } 818 - 819 - return rc; 820 - } 821 - 822 - static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry) 823 - { 824 - int rc = 0; 825 - 826 - switch (entry) { 827 - case ibft_tgt_index: 828 - case ibft_tgt_flags: 829 - case ibft_tgt_ip_addr: 830 - case ibft_tgt_port: 831 - case ibft_tgt_lun: 832 - case ibft_tgt_nic_assoc: 833 - case ibft_tgt_chap_type: 834 - rc = 1; 835 - case ibft_tgt_name: 836 - if (tgt->tgt_name_len) 837 - rc = 1; 838 - break; 839 - case ibft_tgt_chap_name: 840 - case ibft_tgt_chap_secret: 841 - if (tgt->chap_name_len) 842 - rc = 1; 843 - break; 844 - case ibft_tgt_rev_chap_name: 845 - case ibft_tgt_rev_chap_secret: 846 - if (tgt->rev_chap_name_len) 847 - rc = 1; 848 - break; 849 - default: 850 - break; 851 - } 852 - 853 - return rc; 854 - } 855 - 856 - static int __init ibft_check_initiator_for(struct ibft_initiator *init, 857 - int entry) 858 - { 859 - int rc = 0; 860 - 861 - switch (entry) { 862 - case ibft_init_index: 863 - case ibft_init_flags: 864 - rc = 1; 865 - break; 866 - case ibft_init_isns_server: 867 - if (memcmp(init->isns_server, nulls, 868 - sizeof(init->isns_server))) 869 - rc = 1; 870 - break; 871 - case ibft_init_slp_server: 872 - if (memcmp(init->slp_server, nulls, 873 - sizeof(init->slp_server))) 874 - rc = 1; 875 - break; 876 - case ibft_init_pri_radius_server: 877 - if (memcmp(init->pri_radius_server, nulls, 878 - sizeof(init->pri_radius_server))) 879 - rc = 1; 880 - break; 881 - case ibft_init_sec_radius_server: 882 - if (memcmp(init->sec_radius_server, nulls, 883 - sizeof(init->sec_radius_server))) 884 - rc = 1; 885 - break; 886 - case ibft_init_initiator_name: 887 - if (init->initiator_name_len) 888 - rc = 1; 889 - break; 890 - default: 891 - break; 892 - } 893 - 894 - return rc; 895 - } 896 - 897 - /* 898 - * Register the attributes for all of the kobjects. 899 - */ 900 - static int __init ibft_register_attributes(struct list_head *kobject_list, 901 - struct list_head *attr_list) 902 - { 903 - int rc = 0, i = 0; 904 - struct ibft_kobject *data = NULL; 905 - struct ibft_attribute *attr = NULL, *m; 906 - 907 - list_for_each_entry(data, kobject_list, node) { 908 - switch (data->hdr->id) { 909 - case id_nic: 910 - for (i = 0; i < ibft_eth_end_marker && !rc; i++) 911 - if (ibft_check_nic_for(data->nic, i)) 912 - rc = ibft_create_attribute(data, i, 913 - ibft_eth_properties[i], 914 - ibft_attr_show_nic, attr_list); 915 - break; 916 - case id_target: 917 - for (i = 0; i < ibft_tgt_end_marker && !rc; i++) 918 - if (ibft_check_tgt_for(data->tgt, i)) 919 - rc = ibft_create_attribute(data, i, 920 - ibft_tgt_properties[i], 921 - ibft_attr_show_target, 922 - attr_list); 923 - break; 924 - case id_initiator: 925 - for (i = 0; i < ibft_init_end_marker && !rc; i++) 926 - if (ibft_check_initiator_for( 927 - data->initiator, i)) 928 - rc = ibft_create_attribute(data, i, 929 - ibft_initiator_properties[i], 930 - ibft_attr_show_initiator, 931 - attr_list); 932 - break; 933 - default: 934 - break; 935 - } 936 - if (rc) 937 - break; 938 - } 939 - list_for_each_entry_safe(attr, m, attr_list, node) { 940 - rc = sysfs_create_file(attr->kobj, &attr->attr); 941 - if (rc) { 942 - list_del(&attr->node); 943 - kfree(attr); 944 - break; 945 - } 946 - } 947 - 948 - return rc; 708 + ibft_cleanup(); 949 709 } 950 710 951 711 /* ··· 743 927 { 744 928 int rc = 0; 745 929 746 - ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj); 747 - if (!ibft_kset) 748 - return -ENOMEM; 749 - 750 930 if (ibft_addr) { 751 931 printk(KERN_INFO "iBFT detected at 0x%llx.\n", 752 932 (u64)isa_virt_to_bus(ibft_addr)); 753 933 754 934 rc = ibft_check_device(); 755 935 if (rc) 756 - goto out_firmware_unregister; 936 + return rc; 937 + 938 + boot_kset = iscsi_boot_create_kset("ibft"); 939 + if (!boot_kset) 940 + return -ENOMEM; 757 941 758 942 /* Scan the IBFT for data and register the kobjects. */ 759 - rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list); 760 - if (rc) 761 - goto out_free; 762 - 763 - /* Register the attributes */ 764 - rc = ibft_register_attributes(&ibft_kobject_list, 765 - &ibft_attr_list); 943 + rc = ibft_register_kobjects(ibft_addr); 766 944 if (rc) 767 945 goto out_free; 768 946 } else ··· 765 955 return 0; 766 956 767 957 out_free: 768 - ibft_unregister(&ibft_attr_list, &ibft_kobject_list); 769 - out_firmware_unregister: 770 - kset_unregister(ibft_kset); 958 + ibft_cleanup(); 771 959 return rc; 772 - } 773 - 774 - static void __exit ibft_exit(void) 775 - { 776 - ibft_unregister(&ibft_attr_list, &ibft_kobject_list); 777 - kset_unregister(ibft_kset); 778 960 } 779 961 780 962 module_init(ibft_init);
+44 -12
drivers/firmware/iscsi_ibft_find.c
··· 1 1 /* 2 - * Copyright 2007 Red Hat, Inc. 2 + * Copyright 2007-2010 Red Hat, Inc. 3 3 * by Peter Jones <pjones@redhat.com> 4 4 * Copyright 2007 IBM, Inc. 5 5 * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> ··· 22 22 #include <linux/blkdev.h> 23 23 #include <linux/ctype.h> 24 24 #include <linux/device.h> 25 + #include <linux/efi.h> 25 26 #include <linux/err.h> 26 27 #include <linux/init.h> 27 28 #include <linux/limits.h> ··· 31 30 #include <linux/stat.h> 32 31 #include <linux/string.h> 33 32 #include <linux/types.h> 33 + #include <linux/acpi.h> 34 + #include <linux/iscsi_ibft.h> 34 35 35 36 #include <asm/mmzone.h> 36 37 37 38 /* 38 39 * Physical location of iSCSI Boot Format Table. 39 40 */ 40 - struct ibft_table_header *ibft_addr; 41 + struct acpi_table_ibft *ibft_addr; 41 42 EXPORT_SYMBOL_GPL(ibft_addr); 42 43 43 44 #define IBFT_SIGN "iBFT" ··· 49 46 #define VGA_MEM 0xA0000 /* VGA buffer */ 50 47 #define VGA_SIZE 0x20000 /* 128kB */ 51 48 49 + #ifdef CONFIG_ACPI 50 + static int __init acpi_find_ibft(struct acpi_table_header *header) 51 + { 52 + ibft_addr = (struct acpi_table_ibft *)header; 53 + return 0; 54 + } 55 + #endif /* CONFIG_ACPI */ 52 56 53 - /* 54 - * Routine used to find the iSCSI Boot Format Table. The logical 55 - * kernel address is set in the ibft_addr global variable. 56 - */ 57 - unsigned long __init find_ibft_region(unsigned long *sizep) 57 + static int __init find_ibft_in_mem(void) 58 58 { 59 59 unsigned long pos; 60 60 unsigned int len = 0; 61 61 void *virt; 62 - 63 - ibft_addr = NULL; 64 62 65 63 for (pos = IBFT_START; pos < IBFT_END; pos += 16) { 66 64 /* The table can't be inside the VGA BIOS reserved space, ··· 76 72 /* if the length of the table extends past 1M, 77 73 * the table cannot be valid. */ 78 74 if (pos + len <= (IBFT_END-1)) { 79 - ibft_addr = (struct ibft_table_header *)virt; 75 + ibft_addr = (struct acpi_table_ibft *)virt; 80 76 break; 81 77 } 82 78 } 83 79 } 80 + return len; 81 + } 82 + /* 83 + * Routine used to find the iSCSI Boot Format Table. The logical 84 + * kernel address is set in the ibft_addr global variable. 85 + */ 86 + unsigned long __init find_ibft_region(unsigned long *sizep) 87 + { 88 + 89 + ibft_addr = NULL; 90 + 91 + #ifdef CONFIG_ACPI 92 + /* 93 + * One spec says "IBFT", the other says "iBFT". We have to check 94 + * for both. 95 + */ 96 + if (!ibft_addr) 97 + acpi_table_parse(ACPI_SIG_IBFT, acpi_find_ibft); 98 + if (!ibft_addr) 99 + acpi_table_parse(IBFT_SIGN, acpi_find_ibft); 100 + #endif /* CONFIG_ACPI */ 101 + 102 + /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will 103 + * only use ACPI for this */ 104 + 105 + if (!ibft_addr && !efi_enabled) 106 + find_ibft_in_mem(); 107 + 84 108 if (ibft_addr) { 85 - *sizep = PAGE_ALIGN(len); 86 - return pos; 109 + *sizep = PAGE_ALIGN(ibft_addr->header.length); 110 + return (u64)isa_virt_to_bus(ibft_addr); 87 111 } 88 112 89 113 *sizep = 0;
+123
include/linux/iscsi_boot_sysfs.h
··· 1 + /* 2 + * Export the iSCSI boot info to userland via sysfs. 3 + * 4 + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. 5 + * Copyright (C) 2010 Mike Christie 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License v2.0 as published by 9 + * the Free Software Foundation 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + #ifndef _ISCSI_BOOT_SYSFS_ 17 + #define _ISCSI_BOOT_SYSFS_ 18 + 19 + /* 20 + * The text attributes names for each of the kobjects. 21 + */ 22 + enum iscsi_boot_eth_properties_enum { 23 + ISCSI_BOOT_ETH_INDEX, 24 + ISCSI_BOOT_ETH_FLAGS, 25 + ISCSI_BOOT_ETH_IP_ADDR, 26 + ISCSI_BOOT_ETH_SUBNET_MASK, 27 + ISCSI_BOOT_ETH_ORIGIN, 28 + ISCSI_BOOT_ETH_GATEWAY, 29 + ISCSI_BOOT_ETH_PRIMARY_DNS, 30 + ISCSI_BOOT_ETH_SECONDARY_DNS, 31 + ISCSI_BOOT_ETH_DHCP, 32 + ISCSI_BOOT_ETH_VLAN, 33 + ISCSI_BOOT_ETH_MAC, 34 + /* eth_pci_bdf - this is replaced by link to the device itself. */ 35 + ISCSI_BOOT_ETH_HOSTNAME, 36 + ISCSI_BOOT_ETH_END_MARKER, 37 + }; 38 + 39 + enum iscsi_boot_tgt_properties_enum { 40 + ISCSI_BOOT_TGT_INDEX, 41 + ISCSI_BOOT_TGT_FLAGS, 42 + ISCSI_BOOT_TGT_IP_ADDR, 43 + ISCSI_BOOT_TGT_PORT, 44 + ISCSI_BOOT_TGT_LUN, 45 + ISCSI_BOOT_TGT_CHAP_TYPE, 46 + ISCSI_BOOT_TGT_NIC_ASSOC, 47 + ISCSI_BOOT_TGT_NAME, 48 + ISCSI_BOOT_TGT_CHAP_NAME, 49 + ISCSI_BOOT_TGT_CHAP_SECRET, 50 + ISCSI_BOOT_TGT_REV_CHAP_NAME, 51 + ISCSI_BOOT_TGT_REV_CHAP_SECRET, 52 + ISCSI_BOOT_TGT_END_MARKER, 53 + }; 54 + 55 + enum iscsi_boot_initiator_properties_enum { 56 + ISCSI_BOOT_INI_INDEX, 57 + ISCSI_BOOT_INI_FLAGS, 58 + ISCSI_BOOT_INI_ISNS_SERVER, 59 + ISCSI_BOOT_INI_SLP_SERVER, 60 + ISCSI_BOOT_INI_PRI_RADIUS_SERVER, 61 + ISCSI_BOOT_INI_SEC_RADIUS_SERVER, 62 + ISCSI_BOOT_INI_INITIATOR_NAME, 63 + ISCSI_BOOT_INI_END_MARKER, 64 + }; 65 + 66 + struct attribute_group; 67 + 68 + struct iscsi_boot_kobj { 69 + struct kobject kobj; 70 + struct attribute_group *attr_group; 71 + struct list_head list; 72 + 73 + /* 74 + * Pointer to store driver specific info. If set this will 75 + * be freed for the LLD when the kobj release function is called. 76 + */ 77 + void *data; 78 + /* 79 + * Driver specific show function. 80 + * 81 + * The enum of the type. This can be any value of the above 82 + * properties. 83 + */ 84 + ssize_t (*show) (void *data, int type, char *buf); 85 + 86 + /* 87 + * Drivers specific visibility function. 88 + * The function should return if they the attr should be readable 89 + * writable or should not be shown. 90 + * 91 + * The enum of the type. This can be any value of the above 92 + * properties. 93 + */ 94 + mode_t (*is_visible) (void *data, int type); 95 + }; 96 + 97 + struct iscsi_boot_kset { 98 + struct list_head kobj_list; 99 + struct kset *kset; 100 + }; 101 + 102 + struct iscsi_boot_kobj * 103 + iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, 104 + void *data, 105 + ssize_t (*show) (void *data, int type, char *buf), 106 + mode_t (*is_visible) (void *data, int type)); 107 + 108 + struct iscsi_boot_kobj * 109 + iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, 110 + void *data, 111 + ssize_t (*show) (void *data, int type, char *buf), 112 + mode_t (*is_visible) (void *data, int type)); 113 + struct iscsi_boot_kobj * 114 + iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, 115 + void *data, 116 + ssize_t (*show) (void *data, int type, char *buf), 117 + mode_t (*is_visible) (void *data, int type)); 118 + 119 + struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name); 120 + struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno); 121 + void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset); 122 + 123 + #endif
+2 -10
include/linux/iscsi_ibft.h
··· 21 21 #ifndef ISCSI_IBFT_H 22 22 #define ISCSI_IBFT_H 23 23 24 - struct ibft_table_header { 25 - char signature[4]; 26 - u32 length; 27 - u8 revision; 28 - u8 checksum; 29 - char oem_id[6]; 30 - char oem_table_id[8]; 31 - char reserved[24]; 32 - } __attribute__((__packed__)); 24 + #include <acpi/acpi.h> 33 25 34 26 /* 35 27 * Logical location of iSCSI Boot Format Table. 36 28 * If the value is NULL there is no iBFT on the machine. 37 29 */ 38 - extern struct ibft_table_header *ibft_addr; 30 + extern struct acpi_table_ibft *ibft_addr; 39 31 40 32 /* 41 33 * Routine used to find and reserve the iSCSI Boot Format Table. The