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