iPXE
Data Structures | Functions | Variables
ibft.c File Reference

iSCSI boot firmware table More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/pci.h>
#include <ipxe/acpi.h>
#include <ipxe/in.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/vlan.h>
#include <ipxe/tcpip.h>
#include <ipxe/dhcp.h>
#include <ipxe/iscsi.h>
#include <ipxe/ibft.h>

Go to the source code of this file.

Data Structures

struct  ibft_strings
 iSCSI string buffer More...

Functions

 FILE_LICENCE (BSD2)
static size_t ibft_align (size_t len)
 Align structure within iBFT.
static void ibft_set_ipaddr (struct ibft_ipaddr *ipaddr, struct in_addr in)
 Fill in an IP address field within iBFT.
static void ibft_set_ipaddr_setting (struct settings *settings, struct ibft_ipaddr *ipaddr, const struct setting *setting, unsigned int count)
 Fill in an IP address within iBFT from configuration setting.
static const char * ibft_ipaddr (struct ibft_ipaddr *ipaddr)
 Read IP address from iBFT (for debugging)
static char * ibft_alloc_string (struct ibft_strings *strings, struct ibft_string *string, size_t len)
 Allocate a string within iBFT.
static int ibft_set_string (struct ibft_strings *strings, struct ibft_string *string, const char *data)
 Fill in a string field within iBFT.
static int ibft_set_string_setting (struct settings *settings, struct ibft_strings *strings, struct ibft_string *string, const struct setting *setting)
 Fill in a string field within iBFT from configuration setting.
static const char * ibft_string (struct ibft_strings *strings, struct ibft_string *string)
 Read string from iBFT (for debugging)
static int ibft_netdev_is_required (struct net_device *netdev)
 Check if network device is required for the iBFT.
static int ibft_fill_nic (struct ibft_nic *nic, struct ibft_strings *strings, struct net_device *netdev)
 Fill in NIC portion of iBFT.
static int ibft_fill_initiator (struct ibft_initiator *initiator, struct ibft_strings *strings, const char *initiator_iqn)
 Fill in Initiator portion of iBFT.
static int ibft_fill_target_nic_association (struct ibft_target *target, struct iscsi_session *iscsi)
 Fill in Target NIC association.
static int ibft_fill_target_chap (struct ibft_target *target, struct ibft_strings *strings, struct iscsi_session *iscsi)
 Fill in Target CHAP portion of iBFT.
static int ibft_fill_target_reverse_chap (struct ibft_target *target, struct ibft_strings *strings, struct iscsi_session *iscsi)
 Fill in Target Reverse CHAP portion of iBFT.
static int ibft_fill_target (struct ibft_target *target, struct ibft_strings *strings, struct iscsi_session *iscsi)
 Fill in Target portion of iBFT.
static int ibft_complete (struct acpi_descriptor *desc)
 Check if iBFT descriptor is complete.
static int ibft_install (int(*install)(struct acpi_header *acpi))
 Install iBFT.

Variables

struct acpi_model ibft_model __acpi_model
 iBFT model

Detailed Description

iSCSI boot firmware table

The information in this file is derived from the document "iSCSI Boot Firmware Table (iBFT)" as published by IBM at

ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf

Definition in file ibft.c.


Function Documentation

FILE_LICENCE ( BSD2  )
static size_t ibft_align ( size_t  len) [inline, static]

Align structure within iBFT.

Parameters:
lenUnaligned length (or offset)
Return values:
lenAligned length (or offset)

Definition at line 79 of file ibft.c.

References IBFT_ALIGN.

Referenced by ibft_install().

                                               {

        return ( ( len + IBFT_ALIGN - 1 ) & ~( IBFT_ALIGN - 1 ) );
}
static void ibft_set_ipaddr ( struct ibft_ipaddr ipaddr,
struct in_addr  in 
) [static]

Fill in an IP address field within iBFT.

Parameters:
ipaddrIP address field
inIPv4 address

Definition at line 90 of file ibft.c.

References ibft_ipaddr::in, in, memset(), ibft_ipaddr::ones, and in_addr::s_addr.

