xref: /linux/drivers/firmware/iscsi_ibft.c (revision c42813b71a06a2ff4a155aa87ac609feeab76cf3)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Copyright 2007-2010 Red Hat, Inc.
4  *  by Peter Jones <pjones@redhat.com>
5  *  Copyright 2008 IBM, Inc.
6  *  by Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
7  *  Copyright 2008
8  *  by Konrad Rzeszutek <ketuzsezr@darnok.org>
9  *
10  * This code exposes the iSCSI Boot Format Table to userland via sysfs.
11  *
12  * Changelog:
13  *
14  *  06 Jan 2010 - Peter Jones <pjones@redhat.com>
15  *    New changelog entries are in the git log from now on.  Not here.
16  *
17  *  14 Mar 2008 - Konrad Rzeszutek <ketuzsezr@darnok.org>
18  *    Updated comments and copyrights. (v0.4.9)
19  *
20  *  11 Feb 2008 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
21  *    Converted to using ibft_addr. (v0.4.8)
22  *
23  *   8 Feb 2008 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
24  *    Combined two functions in one: reserve_ibft_region. (v0.4.7)
25  *
26  *  30 Jan 2008 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
27  *   Added logic to handle IPv6 addresses. (v0.4.6)
28  *
29  *  25 Jan 2008 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
30  *   Added logic to handle badly not-to-spec iBFT. (v0.4.5)
31  *
32  *   4 Jan 2008 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
33  *   Added __init to function declarations. (v0.4.4)
34  *
35  *  21 Dec 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
36  *   Updated kobject registration, combined unregister functions in one
37  *   and code and style cleanup. (v0.4.3)
38  *
39  *   5 Dec 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
40  *   Added end-markers to enums and re-organized kobject registration. (v0.4.2)
41  *
42  *   4 Dec 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
43  *   Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1)
44  *
45  *  28 Nov 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
46  *   Added sysfs-ibft documentation, moved 'find_ibft' function to
47  *   in its own file and added text attributes for every struct field.  (v0.4)
48  *
49  *  21 Nov 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
50  *   Added text attributes emulating OpenFirmware /proc/device-tree naming.
51  *   Removed binary /sysfs interface (v0.3)
52  *
53  *  29 Aug 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
54  *   Added functionality in setup.c to reserve iBFT region. (v0.2)
55  *
56  *  27 Aug 2007 - Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
57  *   First version exposing iBFT data via a binary /sysfs. (v0.1)
58  */
59 
60 
61 #include <linux/blkdev.h>
62 #include <linux/capability.h>
63 #include <linux/ctype.h>
64 #include <linux/device.h>
65 #include <linux/err.h>
66 #include <linux/init.h>
67 #include <linux/iscsi_ibft.h>
68 #include <linux/limits.h>
69 #include <linux/module.h>
70 #include <linux/pci.h>
71 #include <linux/slab.h>
72 #include <linux/stat.h>
73 #include <linux/string.h>
74 #include <linux/types.h>
75 #include <linux/acpi.h>
76 #include <linux/iscsi_boot_sysfs.h>
77 
78 #define IBFT_ISCSI_VERSION "0.5.0"
79 #define IBFT_ISCSI_DATE "2010-Feb-25"
80 
81 MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and "
82 	      "Konrad Rzeszutek <ketuzsezr@darnok.org>");
83 MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
84 MODULE_LICENSE("GPL");
85 MODULE_VERSION(IBFT_ISCSI_VERSION);
86 
87 static struct acpi_table_ibft *ibft_addr;
88 
89 #ifndef CONFIG_ISCSI_IBFT_FIND
90 phys_addr_t ibft_phys_addr;
91 #endif
92 
93 struct ibft_hdr {
94 	u8 id;
95 	u8 version;
96 	u16 length;
97 	u8 index;
98 	u8 flags;
99 } __attribute__((__packed__));
100 
101 struct ibft_control {
102 	struct ibft_hdr hdr;
103 	u16 extensions;
104 	u16 initiator_off;
105 	u16 nic0_off;
106 	u16 tgt0_off;
107 	u16 nic1_off;
108 	u16 tgt1_off;
109 	u16 expansion[];
110 } __attribute__((__packed__));
111 
112 struct ibft_initiator {
113 	struct ibft_hdr hdr;
114 	char isns_server[16];
115 	char slp_server[16];
116 	char pri_radius_server[16];
117 	char sec_radius_server[16];
118 	u16 initiator_name_len;
119 	u16 initiator_name_off;
120 } __attribute__((__packed__));
121 
122 struct ibft_nic {
123 	struct ibft_hdr hdr;
124 	char ip_addr[16];
125 	u8 subnet_mask_prefix;
126 	u8 origin;
127 	char gateway[16];
128 	char primary_dns[16];
129 	char secondary_dns[16];
130 	char dhcp[16];
131 	u16 vlan;
132 	char mac[6];
133 	u16 pci_bdf;
134 	u16 hostname_len;
135 	u16 hostname_off;
136 } __attribute__((__packed__));
137 
138 struct ibft_tgt {
139 	struct ibft_hdr hdr;
140 	char ip_addr[16];
141 	u16 port;
142 	char lun[8];
143 	u8 chap_type;
144 	u8 nic_assoc;
145 	u16 tgt_name_len;
146 	u16 tgt_name_off;
147 	u16 chap_name_len;
148 	u16 chap_name_off;
149 	u16 chap_secret_len;
150 	u16 chap_secret_off;
151 	u16 rev_chap_name_len;
152 	u16 rev_chap_name_off;
153 	u16 rev_chap_secret_len;
154 	u16 rev_chap_secret_off;
155 } __attribute__((__packed__));
156 
157 /*
158  * The kobject different types and its names.
159  *
160 */
161 enum ibft_id {
162 	id_reserved = 0, /* We don't support. */
163 	id_control = 1, /* Should show up only once and is not exported. */
164 	id_initiator = 2,
165 	id_nic = 3,
166 	id_target = 4,
167 	id_extensions = 5, /* We don't support. */
168 	id_end_marker,
169 };
170 
171 /*
172  * The kobject and attribute structures.
173  */
174 
175 struct ibft_kobject {
176 	struct acpi_table_ibft *header;
177 	union {
178 		struct ibft_initiator *initiator;
179 		struct ibft_nic *nic;
180 		struct ibft_tgt *tgt;
181 		struct ibft_hdr *hdr;
182 	};
183 };
184 
185 static struct iscsi_boot_kset *boot_kset;
186 
187 /* fully null address */
188 static const char nulls[16];
189 
190 /* IPv4-mapped IPv6 ::ffff:0.0.0.0 */
191 static const char mapped_nulls[16] = { 0x00, 0x00, 0x00, 0x00,
192                                        0x00, 0x00, 0x00, 0x00,
193                                        0x00, 0x00, 0xff, 0xff,
194                                        0x00, 0x00, 0x00, 0x00 };
195 
196 static int address_not_null(u8 *ip)
197 {
198 	return (memcmp(ip, nulls, 16) && memcmp(ip, mapped_nulls, 16));
199 }
200 
201 /*
202  * Helper functions to parse data properly.
203  */
204 static ssize_t sprintf_ipaddr(char *buf, u8 *ip)
205 {
206 	char *str = buf;
207 
208 	if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 &&
209 	    ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 &&
210 	    ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) {
211 		/*
212 		 * IPV4
213 		 */
214 		str += sprintf(buf, "%pI4", ip + 12);
215 	} else {
216 		/*
217 		 * IPv6
218 		 */
219 		str += sprintf(str, "%pI6", ip);
220 	}
221 	str += sprintf(str, "\n");
222 	return str - buf;
223 }
224 
225 static ssize_t sprintf_string(char *str, int len, char *buf)
226 {
227 	return sprintf(str, "%.*s\n", len, buf);
228 }
229 
230 /*
231  * Helper function to verify the IBFT header.
232  */
233 static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
234 {
235 	if (hdr->id != id) {
236 		printk(KERN_ERR "iBFT error: We expected the %s " \
237 				"field header.id to have %d but " \
238 				"found %d instead!\n", t, id, hdr->id);
239 		return -ENODEV;
240 	}
241 	if (length && hdr->length != length) {
242 		printk(KERN_ERR "iBFT error: We expected the %s " \
243 				"field header.length to have %d but " \
244 				"found %d instead!\n", t, length, hdr->length);
245 		return -ENODEV;
246 	}
247 
248 	return 0;
249 }
250 
251 /*
252  *  Routines for parsing the iBFT data to be human readable.
253  */
254 static ssize_t ibft_attr_show_initiator(void *data, int type, char *buf)
255 {
256 	struct ibft_kobject *entry = data;
257 	struct ibft_initiator *initiator = entry->initiator;
258 	void *ibft_loc = entry->header;
259 	char *str = buf;
260 
261 	if (!initiator)
262 		return 0;
263 
264 	switch (type) {
265 	case ISCSI_BOOT_INI_INDEX:
266 		str += sprintf(str, "%d\n", initiator->hdr.index);
267 		break;
268 	case ISCSI_BOOT_INI_FLAGS:
269 		str += sprintf(str, "%d\n", initiator->hdr.flags);
270 		break;
271 	case ISCSI_BOOT_INI_ISNS_SERVER:
272 		str += sprintf_ipaddr(str, initiator->isns_server);
273 		break;
274 	case ISCSI_BOOT_INI_SLP_SERVER:
275 		str += sprintf_ipaddr(str, initiator->slp_server);
276 		break;
277 	case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
278 		str += sprintf_ipaddr(str, initiator->pri_radius_server);
279 		break;
280 	case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
281 		str += sprintf_ipaddr(str, initiator->sec_radius_server);
282 		break;
283 	case ISCSI_BOOT_INI_INITIATOR_NAME:
284 		str += sprintf_string(str, initiator->initiator_name_len,
285 				      (char *)ibft_loc +
286 				      initiator->initiator_name_off);
287 		break;
288 	default:
289 		break;
290 	}
291 
292 	return str - buf;
293 }
294 
295 static ssize_t ibft_attr_show_nic(void *data, int type, char *buf)
296 {
297 	struct ibft_kobject *entry = data;
298 	struct ibft_nic *nic = entry->nic;
299 	void *ibft_loc = entry->header;
300 	char *str = buf;
301 	__be32 val;
302 
303 	if (!nic)
304 		return 0;
305 
306 	switch (type) {
307 	case ISCSI_BOOT_ETH_INDEX:
308 		str += sprintf(str, "%d\n", nic->hdr.index);
309 		break;
310 	case ISCSI_BOOT_ETH_FLAGS:
311 		str += sprintf(str, "%d\n", nic->hdr.flags);
312 		break;
313 	case ISCSI_BOOT_ETH_IP_ADDR:
314 		str += sprintf_ipaddr(str, nic->ip_addr);
315 		break;
316 	case ISCSI_BOOT_ETH_SUBNET_MASK:
317 		val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
318 		str += sprintf(str, "%pI4", &val);
319 		break;
320 	case ISCSI_BOOT_ETH_PREFIX_LEN:
321 		str += sprintf(str, "%d\n", nic->subnet_mask_prefix);
322 		break;
323 	case ISCSI_BOOT_ETH_ORIGIN:
324 		str += sprintf(str, "%d\n", nic->origin);
325 		break;
326 	case ISCSI_BOOT_ETH_GATEWAY:
327 		str += sprintf_ipaddr(str, nic->gateway);
328 		break;
329 	case ISCSI_BOOT_ETH_PRIMARY_DNS:
330 		str += sprintf_ipaddr(str, nic->primary_dns);
331 		break;
332 	case ISCSI_BOOT_ETH_SECONDARY_DNS:
333 		str += sprintf_ipaddr(str, nic->secondary_dns);
334 		break;
335 	case ISCSI_BOOT_ETH_DHCP:
336 		str += sprintf_ipaddr(str, nic->dhcp);
337 		break;
338 	case ISCSI_BOOT_ETH_VLAN:
339 		str += sprintf(str, "%d\n", nic->vlan);
340 		break;
341 	case ISCSI_BOOT_ETH_MAC:
342 		str += sprintf(str, "%pM\n", nic->mac);
343 		break;
344 	case ISCSI_BOOT_ETH_HOSTNAME:
345 		str += sprintf_string(str, nic->hostname_len,
346 				      (char *)ibft_loc + nic->hostname_off);
347 		break;
348 	default:
349 		break;
350 	}
351 
352 	return str - buf;
353 };
354 
355 static ssize_t ibft_attr_show_target(void *data, int type, char *buf)
356 {
357 	struct ibft_kobject *entry = data;
358 	struct ibft_tgt *tgt = entry->tgt;
359 	void *ibft_loc = entry->header;
360 	char *str = buf;
361 	int i;
362 
363 	if (!tgt)
364 		return 0;
365 
366 	switch (type) {
367 	case ISCSI_BOOT_TGT_INDEX:
368 		str += sprintf(str, "%d\n", tgt->hdr.index);
369 		break;
370 	case ISCSI_BOOT_TGT_FLAGS:
371 		str += sprintf(str, "%d\n", tgt->hdr.flags);
372 		break;
373 	case ISCSI_BOOT_TGT_IP_ADDR:
374 		str += sprintf_ipaddr(str, tgt->ip_addr);
375 		break;
376 	case ISCSI_BOOT_TGT_PORT:
377 		str += sprintf(str, "%d\n", tgt->port);
378 		break;
379 	case ISCSI_BOOT_TGT_LUN:
380 		for (i = 0; i < 8; i++)
381 			str += sprintf(str, "%x", (u8)tgt->lun[i]);
382 		str += sprintf(str, "\n");
383 		break;
384 	case ISCSI_BOOT_TGT_NIC_ASSOC:
385 		str += sprintf(str, "%d\n", tgt->nic_assoc);
386 		break;
387 	case ISCSI_BOOT_TGT_CHAP_TYPE:
388 		str += sprintf(str, "%d\n", tgt->chap_type);
389 		break;
390 	case ISCSI_BOOT_TGT_NAME:
391 		str += sprintf_string(str, tgt->tgt_name_len,
392 				      (char *)ibft_loc + tgt->tgt_name_off);
393 		break;
394 	case ISCSI_BOOT_TGT_CHAP_NAME:
395 		str += sprintf_string(str, tgt->chap_name_len,
396 				      (char *)ibft_loc + tgt->chap_name_off);
397 		break;
398 	case ISCSI_BOOT_TGT_CHAP_SECRET:
399 		str += sprintf_string(str, tgt->chap_secret_len,
400 				      (char *)ibft_loc + tgt->chap_secret_off);
401 		break;
402 	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
403 		str += sprintf_string(str, tgt->rev_chap_name_len,
404 				      (char *)ibft_loc +
405 				      tgt->rev_chap_name_off);
406 		break;
407 	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
408 		str += sprintf_string(str, tgt->rev_chap_secret_len,
409 				      (char *)ibft_loc +
410 				      tgt->rev_chap_secret_off);
411 		break;
412 	default:
413 		break;
414 	}
415 
416 	return str - buf;
417 }
418 
419 static ssize_t ibft_attr_show_acpitbl(void *data, int type, char *buf)
420 {
421 	struct ibft_kobject *entry = data;
422 	char *str = buf;
423 
424 	switch (type) {
425 	case ISCSI_BOOT_ACPITBL_SIGNATURE:
426 		str += sprintf_string(str, ACPI_NAMESEG_SIZE,
427 				      entry->header->header.signature);
428 		break;
429 	case ISCSI_BOOT_ACPITBL_OEM_ID:
430 		str += sprintf_string(str, ACPI_OEM_ID_SIZE,
431 				      entry->header->header.oem_id);
432 		break;
433 	case ISCSI_BOOT_ACPITBL_OEM_TABLE_ID:
434 		str += sprintf_string(str, ACPI_OEM_TABLE_ID_SIZE,
435 				      entry->header->header.oem_table_id);
436 		break;
437 	default:
438 		break;
439 	}
440 
441 	return str - buf;
442 }
443 
444 static int __init ibft_check_device(void)
445 {
446 	int len;
447 	u8 *pos;
448 	u8 csum = 0;
449 
450 	len = ibft_addr->header.length;
451 
452 	/* Sanity checking of iBFT. */
453 	if (ibft_addr->header.revision != 1) {
454 		printk(KERN_ERR "iBFT module supports only revision 1, " \
455 				"while this is %d.\n",
456 				ibft_addr->header.revision);
457 		return -ENOENT;
458 	}
459 	for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++)
460 		csum += *pos;
461 
462 	if (csum) {
463 		printk(KERN_ERR "iBFT has incorrect checksum (0x%x)!\n", csum);
464 		return -ENOENT;
465 	}
466 
467 	return 0;
468 }
469 
470 /*
471  * Helper routiners to check to determine if the entry is valid
472  * in the proper iBFT structure.
473  */
474 static umode_t ibft_check_nic_for(void *data, int type)
475 {
476 	struct ibft_kobject *entry = data;
477 	struct ibft_nic *nic = entry->nic;
478 	umode_t rc = 0;
479 
480 	switch (type) {
481 	case ISCSI_BOOT_ETH_INDEX:
482 	case ISCSI_BOOT_ETH_FLAGS:
483 		rc = S_IRUGO;
484 		break;
485 	case ISCSI_BOOT_ETH_IP_ADDR:
486 		if (address_not_null(nic->ip_addr))
487 			rc = S_IRUGO;
488 		break;
489 	case ISCSI_BOOT_ETH_PREFIX_LEN:
490 	case ISCSI_BOOT_ETH_SUBNET_MASK:
491 		if (nic->subnet_mask_prefix)
492 			rc = S_IRUGO;
493 		break;
494 	case ISCSI_BOOT_ETH_ORIGIN:
495 		rc = S_IRUGO;
496 		break;
497 	case ISCSI_BOOT_ETH_GATEWAY:
498 		if (address_not_null(nic->gateway))
499 			rc = S_IRUGO;
500 		break;
501 	case ISCSI_BOOT_ETH_PRIMARY_DNS:
502 		if (address_not_null(nic->primary_dns))
503 			rc = S_IRUGO;
504 		break;
505 	case ISCSI_BOOT_ETH_SECONDARY_DNS:
506 		if (address_not_null(nic->secondary_dns))
507 			rc = S_IRUGO;
508 		break;
509 	case ISCSI_BOOT_ETH_DHCP:
510 		if (address_not_null(nic->dhcp))
511 			rc = S_IRUGO;
512 		break;
513 	case ISCSI_BOOT_ETH_VLAN:
514 	case ISCSI_BOOT_ETH_MAC:
515 		rc = S_IRUGO;
516 		break;
517 	case ISCSI_BOOT_ETH_HOSTNAME:
518 		if (nic->hostname_off)
519 			rc = S_IRUGO;
520 		break;
521 	default:
522 		break;
523 	}
524 
525 	return rc;
526 }
527 
528 static umode_t __init ibft_check_tgt_for(void *data, int type)
529 {
530 	struct ibft_kobject *entry = data;
531 	struct ibft_tgt *tgt = entry->tgt;
532 	umode_t rc = 0;
533 
534 	switch (type) {
535 	case ISCSI_BOOT_TGT_INDEX:
536 	case ISCSI_BOOT_TGT_FLAGS:
537 	case ISCSI_BOOT_TGT_IP_ADDR:
538 	case ISCSI_BOOT_TGT_PORT:
539 	case ISCSI_BOOT_TGT_LUN:
540 	case ISCSI_BOOT_TGT_NIC_ASSOC:
541 	case ISCSI_BOOT_TGT_CHAP_TYPE:
542 		rc = S_IRUGO;
543 		break;
544 	case ISCSI_BOOT_TGT_NAME:
545 		if (tgt->tgt_name_len)
546 			rc = S_IRUGO;
547 		break;
548 	case ISCSI_BOOT_TGT_CHAP_NAME:
549 	case ISCSI_BOOT_TGT_CHAP_SECRET:
550 		if (tgt->chap_name_len)
551 			rc = S_IRUGO;
552 		break;
553 	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
554 	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
555 		if (tgt->rev_chap_name_len)
556 			rc = S_IRUGO;
557 		break;
558 	default:
559 		break;
560 	}
561 
562 	return rc;
563 }
564 
565 static umode_t __init ibft_check_initiator_for(void *data, int type)
566 {
567 	struct ibft_kobject *entry = data;
568 	struct ibft_initiator *init = entry->initiator;
569 	umode_t rc = 0;
570 
571 	switch (type) {
572 	case ISCSI_BOOT_INI_INDEX:
573 	case ISCSI_BOOT_INI_FLAGS:
574 		rc = S_IRUGO;
575 		break;
576 	case ISCSI_BOOT_INI_ISNS_SERVER:
577 		if (address_not_null(init->isns_server))
578 			rc = S_IRUGO;
579 		break;
580 	case ISCSI_BOOT_INI_SLP_SERVER:
581 		if (address_not_null(init->slp_server))
582 			rc = S_IRUGO;
583 		break;
584 	case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
585 		if (address_not_null(init->pri_radius_server))
586 			rc = S_IRUGO;
587 		break;
588 	case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
589 		if (address_not_null(init->sec_radius_server))
590 			rc = S_IRUGO;
591 		break;
592 	case ISCSI_BOOT_INI_INITIATOR_NAME:
593 		if (init->initiator_name_len)
594 			rc = S_IRUGO;
595 		break;
596 	default:
597 		break;
598 	}
599 
600 	return rc;
601 }
602 
603 static umode_t __init ibft_check_acpitbl_for(void *data, int type)
604 {
605 
606 	umode_t rc = 0;
607 
608 	switch (type) {
609 	case ISCSI_BOOT_ACPITBL_SIGNATURE:
610 	case ISCSI_BOOT_ACPITBL_OEM_ID:
611 	case ISCSI_BOOT_ACPITBL_OEM_TABLE_ID:
612 		rc = S_IRUGO;
613 		break;
614 	default:
615 		break;
616 	}
617 
618 	return rc;
619 }
620 
621 static void ibft_kobj_release(void *data)
622 {
623 	kfree(data);
624 }
625 
626 /*
627  * Helper function for ibft_register_kobjects.
628  */
629 static int __init ibft_create_kobject(struct acpi_table_ibft *header,
630 				      struct ibft_hdr *hdr)
631 {
632 	struct iscsi_boot_kobj *boot_kobj = NULL;
633 	struct ibft_kobject *ibft_kobj = NULL;
634 	struct ibft_nic *nic = (struct ibft_nic *)hdr;
635 	struct pci_dev *pci_dev;
636 	int rc = 0;
637 
638 	ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
639 	if (!ibft_kobj)
640 		return -ENOMEM;
641 
642 	ibft_kobj->header = header;
643 	ibft_kobj->hdr = hdr;
644 
645 	switch (hdr->id) {
646 	case id_initiator:
647 		rc = ibft_verify_hdr("initiator", hdr, id_initiator,
648 				     sizeof(*ibft_kobj->initiator));
649 		if (rc)
650 			break;
651 
652 		boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
653 						ibft_kobj,
654 						ibft_attr_show_initiator,
655 						ibft_check_initiator_for,
656 						ibft_kobj_release);
657 		if (!boot_kobj) {
658 			rc = -ENOMEM;
659 			goto free_ibft_obj;
660 		}
661 		break;
662 	case id_nic:
663 		rc = ibft_verify_hdr("ethernet", hdr, id_nic,
664 				     sizeof(*ibft_kobj->nic));
665 		if (rc)
666 			break;
667 
668 		boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
669 						       ibft_kobj,
670 						       ibft_attr_show_nic,
671 						       ibft_check_nic_for,
672 						       ibft_kobj_release);
673 		if (!boot_kobj) {
674 			rc = -ENOMEM;
675 			goto free_ibft_obj;
676 		}
677 		break;
678 	case id_target:
679 		rc = ibft_verify_hdr("target", hdr, id_target,
680 				     sizeof(*ibft_kobj->tgt));
681 		if (rc)
682 			break;
683 
684 		boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
685 						     ibft_kobj,
686 						     ibft_attr_show_target,
687 						     ibft_check_tgt_for,
688 						     ibft_kobj_release);
689 		if (!boot_kobj) {
690 			rc = -ENOMEM;
691 			goto free_ibft_obj;
692 		}
693 		break;
694 	case id_reserved:
695 	case id_control:
696 	case id_extensions:
697 		/* Fields which we don't support. Ignore them */
698 		rc = 1;
699 		break;
700 	default:
701 		printk(KERN_ERR "iBFT has unknown structure type (%d). " \
702 				"Report this bug to %.6s!\n", hdr->id,
703 				header->header.oem_id);
704 		rc = 1;
705 		break;
706 	}
707 
708 	if (rc) {
709 		/* Skip adding this kobject, but exit with non-fatal error. */
710 		rc = 0;
711 		goto free_ibft_obj;
712 	}
713 
714 	if (hdr->id == id_nic) {
715 		/*
716 		* We don't search for the device in other domains than
717 		* zero. This is because on x86 platforms the BIOS
718 		* executes only devices which are in domain 0. Furthermore, the
719 		* iBFT spec doesn't have a domain id field :-(
720 		*/
721 		pci_dev = pci_get_domain_bus_and_slot(0,
722 						(nic->pci_bdf & 0xff00) >> 8,
723 						(nic->pci_bdf & 0xff));
724 		if (pci_dev) {
725 			rc = sysfs_create_link(&boot_kobj->kobj,
726 					       &pci_dev->dev.kobj, "device");
727 			pci_dev_put(pci_dev);
728 		}
729 	}
730 	return 0;
731 
732 free_ibft_obj:
733 	kfree(ibft_kobj);
734 	return rc;
735 }
736 
737 /*
738  * Scan the IBFT table structure for the NIC and Target fields. When
739  * found add them on the passed-in list. We do not support the other
740  * fields at this point, so they are skipped.
741  */
742 static int __init ibft_register_kobjects(struct acpi_table_ibft *header)
743 {
744 	struct ibft_control *control = NULL;
745 	struct iscsi_boot_kobj *boot_kobj;
746 	struct ibft_kobject *ibft_kobj;
747 	void *ptr, *end;
748 	int rc = 0;
749 	u16 offset;
750 	u16 eot_offset;
751 
752 	control = (void *)header + sizeof(*header);
753 	end = (void *)control + control->hdr.length;
754 	eot_offset = (void *)header + header->header.length - (void *)control;
755 	rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, 0);
756 
757 	/* iBFT table safety checking */
758 	rc |= ((control->hdr.index) ? -ENODEV : 0);
759 	rc |= ((control->hdr.length < sizeof(*control)) ? -ENODEV : 0);
760 	if (rc) {
761 		printk(KERN_ERR "iBFT error: Control header is invalid!\n");
762 		return rc;
763 	}
764 	for (ptr = &control->initiator_off; ptr + sizeof(u16) <= end; ptr += sizeof(u16)) {
765 		offset = *(u16 *)ptr;
766 		if (offset && offset < header->header.length &&
767 						offset < eot_offset) {
768 			rc = ibft_create_kobject(header,
769 						 (void *)header + offset);
770 			if (rc)
771 				break;
772 		}
773 	}
774 	if (rc)
775 		return rc;
776 
777 	ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
778 	if (!ibft_kobj)
779 		return -ENOMEM;
780 
781 	ibft_kobj->header = header;
782 	ibft_kobj->hdr = NULL; /*for ibft_unregister*/
783 
784 	boot_kobj = iscsi_boot_create_acpitbl(boot_kset, 0,
785 					ibft_kobj,
786 					ibft_attr_show_acpitbl,
787 					ibft_check_acpitbl_for,
788 					ibft_kobj_release);
789 	if (!boot_kobj)  {
790 		kfree(ibft_kobj);
791 		rc = -ENOMEM;
792 	}
793 
794 	return rc;
795 }
796 
797 static void ibft_unregister(void)
798 {
799 	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
800 	struct ibft_kobject *ibft_kobj;
801 
802 	list_for_each_entry_safe(boot_kobj, tmp_kobj,
803 				 &boot_kset->kobj_list, list) {
804 		ibft_kobj = boot_kobj->data;
805 		if (ibft_kobj->hdr && ibft_kobj->hdr->id == id_nic)
806 			sysfs_remove_link(&boot_kobj->kobj, "device");
807 	};
808 }
809 
810 static void ibft_cleanup(void)
811 {
812 	if (boot_kset) {
813 		ibft_unregister();
814 		iscsi_boot_destroy_kset(boot_kset);
815 	}
816 }
817 
818 static void __exit ibft_exit(void)
819 {
820 	ibft_cleanup();
821 }
822 
823 #ifdef CONFIG_ACPI
824 static const struct {
825 	char *sign;
826 } ibft_signs[] = {
827 	/*
828 	 * One spec says "IBFT", the other says "iBFT". We have to check
829 	 * for both.
830 	 */
831 	{ ACPI_SIG_IBFT },
832 	{ "iBFT" },
833 	{ "BIFT" },	/* Broadcom iSCSI Offload */
834 };
835 
836 static void __init acpi_find_ibft_region(void)
837 {
838 	int i;
839 	struct acpi_table_header *table = NULL;
840 
841 	if (acpi_disabled)
842 		return;
843 
844 	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) {
845 		acpi_get_table(ibft_signs[i].sign, 0, &table);
846 		ibft_addr = (struct acpi_table_ibft *)table;
847 	}
848 }
849 #else
850 static void __init acpi_find_ibft_region(void)
851 {
852 }
853 #endif
854 
855 /*
856  * ibft_init() - creates sysfs tree entries for the iBFT data.
857  */
858 static int __init ibft_init(void)
859 {
860 	int rc = 0;
861 
862 	/*
863 	   As on UEFI systems the setup_arch()/reserve_ibft_region()
864 	   is called before ACPI tables are parsed and it only does
865 	   legacy finding.
866 	*/
867 	if (ibft_phys_addr)
868 		ibft_addr = isa_bus_to_virt(ibft_phys_addr);
869 	else
870 		acpi_find_ibft_region();
871 
872 	if (ibft_addr) {
873 		pr_info("iBFT detected.\n");
874 
875 		rc = ibft_check_device();
876 		if (rc)
877 			return rc;
878 
879 		boot_kset = iscsi_boot_create_kset("ibft");
880 		if (!boot_kset)
881 			return -ENOMEM;
882 
883 		/* Scan the IBFT for data and register the kobjects. */
884 		rc = ibft_register_kobjects(ibft_addr);
885 		if (rc)
886 			goto out_free;
887 	} else
888 		printk(KERN_INFO "No iBFT detected.\n");
889 
890 	return 0;
891 
892 out_free:
893 	ibft_cleanup();
894 	return rc;
895 }
896 
897 module_init(ibft_init);
898 module_exit(ibft_exit);
899