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