Referenced by ibft_fill_target(), and ibft_set_ipaddr_setting().

                                                                              {
        memset ( ipaddr, 0, sizeof ( *ipaddr ) );
        if ( in.s_addr ) {
                ipaddr->in = in;
                ipaddr->ones = 0xffff;
        }
}
static void ibft_set_ipaddr_setting ( struct settings settings,
struct ibft_ipaddr ipaddr,
const struct setting setting,
unsigned int  count 
) [static]

Fill in an IP address within iBFT from configuration setting.

Parameters:
settingsParent settings block, or NULL
ipaddrIP address field
settingConfiguration setting
countMaximum number of IP addresses

Definition at line 106 of file ibft.c.

References count, fetch_ipv4_array_setting(), and ibft_set_ipaddr().

Referenced by ibft_fill_nic().

                                                           {
        struct in_addr in[count];
        unsigned int i;

        fetch_ipv4_array_setting ( settings, setting, in, count );
        for ( i = 0 ; i < count ; i++ ) {
                ibft_set_ipaddr ( &ipaddr[i], in[i] );
        }
}
static const char* ibft_ipaddr ( struct ibft_ipaddr ipaddr) [static]

Read IP address from iBFT (for debugging)

Parameters:
stringsiBFT string block descriptor
stringString field
Return values:
ipaddrIP address string

Definition at line 126 of file ibft.c.

References ibft_ipaddr::in, and inet_ntoa().

                                                               {
        return inet_ntoa ( ipaddr->in );
}
static char* ibft_alloc_string ( struct ibft_strings strings,
struct ibft_string string,
size_t  len 
) [static]

Allocate a string within iBFT.

Parameters:
stringsiBFT string block descriptor
stringString field to fill in
lenLength of string to allocate (excluding NUL)
Return values:
destString destination, or NULL

Definition at line 138 of file ibft.c.

References cpu_to_le16, ibft_strings::data, dest, ibft_strings::len, memset(), NULL, realloc(), and ibft_strings::start.

Referenced by ibft_set_string(), and ibft_set_string_setting().

                                                                           {
        size_t new_len;
        char *new_data;
        char *dest;

        /* Extend string data buffer */
        new_len = ( strings->len + len + 1 /* NUL */ );
        new_data = realloc ( strings->data, new_len );
        if ( ! new_data )
                return NULL;
        strings->data = new_data;

        /* Fill in string field */
        string->offset = cpu_to_le16 ( strings->start + strings->len );
        string->len = cpu_to_le16 ( len );

        /* Zero string */
        dest = ( strings->data + strings->len );
        memset ( dest, 0, ( len + 1 /* NUL */ ) );

        /* Update allocated length */
        strings->len = new_len;

        return dest;
}
static int ibft_set_string ( struct ibft_strings strings,
struct ibft_string string,
const char *  data 
) [static]

Fill in a string field within iBFT.

Parameters:
stringsiBFT string block descriptor
stringString field
dataString to fill in, or NULL
Return values:
rcReturn status code

Definition at line 173 of file ibft.c.

References dest, ENOBUFS, ibft_alloc_string(), strcpy(), and strlen().

Referenced by ibft_fill_initiator(), ibft_fill_target(), ibft_fill_target_chap(), and ibft_fill_target_reverse_chap().

                                                                            {
        char *dest;

        if ( ! data )
                return 0;

        dest = ibft_alloc_string ( strings, string, strlen ( data ) );
        if ( ! dest )
                return -ENOBUFS;
        strcpy ( dest, data );

        return 0;
}
static int ibft_set_string_setting ( struct settings settings,
struct ibft_strings strings,
struct ibft_string string,
const struct setting setting 
) [static]

Fill in a string field within iBFT from configuration setting.

Parameters:
settingsParent settings block, or NULL
stringsiBFT string block descriptor
stringString field
settingConfiguration setting
Return values:
rcReturn status code

Definition at line 197 of file ibft.c.

References dest, ENOBUFS, fetch_setting(), fetch_string_setting(), ibft_alloc_string(), len, NULL, and origin.

