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