aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/iscsi_ibft.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/iscsi_ibft.c')
-rw-r--r--drivers/firmware/iscsi_ibft.c698
1 files changed, 247 insertions, 451 deletions
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index b3ab24f9d78f..4f04ec0410a0 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -82,6 +82,7 @@
82#include <linux/string.h> 82#include <linux/string.h>
83#include <linux/types.h> 83#include <linux/types.h>
84#include <linux/acpi.h> 84#include <linux/acpi.h>
85#include <linux/iscsi_boot_sysfs.h>
85 86
86#define IBFT_ISCSI_VERSION "0.5.0" 87#define IBFT_ISCSI_VERSION "0.5.0"
87#define IBFT_ISCSI_DATE "2010-Feb-25" 88#define IBFT_ISCSI_DATE "2010-Feb-25"
@@ -170,74 +171,6 @@ enum ibft_id {
170}; 171};
171 172
172/* 173/*
173 * We do not support the other types, hence the usage of NULL.
174 * This maps to the enum ibft_id.
175 */
176static const char *ibft_id_names[] =
177 {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
178
179/*
180 * The text attributes names for each of the kobjects.
181*/
182enum ibft_eth_properties_enum {
183 ibft_eth_index,
184 ibft_eth_flags,
185 ibft_eth_ip_addr,
186 ibft_eth_subnet_mask,
187 ibft_eth_origin,
188 ibft_eth_gateway,
189 ibft_eth_primary_dns,
190 ibft_eth_secondary_dns,
191 ibft_eth_dhcp,
192 ibft_eth_vlan,
193 ibft_eth_mac,
194 /* ibft_eth_pci_bdf - this is replaced by link to the device itself. */
195 ibft_eth_hostname,
196 ibft_eth_end_marker,
197};
198
199static const char *ibft_eth_properties[] =
200 {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
201 "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
202 NULL};
203
204enum ibft_tgt_properties_enum {
205 ibft_tgt_index,
206 ibft_tgt_flags,
207 ibft_tgt_ip_addr,
208 ibft_tgt_port,
209 ibft_tgt_lun,
210 ibft_tgt_chap_type,
211 ibft_tgt_nic_assoc,
212 ibft_tgt_name,
213 ibft_tgt_chap_name,
214 ibft_tgt_chap_secret,
215 ibft_tgt_rev_chap_name,
216 ibft_tgt_rev_chap_secret,
217 ibft_tgt_end_marker,
218};
219
220static const char *ibft_tgt_properties[] =
221 {"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc",
222 "target-name", "chap-name", "chap-secret", "rev-chap-name",
223 "rev-chap-name-secret", NULL};
224
225enum ibft_initiator_properties_enum {
226 ibft_init_index,
227 ibft_init_flags,
228 ibft_init_isns_server,
229 ibft_init_slp_server,
230 ibft_init_pri_radius_server,
231 ibft_init_sec_radius_server,
232 ibft_init_initiator_name,
233 ibft_init_end_marker,
234};
235
236static const char *ibft_initiator_properties[] =
237 {"index", "flags", "isns-server", "slp-server", "pri-radius-server",
238 "sec-radius-server", "initiator-name", NULL};
239
240/*
241 * The kobject and attribute structures. 174 * The kobject and attribute structures.
242 */ 175 */
243 176
@@ -249,29 +182,9 @@ struct ibft_kobject {
249 struct ibft_tgt *tgt; 182 struct ibft_tgt *tgt;
250 struct ibft_hdr *hdr; 183 struct ibft_hdr *hdr;
251 }; 184 };
252 struct kobject kobj;
253 struct list_head node;
254}; 185};
255 186
256struct ibft_attribute { 187static struct iscsi_boot_kset *boot_kset;
257 struct attribute attr;
258 ssize_t (*show) (struct ibft_kobject *entry,
259 struct ibft_attribute *attr, char *buf);
260 union {
261 struct ibft_initiator *initiator;
262 struct ibft_nic *nic;
263 struct ibft_tgt *tgt;
264 struct ibft_hdr *hdr;
265 };
266 struct kobject *kobj;
267 int type; /* The enum of the type. This can be any value of:
268 ibft_eth_properties_enum, ibft_tgt_properties_enum,
269 or ibft_initiator_properties_enum. */
270 struct list_head node;
271};
272
273static LIST_HEAD(ibft_attr_list);
274static LIST_HEAD(ibft_kobject_list);
275 188
276static const char nulls[16]; 189static const char nulls[16];
277 190
@@ -310,35 +223,27 @@ static ssize_t sprintf_string(char *str, int len, char *buf)
310static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length) 223static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
311{ 224{
312 if (hdr->id != id) { 225 if (hdr->id != id) {
313 printk(KERN_ERR "iBFT error: We expected the " \ 226 printk(KERN_ERR "iBFT error: We expected the %s " \
314 "field header.id to have %d but " \ 227 "field header.id to have %d but " \
315 "found %d instead!\n", id, hdr->id); 228 "found %d instead!\n", t, id, hdr->id);
316 return -ENODEV; 229 return -ENODEV;
317 } 230 }
318 if (hdr->length != length) { 231 if (hdr->length != length) {
319 printk(KERN_ERR "iBFT error: We expected the " \ 232 printk(KERN_ERR "iBFT error: We expected the %s " \
320 "field header.length to have %d but " \ 233 "field header.length to have %d but " \
321 "found %d instead!\n", length, hdr->length); 234 "found %d instead!\n", t, length, hdr->length);
322 return -ENODEV; 235 return -ENODEV;
323 } 236 }
324 237
325 return 0; 238 return 0;
326} 239}
327 240
328static void ibft_release(struct kobject *kobj)
329{
330 struct ibft_kobject *ibft =
331 container_of(kobj, struct ibft_kobject, kobj);
332 kfree(ibft);
333}
334
335/* 241/*
336 * Routines for parsing the iBFT data to be human readable. 242 * Routines for parsing the iBFT data to be human readable.
337 */ 243 */
338static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry, 244static ssize_t ibft_attr_show_initiator(void *data, int type, char *buf)
339 struct ibft_attribute *attr,
340 char *buf)
341{ 245{
246 struct ibft_kobject *entry = data;
342 struct ibft_initiator *initiator = entry->initiator; 247 struct ibft_initiator *initiator = entry->initiator;
343 void *ibft_loc = entry->header; 248 void *ibft_loc = entry->header;
344 char *str = buf; 249 char *str = buf;
@@ -346,26 +251,26 @@ static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
346 if (!initiator) 251 if (!initiator)
347 return 0; 252 return 0;
348 253
349 switch (attr->type) { 254 switch (type) {
350 case ibft_init_index: 255 case ISCSI_BOOT_INI_INDEX:
351 str += sprintf(str, "%d\n", initiator->hdr.index); 256 str += sprintf(str, "%d\n", initiator->hdr.index);
352 break; 257 break;
353 case ibft_init_flags: 258 case ISCSI_BOOT_INI_FLAGS:
354 str += sprintf(str, "%d\n", initiator->hdr.flags); 259 str += sprintf(str, "%d\n", initiator->hdr.flags);
355 break; 260 break;
356 case ibft_init_isns_server: 261 case ISCSI_BOOT_INI_ISNS_SERVER:
357 str += sprintf_ipaddr(str, initiator->isns_server); 262 str += sprintf_ipaddr(str, initiator->isns_server);
358 break; 263 break;
359 case ibft_init_slp_server: 264 case ISCSI_BOOT_INI_SLP_SERVER:
360 str += sprintf_ipaddr(str, initiator->slp_server); 265 str += sprintf_ipaddr(str, initiator->slp_server);
361 break; 266 break;
362 case ibft_init_pri_radius_server: 267 case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
363 str += sprintf_ipaddr(str, initiator->pri_radius_server); 268 str += sprintf_ipaddr(str, initiator->pri_radius_server);
364 break; 269 break;
365 case ibft_init_sec_radius_server: 270 case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
366 str += sprintf_ipaddr(str, initiator->sec_radius_server); 271 str += sprintf_ipaddr(str, initiator->sec_radius_server);
367 break; 272 break;
368 case ibft_init_initiator_name: 273 case ISCSI_BOOT_INI_INITIATOR_NAME:
369 str += sprintf_string(str, initiator->initiator_name_len, 274 str += sprintf_string(str, initiator->initiator_name_len,
370 (char *)ibft_loc + 275 (char *)ibft_loc +
371 initiator->initiator_name_off); 276 initiator->initiator_name_off);
@@ -377,10 +282,9 @@ static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
377 return str - buf; 282 return str - buf;
378} 283}
379 284
380static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, 285static ssize_t ibft_attr_show_nic(void *data, int type, char *buf)
381 struct ibft_attribute *attr,
382 char *buf)
383{ 286{
287 struct ibft_kobject *entry = data;
384 struct ibft_nic *nic = entry->nic; 288 struct ibft_nic *nic = entry->nic;
385 void *ibft_loc = entry->header; 289 void *ibft_loc = entry->header;
386 char *str = buf; 290 char *str = buf;
@@ -389,42 +293,42 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
389 if (!nic) 293 if (!nic)
390 return 0; 294 return 0;
391 295
392 switch (attr->type) { 296 switch (type) {
393 case ibft_eth_index: 297 case ISCSI_BOOT_ETH_INDEX:
394 str += sprintf(str, "%d\n", nic->hdr.index); 298 str += sprintf(str, "%d\n", nic->hdr.index);
395 break; 299 break;
396 case ibft_eth_flags: 300 case ISCSI_BOOT_ETH_FLAGS:
397 str += sprintf(str, "%d\n", nic->hdr.flags); 301 str += sprintf(str, "%d\n", nic->hdr.flags);
398 break; 302 break;
399 case ibft_eth_ip_addr: 303 case ISCSI_BOOT_ETH_IP_ADDR:
400 str += sprintf_ipaddr(str, nic->ip_addr); 304 str += sprintf_ipaddr(str, nic->ip_addr);
401 break; 305 break;
402 case ibft_eth_subnet_mask: 306 case ISCSI_BOOT_ETH_SUBNET_MASK:
403 val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1)); 307 val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
404 str += sprintf(str, "%pI4", &val); 308 str += sprintf(str, "%pI4", &val);
405 break; 309 break;
406 case ibft_eth_origin: 310 case ISCSI_BOOT_ETH_ORIGIN:
407 str += sprintf(str, "%d\n", nic->origin); 311 str += sprintf(str, "%d\n", nic->origin);
408 break; 312 break;
409 case ibft_eth_gateway: 313 case ISCSI_BOOT_ETH_GATEWAY:
410 str += sprintf_ipaddr(str, nic->gateway); 314 str += sprintf_ipaddr(str, nic->gateway);
411 break; 315 break;
412 case ibft_eth_primary_dns: 316 case ISCSI_BOOT_ETH_PRIMARY_DNS:
413 str += sprintf_ipaddr(str, nic->primary_dns); 317 str += sprintf_ipaddr(str, nic->primary_dns);
414 break; 318 break;
415 case ibft_eth_secondary_dns: 319 case ISCSI_BOOT_ETH_SECONDARY_DNS:
416 str += sprintf_ipaddr(str, nic->secondary_dns); 320 str += sprintf_ipaddr(str, nic->secondary_dns);
417 break; 321 break;
418 case ibft_eth_dhcp: 322 case ISCSI_BOOT_ETH_DHCP:
419 str += sprintf_ipaddr(str, nic->dhcp); 323 str += sprintf_ipaddr(str, nic->dhcp);
420 break; 324 break;
421 case ibft_eth_vlan: 325 case ISCSI_BOOT_ETH_VLAN:
422 str += sprintf(str, "%d\n", nic->vlan); 326 str += sprintf(str, "%d\n", nic->vlan);
423 break; 327 break;
424 case ibft_eth_mac: 328 case ISCSI_BOOT_ETH_MAC:
425 str += sprintf(str, "%pM\n", nic->mac); 329 str += sprintf(str, "%pM\n", nic->mac);
426 break; 330 break;
427 case ibft_eth_hostname: 331 case ISCSI_BOOT_ETH_HOSTNAME:
428 str += sprintf_string(str, nic->hostname_len, 332 str += sprintf_string(str, nic->hostname_len,
429 (char *)ibft_loc + nic->hostname_off); 333 (char *)ibft_loc + nic->hostname_off);
430 break; 334 break;
@@ -435,10 +339,9 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
435 return str - buf; 339 return str - buf;
436}; 340};
437 341
438static ssize_t ibft_attr_show_target(struct ibft_kobject *entry, 342static ssize_t ibft_attr_show_target(void *data, int type, char *buf)
439 struct ibft_attribute *attr,
440 char *buf)
441{ 343{
344 struct ibft_kobject *entry = data;
442 struct ibft_tgt *tgt = entry->tgt; 345 struct ibft_tgt *tgt = entry->tgt;
443 void *ibft_loc = entry->header; 346 void *ibft_loc = entry->header;
444 char *str = buf; 347 char *str = buf;
@@ -447,48 +350,48 @@ static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
447 if (!tgt) 350 if (!tgt)
448 return 0; 351 return 0;
449 352
450 switch (attr->type) { 353 switch (type) {
451 case ibft_tgt_index: 354 case ISCSI_BOOT_TGT_INDEX:
452 str += sprintf(str, "%d\n", tgt->hdr.index); 355 str += sprintf(str, "%d\n", tgt->hdr.index);
453 break; 356 break;
454 case ibft_tgt_flags: 357 case ISCSI_BOOT_TGT_FLAGS:
455 str += sprintf(str, "%d\n", tgt->hdr.flags); 358 str += sprintf(str, "%d\n", tgt->hdr.flags);
456 break; 359 break;
457 case ibft_tgt_ip_addr: 360 case ISCSI_BOOT_TGT_IP_ADDR:
458 str += sprintf_ipaddr(str, tgt->ip_addr); 361 str += sprintf_ipaddr(str, tgt->ip_addr);
459 break; 362 break;
460 case ibft_tgt_port: 363 case ISCSI_BOOT_TGT_PORT:
461 str += sprintf(str, "%d\n", tgt->port); 364 str += sprintf(str, "%d\n", tgt->port);
462 break; 365 break;
463 case ibft_tgt_lun: 366 case ISCSI_BOOT_TGT_LUN:
464 for (i = 0; i < 8; i++) 367 for (i = 0; i < 8; i++)
465 str += sprintf(str, "%x", (u8)tgt->lun[i]); 368 str += sprintf(str, "%x", (u8)tgt->lun[i]);
466 str += sprintf(str, "\n"); 369 str += sprintf(str, "\n");
467 break; 370 break;
468 case ibft_tgt_nic_assoc: 371 case ISCSI_BOOT_TGT_NIC_ASSOC:
469 str += sprintf(str, "%d\n", tgt->nic_assoc); 372 str += sprintf(str, "%d\n", tgt->nic_assoc);
470 break; 373 break;
471 case ibft_tgt_chap_type: 374 case ISCSI_BOOT_TGT_CHAP_TYPE:
472 str += sprintf(str, "%d\n", tgt->chap_type); 375 str += sprintf(str, "%d\n", tgt->chap_type);
473 break; 376 break;
474 case ibft_tgt_name: 377 case ISCSI_BOOT_TGT_NAME:
475 str += sprintf_string(str, tgt->tgt_name_len, 378 str += sprintf_string(str, tgt->tgt_name_len,
476 (char *)ibft_loc + tgt->tgt_name_off); 379 (char *)ibft_loc + tgt->tgt_name_off);
477 break; 380 break;
478 case ibft_tgt_chap_name: 381 case ISCSI_BOOT_TGT_CHAP_NAME:
479 str += sprintf_string(str, tgt->chap_name_len, 382 str += sprintf_string(str, tgt->chap_name_len,
480 (char *)ibft_loc + tgt->chap_name_off); 383 (char *)ibft_loc + tgt->chap_name_off);
481 break; 384 break;
482 case ibft_tgt_chap_secret: 385 case ISCSI_BOOT_TGT_CHAP_SECRET:
483 str += sprintf_string(str, tgt->chap_secret_len, 386 str += sprintf_string(str, tgt->chap_secret_len,
484 (char *)ibft_loc + tgt->chap_secret_off); 387 (char *)ibft_loc + tgt->chap_secret_off);
485 break; 388 break;
486 case ibft_tgt_rev_chap_name: 389 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
487 str += sprintf_string(str, tgt->rev_chap_name_len, 390 str += sprintf_string(str, tgt->rev_chap_name_len,
488 (char *)ibft_loc + 391 (char *)ibft_loc +
489 tgt->rev_chap_name_off); 392 tgt->rev_chap_name_off);
490 break; 393 break;
491 case ibft_tgt_rev_chap_secret: 394 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
492 str += sprintf_string(str, tgt->rev_chap_secret_len, 395 str += sprintf_string(str, tgt->rev_chap_secret_len,
493 (char *)ibft_loc + 396 (char *)ibft_loc +
494 tgt->rev_chap_secret_off); 397 tgt->rev_chap_secret_off);
@@ -500,40 +403,6 @@ static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
500 return str - buf; 403 return str - buf;
501} 404}
502 405
503/*
504 * The routine called for all sysfs attributes.
505 */
506static ssize_t ibft_show_attribute(struct kobject *kobj,
507 struct attribute *attr,
508 char *buf)
509{
510 struct ibft_kobject *dev =
511 container_of(kobj, struct ibft_kobject, kobj);
512 struct ibft_attribute *ibft_attr =
513 container_of(attr, struct ibft_attribute, attr);
514 ssize_t ret = -EIO;
515 char *str = buf;
516
517 if (!capable(CAP_SYS_ADMIN))
518 return -EACCES;
519
520 if (ibft_attr->show)
521 ret = ibft_attr->show(dev, ibft_attr, str);
522
523 return ret;
524}
525
526static const struct sysfs_ops ibft_attr_ops = {
527 .show = ibft_show_attribute,
528};
529
530static struct kobj_type ibft_ktype = {
531 .release = ibft_release,
532 .sysfs_ops = &ibft_attr_ops,
533};
534
535static struct kset *ibft_kset;
536
537static int __init ibft_check_device(void) 406static int __init ibft_check_device(void)
538{ 407{
539 int len; 408 int len;
@@ -561,12 +430,149 @@ static int __init ibft_check_device(void)
561} 430}
562 431
563/* 432/*
433 * Helper routiners to check to determine if the entry is valid
434 * in the proper iBFT structure.
435 */
436static mode_t ibft_check_nic_for(void *data, int type)
437{
438 struct ibft_kobject *entry = data;
439 struct ibft_nic *nic = entry->nic;
440 mode_t rc = 0;
441
442 switch (type) {
443 case ISCSI_BOOT_ETH_INDEX:
444 case ISCSI_BOOT_ETH_FLAGS:
445 rc = S_IRUGO;
446 break;
447 case ISCSI_BOOT_ETH_IP_ADDR:
448 if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
449 rc = S_IRUGO;
450 break;
451 case ISCSI_BOOT_ETH_SUBNET_MASK:
452 if (nic->subnet_mask_prefix)
453 rc = S_IRUGO;
454 break;
455 case ISCSI_BOOT_ETH_ORIGIN:
456 rc = S_IRUGO;
457 break;
458 case ISCSI_BOOT_ETH_GATEWAY:
459 if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
460 rc = S_IRUGO;
461 break;
462 case ISCSI_BOOT_ETH_PRIMARY_DNS:
463 if (memcmp(nic->primary_dns, nulls,
464 sizeof(nic->primary_dns)))
465 rc = S_IRUGO;
466 break;
467 case ISCSI_BOOT_ETH_SECONDARY_DNS:
468 if (memcmp(nic->secondary_dns, nulls,
469 sizeof(nic->secondary_dns)))
470 rc = S_IRUGO;
471 break;
472 case ISCSI_BOOT_ETH_DHCP:
473 if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
474 rc = S_IRUGO;
475 break;
476 case ISCSI_BOOT_ETH_VLAN:
477 case ISCSI_BOOT_ETH_MAC:
478 rc = S_IRUGO;
479 break;
480 case ISCSI_BOOT_ETH_HOSTNAME:
481 if (nic->hostname_off)
482 rc = S_IRUGO;
483 break;
484 default:
485 break;
486 }
487
488 return rc;
489}
490
491static mode_t __init ibft_check_tgt_for(void *data, int type)
492{
493 struct ibft_kobject *entry = data;
494 struct ibft_tgt *tgt = entry->tgt;
495 mode_t rc = 0;
496
497 switch (type) {
498 case ISCSI_BOOT_TGT_INDEX:
499 case ISCSI_BOOT_TGT_FLAGS:
500 case ISCSI_BOOT_TGT_IP_ADDR:
501 case ISCSI_BOOT_TGT_PORT:
502 case ISCSI_BOOT_TGT_LUN:
503 case ISCSI_BOOT_TGT_NIC_ASSOC:
504 case ISCSI_BOOT_TGT_CHAP_TYPE:
505 rc = S_IRUGO;
506 case ISCSI_BOOT_TGT_NAME:
507 if (tgt->tgt_name_len)
508 rc = S_IRUGO;
509 break;
510 case ISCSI_BOOT_TGT_CHAP_NAME:
511 case ISCSI_BOOT_TGT_CHAP_SECRET:
512 if (tgt->chap_name_len)
513 rc = S_IRUGO;
514 break;
515 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
516 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
517 if (tgt->rev_chap_name_len)
518 rc = S_IRUGO;
519 break;
520 default:
521 break;
522 }
523
524 return rc;
525}
526
527static mode_t __init ibft_check_initiator_for(void *data, int type)
528{
529 struct ibft_kobject *entry = data;
530 struct ibft_initiator *init = entry->initiator;
531 mode_t rc = 0;
532
533 switch (type) {
534 case ISCSI_BOOT_INI_INDEX:
535 case ISCSI_BOOT_INI_FLAGS:
536 rc = S_IRUGO;
537 break;
538 case ISCSI_BOOT_INI_ISNS_SERVER:
539 if (memcmp(init->isns_server, nulls,
540 sizeof(init->isns_server)))
541 rc = S_IRUGO;
542 break;
543 case ISCSI_BOOT_INI_SLP_SERVER:
544 if (memcmp(init->slp_server, nulls,
545 sizeof(init->slp_server)))
546 rc = S_IRUGO;
547 break;
548 case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
549 if (memcmp(init->pri_radius_server, nulls,
550 sizeof(init->pri_radius_server)))
551 rc = S_IRUGO;
552 break;
553 case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
554 if (memcmp(init->sec_radius_server, nulls,
555 sizeof(init->sec_radius_server)))
556 rc = S_IRUGO;
557 break;
558 case ISCSI_BOOT_INI_INITIATOR_NAME:
559 if (init->initiator_name_len)
560 rc = S_IRUGO;
561 break;
562 default:
563 break;
564 }
565
566 return rc;
567}
568
569/*
564 * Helper function for ibft_register_kobjects. 570 * Helper function for ibft_register_kobjects.
565 */ 571 */
566static int __init ibft_create_kobject(struct acpi_table_ibft *header, 572static int __init ibft_create_kobject(struct acpi_table_ibft *header,
567 struct ibft_hdr *hdr, 573 struct ibft_hdr *hdr)
568 struct list_head *list)
569{ 574{
575 struct iscsi_boot_kobj *boot_kobj = NULL;
570 struct ibft_kobject *ibft_kobj = NULL; 576 struct ibft_kobject *ibft_kobj = NULL;
571 struct ibft_nic *nic = (struct ibft_nic *)hdr; 577 struct ibft_nic *nic = (struct ibft_nic *)hdr;
572 struct pci_dev *pci_dev; 578 struct pci_dev *pci_dev;
@@ -583,14 +589,47 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
583 case id_initiator: 589 case id_initiator:
584 rc = ibft_verify_hdr("initiator", hdr, id_initiator, 590 rc = ibft_verify_hdr("initiator", hdr, id_initiator,
585 sizeof(*ibft_kobj->initiator)); 591 sizeof(*ibft_kobj->initiator));
592 if (rc)
593 break;
594
595 boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
596 ibft_kobj,
597 ibft_attr_show_initiator,
598 ibft_check_initiator_for);
599 if (!boot_kobj) {
600 rc = -ENOMEM;
601 goto free_ibft_obj;
602 }
586 break; 603 break;
587 case id_nic: 604 case id_nic:
588 rc = ibft_verify_hdr("ethernet", hdr, id_nic, 605 rc = ibft_verify_hdr("ethernet", hdr, id_nic,
589 sizeof(*ibft_kobj->nic)); 606 sizeof(*ibft_kobj->nic));
607 if (rc)
608 break;
609
610 boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
611 ibft_kobj,
612 ibft_attr_show_nic,
613 ibft_check_nic_for);
614 if (!boot_kobj) {
615 rc = -ENOMEM;
616 goto free_ibft_obj;
617 }
590 break; 618 break;
591 case id_target: 619 case id_target:
592 rc = ibft_verify_hdr("target", hdr, id_target, 620 rc = ibft_verify_hdr("target", hdr, id_target,
593 sizeof(*ibft_kobj->tgt)); 621 sizeof(*ibft_kobj->tgt));
622 if (rc)
623 break;
624
625 boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
626 ibft_kobj,
627 ibft_attr_show_target,
628 ibft_check_tgt_for);
629 if (!boot_kobj) {
630 rc = -ENOMEM;
631 goto free_ibft_obj;
632 }
594 break; 633 break;
595 case id_reserved: 634 case id_reserved:
596 case id_control: 635 case id_control:
@@ -608,22 +647,10 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
608 647
609 if (rc) { 648 if (rc) {
610 /* Skip adding this kobject, but exit with non-fatal error. */ 649 /* Skip adding this kobject, but exit with non-fatal error. */
611 kfree(ibft_kobj); 650 rc = 0;
612 goto out_invalid_struct; 651 goto free_ibft_obj;
613 }
614
615 ibft_kobj->kobj.kset = ibft_kset;
616
617 rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
618 NULL, ibft_id_names[hdr->id], hdr->index);
619
620 if (rc) {
621 kfree(ibft_kobj);
622 goto out;
623 } 652 }
624 653
625 kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD);
626
627 if (hdr->id == id_nic) { 654 if (hdr->id == id_nic) {
628 /* 655 /*
629 * We don't search for the device in other domains than 656 * We don't search for the device in other domains than
@@ -634,19 +661,16 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
634 pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, 661 pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8,
635 (nic->pci_bdf & 0xff)); 662 (nic->pci_bdf & 0xff));
636 if (pci_dev) { 663 if (pci_dev) {
637 rc = sysfs_create_link(&ibft_kobj->kobj, 664 rc = sysfs_create_link(&boot_kobj->kobj,
638 &pci_dev->dev.kobj, "device"); 665 &pci_dev->dev.kobj, "device");
639 pci_dev_put(pci_dev); 666 pci_dev_put(pci_dev);
640 } 667 }
641 } 668 }
669 return 0;
642 670
643 /* Nothing broke so lets add it to the list. */ 671free_ibft_obj:
644 list_add_tail(&ibft_kobj->node, list); 672 kfree(ibft_kobj);
645out:
646 return rc; 673 return rc;
647out_invalid_struct:
648 /* Unsupported structs are skipped. */
649 return 0;
650} 674}
651 675
652/* 676/*
@@ -654,8 +678,7 @@ out_invalid_struct:
654 * found add them on the passed-in list. We do not support the other 678 * found add them on the passed-in list. We do not support the other
655 * fields at this point, so they are skipped. 679 * fields at this point, so they are skipped.
656 */ 680 */
657static int __init ibft_register_kobjects(struct acpi_table_ibft *header, 681static int __init ibft_register_kobjects(struct acpi_table_ibft *header)
658 struct list_head *list)
659{ 682{
660 struct ibft_control *control = NULL; 683 struct ibft_control *control = NULL;
661 void *ptr, *end; 684 void *ptr, *end;
@@ -680,8 +703,7 @@ static int __init ibft_register_kobjects(struct acpi_table_ibft *header,
680 if (offset && offset < header->header.length && 703 if (offset && offset < header->header.length &&
681 offset < eot_offset) { 704 offset < eot_offset) {
682 rc = ibft_create_kobject(header, 705 rc = ibft_create_kobject(header,
683 (void *)header + offset, 706 (void *)header + offset);
684 list);
685 if (rc) 707 if (rc)
686 break; 708 break;
687 } 709 }
@@ -690,240 +712,28 @@ static int __init ibft_register_kobjects(struct acpi_table_ibft *header,
690 return rc; 712 return rc;
691} 713}
692 714
693static void ibft_unregister(struct list_head *attr_list, 715static void ibft_unregister(void)
694 struct list_head *kobj_list)
695{ 716{
696 struct ibft_kobject *data = NULL, *n; 717 struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
697 struct ibft_attribute *attr = NULL, *m; 718 struct ibft_kobject *ibft_kobj;
698 719
699 list_for_each_entry_safe(attr, m, attr_list, node) { 720 list_for_each_entry_safe(boot_kobj, tmp_kobj,
700 sysfs_remove_file(attr->kobj, &attr->attr); 721 &boot_kset->kobj_list, list) {
701 list_del(&attr->node); 722 ibft_kobj = boot_kobj->data;
702 kfree(attr); 723 if (ibft_kobj->hdr->id == id_nic)
724 sysfs_remove_link(&boot_kobj->kobj, "device");
703 }; 725 };
704 list_del_init(attr_list);
705
706 list_for_each_entry_safe(data, n, kobj_list, node) {
707 list_del(&data->node);
708 if (data->hdr->id == id_nic)
709 sysfs_remove_link(&data->kobj, "device");
710 kobject_put(&data->kobj);
711 };
712 list_del_init(kobj_list);
713} 726}
714 727
715static int __init ibft_create_attribute(struct ibft_kobject *kobj_data, 728static void ibft_cleanup(void)
716 int type,
717 const char *name,
718 ssize_t (*show)(struct ibft_kobject *,
719 struct ibft_attribute*,
720 char *buf),
721 struct list_head *list)
722{ 729{
723 struct ibft_attribute *attr = NULL; 730 ibft_unregister();
724 struct ibft_hdr *hdr = kobj_data->hdr; 731 iscsi_boot_destroy_kset(boot_kset);
725
726 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
727 if (!attr)
728 return -ENOMEM;
729
730 attr->attr.name = name;
731 attr->attr.mode = S_IRUSR;
732
733 attr->hdr = hdr;
734 attr->show = show;
735 attr->kobj = &kobj_data->kobj;
736 attr->type = type;
737
738 list_add_tail(&attr->node, list);
739
740 return 0;
741}
742
743/*
744 * Helper routiners to check to determine if the entry is valid
745 * in the proper iBFT structure.
746 */
747static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
748{
749 int rc = 0;
750
751 switch (entry) {
752 case ibft_eth_index:
753 case ibft_eth_flags:
754 rc = 1;
755 break;
756 case ibft_eth_ip_addr:
757 if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
758 rc = 1;
759 break;
760 case ibft_eth_subnet_mask:
761 if (nic->subnet_mask_prefix)
762 rc = 1;
763 break;
764 case ibft_eth_origin:
765 rc = 1;
766 break;
767 case ibft_eth_gateway:
768 if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
769 rc = 1;
770 break;
771 case ibft_eth_primary_dns:
772 if (memcmp(nic->primary_dns, nulls,
773 sizeof(nic->primary_dns)))
774 rc = 1;
775 break;
776 case ibft_eth_secondary_dns:
777 if (memcmp(nic->secondary_dns, nulls,
778 sizeof(nic->secondary_dns)))
779 rc = 1;
780 break;
781 case ibft_eth_dhcp:
782 if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
783 rc = 1;
784 break;
785 case ibft_eth_vlan:
786 case ibft_eth_mac:
787 rc = 1;
788 break;
789 case ibft_eth_hostname:
790 if (nic->hostname_off)
791 rc = 1;
792 break;
793 default:
794 break;
795 }
796
797 return rc;
798} 732}
799 733
800static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry) 734static void __exit ibft_exit(void)
801{
802 int rc = 0;
803
804 switch (entry) {
805 case ibft_tgt_index:
806 case ibft_tgt_flags:
807 case ibft_tgt_ip_addr:
808 case ibft_tgt_port:
809 case ibft_tgt_lun:
810 case ibft_tgt_nic_assoc:
811 case ibft_tgt_chap_type:
812 rc = 1;
813 case ibft_tgt_name:
814 if (tgt->tgt_name_len)
815 rc = 1;
816 break;
817 case ibft_tgt_chap_name:
818 case ibft_tgt_chap_secret:
819 if (tgt->chap_name_len)
820 rc = 1;
821 break;
822 case ibft_tgt_rev_chap_name:
823 case ibft_tgt_rev_chap_secret:
824 if (tgt->rev_chap_name_len)
825 rc = 1;
826 break;
827 default:
828 break;
829 }
830
831 return rc;
832}
833
834static int __init ibft_check_initiator_for(struct ibft_initiator *init,
835 int entry)
836{
837 int rc = 0;
838
839 switch (entry) {
840 case ibft_init_index:
841 case ibft_init_flags:
842 rc = 1;
843 break;
844 case ibft_init_isns_server:
845 if (memcmp(init->isns_server, nulls,
846 sizeof(init->isns_server)))
847 rc = 1;
848 break;
849 case ibft_init_slp_server:
850 if (memcmp(init->slp_server, nulls,
851 sizeof(init->slp_server)))
852 rc = 1;
853 break;
854 case ibft_init_pri_radius_server:
855 if (memcmp(init->pri_radius_server, nulls,
856 sizeof(init->pri_radius_server)))
857 rc = 1;
858 break;
859 case ibft_init_sec_radius_server:
860 if (memcmp(init->sec_radius_server, nulls,
861 sizeof(init->sec_radius_server)))
862 rc = 1;
863 break;
864 case ibft_init_initiator_name:
865 if (init->initiator_name_len)
866 rc = 1;
867 break;
868 default:
869 break;
870 }
871
872 return rc;
873}
874
875/*
876 * Register the attributes for all of the kobjects.
877 */
878static int __init ibft_register_attributes(struct list_head *kobject_list,
879 struct list_head *attr_list)
880{ 735{
881 int rc = 0, i = 0; 736 ibft_cleanup();
882 struct ibft_kobject *data = NULL;
883 struct ibft_attribute *attr = NULL, *m;
884
885 list_for_each_entry(data, kobject_list, node) {
886 switch (data->hdr->id) {
887 case id_nic:
888 for (i = 0; i < ibft_eth_end_marker && !rc; i++)
889 if (ibft_check_nic_for(data->nic, i))
890 rc = ibft_create_attribute(data, i,
891 ibft_eth_properties[i],
892 ibft_attr_show_nic, attr_list);
893 break;
894 case id_target:
895 for (i = 0; i < ibft_tgt_end_marker && !rc; i++)
896 if (ibft_check_tgt_for(data->tgt, i))
897 rc = ibft_create_attribute(data, i,
898 ibft_tgt_properties[i],
899 ibft_attr_show_target,
900 attr_list);
901 break;
902 case id_initiator:
903 for (i = 0; i < ibft_init_end_marker && !rc; i++)
904 if (ibft_check_initiator_for(
905 data->initiator, i))
906 rc = ibft_create_attribute(data, i,
907 ibft_initiator_properties[i],
908 ibft_attr_show_initiator,
909 attr_list);
910 break;
911 default:
912 break;
913 }
914 if (rc)
915 break;
916 }
917 list_for_each_entry_safe(attr, m, attr_list, node) {
918 rc = sysfs_create_file(attr->kobj, &attr->attr);
919 if (rc) {
920 list_del(&attr->node);
921 kfree(attr);
922 break;
923 }
924 }
925
926 return rc;
927} 737}
928 738
929/* 739/*
@@ -933,26 +743,20 @@ static int __init ibft_init(void)
933{ 743{
934 int rc = 0; 744 int rc = 0;
935 745
936 ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
937 if (!ibft_kset)
938 return -ENOMEM;
939
940 if (ibft_addr) { 746 if (ibft_addr) {
941 printk(KERN_INFO "iBFT detected at 0x%llx.\n", 747 printk(KERN_INFO "iBFT detected at 0x%llx.\n",
942 (u64)isa_virt_to_bus(ibft_addr)); 748 (u64)isa_virt_to_bus(ibft_addr));
943 749
944 rc = ibft_check_device(); 750 rc = ibft_check_device();
945 if (rc) 751 if (rc)
946 goto out_firmware_unregister; 752 return rc;
947 753
948 /* Scan the IBFT for data and register the kobjects. */ 754 boot_kset = iscsi_boot_create_kset("ibft");
949 rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list); 755 if (!boot_kset)
950 if (rc) 756 return -ENOMEM;
951 goto out_free;
952 757
953 /* Register the attributes */ 758 /* Scan the IBFT for data and register the kobjects. */
954 rc = ibft_register_attributes(&ibft_kobject_list, 759 rc = ibft_register_kobjects(ibft_addr);
955 &ibft_attr_list);
956 if (rc) 760 if (rc)
957 goto out_free; 761 goto out_free;
958 } else 762 } else
@@ -961,17 +765,9 @@ static int __init ibft_init(void)
961 return 0; 765 return 0;
962 766
963out_free: 767out_free:
964 ibft_unregister(&ibft_attr_list, &ibft_kobject_list); 768 ibft_cleanup();
965out_firmware_unregister:
966 kset_unregister(ibft_kset);
967 return rc; 769 return rc;
968} 770}
969 771
970static void __exit ibft_exit(void)
971{
972 ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
973 kset_unregister(ibft_kset);
974}
975
976module_init(ibft_init); 772module_init(ibft_init);
977module_exit(ibft_exit); 773module_exit(ibft_exit);