Referenced by ibft_fill_nic().

                                                                     {
        struct settings *origin;
        struct setting fetched;
        int len;
        char *dest;

        len = fetch_setting ( settings, setting, &origin, &fetched, NULL, 0 );
        if ( len < 0 ) {
                string->offset = 0;
                string->len = 0;
                return 0;
        }

        dest = ibft_alloc_string ( strings, string, len );
        if ( ! dest )
                return -ENOBUFS;
        fetch_string_setting ( origin, &fetched, dest, ( len + 1 ));

        return 0;
}
static const char* ibft_string ( struct ibft_strings strings,
struct ibft_string string 
) [static]

Read string from iBFT (for debugging)

Parameters:
stringsiBFT string block descriptor
stringString field
Return values:
dataString content (or "<empty>")

Definition at line 228 of file ibft.c.

References ibft_strings::data, le16_to_cpu, NULL, ibft_string::offset, offset, and ibft_strings::start.

                                                               {
        size_t offset = le16_to_cpu ( string->offset );

        return ( offset ? ( strings->data + offset - strings->start ) : NULL );
}
static int ibft_netdev_is_required ( struct net_device netdev) [static]

Check if network device is required for the iBFT.

Parameters:
netdevNetwork device
Return values:
is_requiredNetwork device is required

Definition at line 241 of file ibft.c.

References list_for_each_entry, netdev, iscsi_session::target_sockaddr, and tcpip_netdev().

Referenced by ibft_fill_target_nic_association(), and ibft_install().

                                                                 {
        struct iscsi_session *iscsi;
        struct sockaddr_tcpip *st_target;

        list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
                st_target = ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
                if ( tcpip_netdev ( st_target ) == netdev )
                        return 1;
        }

        return 0;
}
static int ibft_fill_nic ( struct ibft_nic nic,
struct ibft_strings strings,
struct net_device netdev 
) [static]

Fill in NIC portion of iBFT.

Parameters:
nicNIC portion of iBFT
stringsiBFT string block descriptor
netdevNetwork device
Return values:
rcReturn status code

Definition at line 262 of file ibft.c.

References cpu_to_le16, DBG, device::desc, net_device::dev, ibft_nic::dhcp, ibft_nic::dns, ll_protocol::eth_addr, eth_ntoa(), fetch_ipv4_setting(), fetch_setting(), ibft_header::flags, ibft_nic::gateway, ibft_nic::header, ibft_nic::hostname, IBFT_FL_NIC_BLOCK_VALID, IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED, IBFT_NIC_ORIGIN_DHCP, IBFT_NIC_ORIGIN_MANUAL, ibft_set_ipaddr_setting(), ibft_set_string_setting(), IBFT_STRUCTURE_ID_NIC, ibft_header::index, ibft_nic::ip_address, le16_to_cpu, ibft_header::length, net_device::ll_addr, net_device::ll_protocol, device_description::location, ibft_nic::mac_address, net_device::name, netdev_settings(), NULL, origin, ibft_nic::origin, settings::parent, ibft_nic::pci_bus_dev_func, rc, in_addr::s_addr, strerror(), ibft_header::structure_id, ibft_nic::subnet_mask_prefix, ibft_header::version, ibft_nic::vlan, and vlan_tag().

