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