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