Referenced by ibft_install().

                                                       {
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        struct in_addr netmask_addr = { 0 };
        unsigned int netmask_count = 0;
        struct settings *parent = netdev_settings ( netdev );
        struct settings *origin;
        int rc;

        /* Fill in common header */
        nic->header.structure_id = IBFT_STRUCTURE_ID_NIC;
        nic->header.version = 1;
        nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
        nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
                              IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
        DBG ( "iBFT NIC %d is %s\n", nic->header.index, netdev->name );

        /* Determine origin of IP address */
        fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
        nic->origin = ( ( origin == parent ) ?
                        IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
        DBG ( "iBFT NIC %d origin = %d\n", nic->header.index, nic->origin );

        /* Extract values from configuration settings */
        ibft_set_ipaddr_setting ( parent, &nic->ip_address, &ip_setting, 1 );
        DBG ( "iBFT NIC %d IP = %s\n",
              nic->header.index, ibft_ipaddr ( &nic->ip_address ) );
        ibft_set_ipaddr_setting ( parent, &nic->gateway, &gateway_setting, 1 );
        DBG ( "iBFT NIC %d gateway = %s\n",
              nic->header.index, ibft_ipaddr ( &nic->gateway ) );
        ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
                                  ( sizeof ( nic->dns ) /
                                    sizeof ( nic->dns[0] ) ) );
        ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 );
        DBG ( "iBFT NIC %d DNS = %s",
              nic->header.index, ibft_ipaddr ( &nic->dns[0] ) );
        DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
        if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
                                              &hostname_setting ) ) != 0 )
                return rc;
        DBG ( "iBFT NIC %d hostname = %s\n",
              nic->header.index, ibft_string ( strings, &nic->hostname ) );

        /* Derive subnet mask prefix from subnet mask */
        fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr );
        while ( netmask_addr.s_addr ) {
                if ( netmask_addr.s_addr & 0x1 )
                        netmask_count++;
                netmask_addr.s_addr >>= 1;
        }
        nic->subnet_mask_prefix = netmask_count;
        DBG ( "iBFT NIC %d subnet = /%d\n",
              nic->header.index, nic->subnet_mask_prefix );

        /* Extract values from net-device configuration */
        nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) );
        DBG ( "iBFT NIC %d VLAN = %02x\n",
              nic->header.index, le16_to_cpu ( nic->vlan ) );
        if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
                                            nic->mac_address ) ) != 0 ) {
                DBG ( "Could not determine %s MAC: %s\n",
                      netdev->name, strerror ( rc ) );
                return rc;
        }
        DBG ( "iBFT NIC %d MAC = %s\n",
              nic->header.index, eth_ntoa ( nic->mac_address ) );
        nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
        DBG ( "iBFT NIC %d PCI = %04x\n",
              nic->header.index, le16_to_cpu ( nic->pci_bus_dev_func ) );

        return 0;
}
static int ibft_fill_initiator ( struct ibft_initiator initiator,
struct ibft_strings strings,
const char *  initiator_iqn 
) [static]

Fill in Initiator portion of iBFT.

Parameters:
initiatorInitiator portion of iBFT
stringsiBFT string block descriptor
initiator_iqnInitiator IQN
Return values:
rcReturn status code

Definition at line 344 of file ibft.c.

References cpu_to_le16, DBG, ibft_header::flags, ibft_initiator::header, IBFT_FL_INITIATOR_BLOCK_VALID, IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED, ibft_set_string(), IBFT_STRUCTURE_ID_INITIATOR, ibft_initiator::initiator_name, ibft_header::length, rc, ibft_header::structure_id, and ibft_header::version.

Referenced by ibft_install().

                                                             {
        int rc;

        /* Fill in common header */
        initiator->header.structure_id = IBFT_STRUCTURE_ID_INITIATOR;
        initiator->header.version = 1;
        initiator->header.length = cpu_to_le16 ( sizeof ( *initiator ) );
        initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
                                    IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );

        /* Fill in initiator name */
        if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
                                      initiator_iqn ) ) != 0 )
                return rc;
        DBG ( "iBFT initiator name = %s\n",
              ibft_string ( strings, &initiator->initiator_name ) );

        return 0;
}
static int ibft_fill_target_nic_association ( struct ibft_target target,
struct iscsi_session iscsi 
) [static]

Fill in Target NIC association.

Parameters:
targetTarget portion of iBFT
iscsiiSCSI session
Return values:
rcReturn status code

Definition at line 373 of file ibft.c.

References DBG, EHOSTUNREACH, EINVAL, for_each_netdev, ibft_target::header, ibft_netdev_is_required(), ibft_header::index, net_device::name, netdev, ibft_target::nic_association, iscsi_session::target_sockaddr, and tcpip_netdev().

Referenced by ibft_fill_target().

                                                                            {
        struct sockaddr_tcpip *st_target =
                ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
        struct net_device *associated;
        struct net_device *netdev;

        /* Find network device used to reach target */
        associated = tcpip_netdev ( st_target );
        if ( ! associated ) {
                DBG ( "iBFT target %d has no net device\n",
                      target->header.index );
                return -EHOSTUNREACH;
        }

        /* Calculate association */
        for_each_netdev ( netdev ) {
                if ( netdev == associated ) {
                        DBG ( "iBFT target %d uses NIC %d (%s)\n",
                              target->header.index, target->nic_association,
                              netdev->name );
                        return 0;
                }
                if ( ! ibft_netdev_is_required ( netdev ) )
                        continue;
                target->nic_association++;
        }

        DBG ( "iBFT target %d has impossible NIC %s\n",
              target->header.index, netdev->name );
        return -EINVAL;
}
static int ibft_fill_target_chap ( struct ibft_target target,
struct ibft_strings strings,
struct iscsi_session iscsi 
) [static]

Fill in Target CHAP portion of iBFT.

Parameters:
targetTarget portion of iBFT
stringsiBFT string block descriptor
iscsiiSCSI session
Return values:
rcReturn status code

Definition at line 414 of file ibft.c.

References assert, ibft_target::chap_name, ibft_target::chap_secret, ibft_target::chap_type, DBG, ibft_target::header, IBFT_CHAP_ONE_WAY, ibft_set_string(), ibft_header::index, iscsi_session::initiator_password, iscsi_session::initiator_username, ISCSI_STATUS_AUTH_FORWARD_REQUIRED, rc, and iscsi_session::status.

Referenced by ibft_fill_target().

                                                                 {
        int rc;

        if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
                return 0;

        assert ( iscsi->initiator_username );
        assert ( iscsi->initiator_password );

        target->chap_type = IBFT_CHAP_ONE_WAY;
        if ( ( rc = ibft_set_string ( strings, &target->chap_name,
                                      iscsi->initiator_username ) ) != 0 )
                return rc;
        DBG ( "iBFT target %d username = %s\n", target->header.index,
              ibft_string ( strings, &target->chap_name ) );
        if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
                                      iscsi->initiator_password ) ) != 0 )
                return rc;
        DBG ( "iBFT target %d password = <redacted>\n", target->header.index );

        return 0;
}
static int ibft_fill_target_reverse_chap ( struct ibft_target target,
struct ibft_strings strings,
struct iscsi_session iscsi 
) [static]

Fill in Target Reverse CHAP portion of iBFT.

Parameters:
targetTarget portion of iBFT
stringsiBFT string block descriptor
iscsiiSCSI session
Return values:
rcReturn status code

Definition at line 447 of file ibft.c.

References assert, ibft_target::chap_name, ibft_target::chap_type, DBG, ibft_target::header, IBFT_CHAP_MUTUAL, ibft_set_string(), ibft_header::index, iscsi_session::initiator_password, iscsi_session::initiator_username, ISCSI_STATUS_AUTH_REVERSE_REQUIRED, rc, ibft_target::reverse_chap_name, ibft_target::reverse_chap_secret, iscsi_session::status, iscsi_session::target_password, and iscsi_session::target_username.

Referenced by ibft_fill_target().

                                                                         {
        int rc;

        if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
                return 0;

        assert ( iscsi->initiator_username );
        assert ( iscsi->initiator_password );
        assert ( iscsi->target_username );
        assert ( iscsi->target_password );

        target->chap_type = IBFT_CHAP_MUTUAL;
        if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
                                      iscsi->target_username ) ) != 0 )
                return rc;
        DBG ( "iBFT target %d reverse username = %s\n", target->header.index,
              ibft_string ( strings, &target->chap_name ) );
        if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
                                      iscsi->target_password ) ) != 0 )
                return rc;
        DBG ( "iBFT target %d reverse password = <redacted>\n",
              target->header.index );

        return 0;
}
static int ibft_fill_target ( struct ibft_target target,
struct ibft_strings strings,
struct iscsi_session iscsi 
) [static]

Fill in Target portion of iBFT.

Parameters:
targetTarget portion of iBFT
stringsiBFT string block descriptor
iscsiiSCSI session
Return values:
rcReturn status code

Definition at line 483 of file ibft.c.

References ibft_target::boot_lun, cpu_to_le16, DBG, ibft_header::flags, ibft_target::header, ibft_fill_target_chap(), ibft_fill_target_nic_association(), ibft_fill_target_reverse_chap(), IBFT_FL_TARGET_BLOCK_VALID, IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED, ibft_set_ipaddr(), ibft_set_string(), IBFT_STRUCTURE_ID_TARGET, ibft_header::index, ibft_target::ip_address, ibft_header::length, iscsi_session::lun, memcpy(), ntohs, rc, SCSI_LUN_DATA, SCSI_LUN_FORMAT, ibft_target::socket, sockaddr_tcpip::st_port, ibft_header::structure_id, iscsi_session::target_iqn, ibft_target::target_name, iscsi_session::target_sockaddr, and ibft_header::version.

Referenced by ibft_install().

                                                            {
        struct sockaddr_tcpip *st_target =
                ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
        struct sockaddr_in *sin_target =
                ( struct sockaddr_in * ) &iscsi->target_sockaddr;
        int rc;

        /* Fill in common header */
        target->header.structure_id = IBFT_STRUCTURE_ID_TARGET;
        target->header.version = 1;
        target->header.length = cpu_to_le16 ( sizeof ( *target ) );
        target->header.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
                                 IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED );

        /* Fill in Target values */
        ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
        DBG ( "iBFT target %d IP = %s\n",
              target->header.index, ibft_ipaddr ( &target->ip_address ) );
        target->socket = cpu_to_le16 ( ntohs ( st_target->st_port ) );
        DBG ( "iBFT target %d port = %d\n",
              target->header.index, target->socket );
        memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
        DBG ( "iBFT target %d boot LUN = " SCSI_LUN_FORMAT "\n",
              target->header.index, SCSI_LUN_DATA ( target->boot_lun ) );
        if ( ( rc = ibft_set_string ( strings, &target->target_name,
                                      iscsi->target_iqn ) ) != 0 )
                return rc;
        DBG ( "iBFT target %d name = %s\n", target->header.index,
              ibft_string ( strings, &target->target_name ) );
        if ( ( rc = ibft_fill_target_nic_association ( target, iscsi ) ) != 0 )
                return rc;
        if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
                return rc;
        if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
                                                    iscsi ) ) != 0 )
                return rc;

        return 0;
}
static int ibft_complete ( struct acpi_descriptor desc) [static]

Check if iBFT descriptor is complete.

Parameters:
descACPI descriptor
Return values:
rcReturn status code

Definition at line 531 of file ibft.c.

References container_of, EAGAIN, sockaddr::sa_family, and iscsi_session::target_sockaddr.

                                                          {
        struct iscsi_session *iscsi =
                container_of ( desc, struct iscsi_session, desc );

        /* Fail if we do not yet have the target address */
        if ( ! iscsi->target_sockaddr.sa_family )
                return -EAGAIN;

        return 0;
}
static int ibft_install ( int(*)(struct acpi_header *acpi install) [static]

Install iBFT.

Parameters:
installInstallation method
Return values:
rcReturn status code

Definition at line 548 of file ibft.c.

References acpi, assert, control, ibft_table::control, cpu_to_le16, cpu_to_le32, ibft_strings::data, data, DBG, ENOMEM, for_each_netdev, free, ibft_control::header, ibft_nic::header, ibft_target::header, ibft_align(), ibft_fill_initiator(), ibft_fill_nic(), ibft_fill_target(), ibft_netdev_is_required(), IBFT_SIG, IBFT_STRUCTURE_ID_CONTROL, ibft_header::index, ibft_control::initiator, iscsi_session::initiator_iqn, ibft_strings::len, len, acpi_header::length, ibft_header::length, list_first_entry, list_for_each_entry, memcpy(), netdev, nic, ibft_offset_pair::nic, NULL, offset, offsetof, ibft_control::pair, rc, realloc(), acpi_header::revision, acpi_header::signature, ibft_strings::start, strerror(), ibft_header::structure_id, ibft_offset_pair::target, ibft_header::version, and zalloc().

                                                                           {
        struct net_device *netdev;
        struct iscsi_session *iscsi;
        struct ibft_table *table;
        struct ibft_initiator *initiator;
        struct ibft_nic *nic;
        struct ibft_target *target;
        struct ibft_strings strings;
        struct acpi_header *acpi;
        void *data;
        unsigned int targets = 0;
        unsigned int pairs = 0;
        size_t offset = 0;
        size_t table_len;
        size_t control_len;
        size_t initiator_offset;
        size_t nic_offset;
        size_t target_offset;
        size_t strings_offset;
        size_t len;
        unsigned int i;
        int rc;

        /* Calculate table sizes and offsets */
        list_for_each_entry ( iscsi, &ibft_model.descs, desc.list )
                targets++;
        pairs = ( sizeof ( table->control.pair ) /
                  sizeof ( table->control.pair[0] ) );
        if ( pairs < targets )
                pairs = targets;
        offset = offsetof ( typeof ( *table ), control.pair );
        offset += ( pairs * sizeof ( table->control.pair[0] ) );
        table_len = offset;
        control_len = ( table_len - offsetof ( typeof ( *table ), control ) );
        offset = ibft_align ( offset );
        initiator_offset = offset;
        offset += ibft_align ( sizeof ( *initiator ) );
        nic_offset = offset;
        offset += ( pairs * ibft_align ( sizeof ( *nic ) ) );
        target_offset = offset;
        offset += ( pairs * ibft_align ( sizeof ( *target ) ) );
        strings_offset = offset;
        strings.data = NULL;
        strings.start = strings_offset;
        strings.len = 0;
        len = offset;

        /* Do nothing if no targets exist */
        if ( ! targets ) {
                rc = 0;
                goto no_targets;
        }

        /* Allocate table */
        data = zalloc ( len );
        if ( ! data ) {
                rc = -ENOMEM;
                goto err_alloc;
        }

        /* Fill in Control block */
        table = data;
        table->control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
        table->control.header.version = 1;
        table->control.header.length = cpu_to_le16 ( control_len );

        /* Fill in Initiator block */
        initiator = ( data + initiator_offset );
        table->control.initiator = cpu_to_le16 ( initiator_offset );
        iscsi = list_first_entry ( &ibft_model.descs, struct iscsi_session,
                                   desc.list );
        if ( ( rc = ibft_fill_initiator ( initiator, &strings,
                                          iscsi->initiator_iqn ) ) != 0 )
                goto err_initiator;

        /* Fill in NIC blocks */
        i = 0;
        for_each_netdev ( netdev ) {
                if ( ! ibft_netdev_is_required ( netdev ) )
                        continue;
                assert ( i < pairs );
                table->control.pair[i].nic = nic_offset;
                nic = ( data + nic_offset );
                nic->header.index = i;
                if ( ( rc = ibft_fill_nic ( nic, &strings, netdev ) ) != 0 )
                        goto err_nic;
                i++;
                nic_offset += ibft_align ( sizeof ( *nic ) );
        }

        /* Fill in Target blocks */
        i = 0;
        list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
                assert ( i < pairs );
                table->control.pair[i].target = target_offset;
                target = ( data + target_offset );
                target->header.index = i;
                if ( ( rc = ibft_fill_target ( target, &strings, iscsi ) ) != 0)
                        goto err_target;
                i++;
                target_offset += ibft_align ( sizeof ( *target ) );
        }

        /* Reallocate table to include space for strings */
        len += strings.len;
        acpi = realloc ( data, len );
        if ( ! acpi )
                goto err_realloc;
        data = NULL;

        /* Fill in ACPI header */
        acpi->signature = cpu_to_le32 ( IBFT_SIG );
        acpi->length = cpu_to_le32 ( len );
        acpi->revision = 1;

        /* Append strings */
        memcpy ( ( ( ( void * ) acpi ) + strings_offset ), strings.data,
                 strings.len );

        /* Install ACPI table */
        if ( ( rc = install ( acpi ) ) != 0 ) {
                DBG ( "iBFT could not install: %s\n", strerror ( rc ) );
                goto err_install;
        }

 err_install:
        free ( acpi );
 err_realloc:
 err_target:
 err_nic:
 err_initiator:
        free ( data );
 err_alloc:
 no_targets:
        free ( strings.data );
        return rc;
}

Variable Documentation

struct acpi_model ibft_model __acpi_model
Initial value:
 {
        .descs = LIST_HEAD_INIT ( ibft_model.descs ),
        .complete = ibft_complete,
        .install = ibft_install,
}

iBFT model

aBFT model

Definition at line 687 of file ibft.c.