iPXE
ib_srp.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  *   Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  *   Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in
00014  *   the documentation and/or other materials provided with the
00015  *   distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00022  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00024  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00026  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00028  * OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 FILE_LICENCE ( BSD2 );
00032 
00033 #include <stdlib.h>
00034 #include <errno.h>
00035 #include <ipxe/interface.h>
00036 #include <ipxe/uri.h>
00037 #include <ipxe/open.h>
00038 #include <ipxe/base16.h>
00039 #include <ipxe/acpi.h>
00040 #include <ipxe/srp.h>
00041 #include <ipxe/infiniband.h>
00042 #include <ipxe/ib_cmrc.h>
00043 #include <ipxe/ib_srp.h>
00044 
00045 /**
00046  * @file
00047  *
00048  * SCSI RDMA Protocol over Infiniband
00049  *
00050  */
00051 
00052 /* Disambiguate the various possible EINVALs */
00053 #define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN )
00054 #define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \
00055         ( EINFO_EINVAL, 0x01, "Invalid byte string length" )
00056 #define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
00057 #define EINFO_EINVAL_INTEGER __einfo_uniqify \
00058         ( EINFO_EINVAL, 0x03, "Invalid integer" )
00059 #define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT )
00060 #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
00061         ( EINFO_EINVAL, 0x04, "Root path too short" )
00062 
00063 struct acpi_model ib_sbft_model __acpi_model;
00064 
00065 /******************************************************************************
00066  *
00067  * IB SRP devices
00068  *
00069  ******************************************************************************
00070  */
00071 
00072 /**
00073  * An IB SRP sBFT created by iPXE
00074  */
00075 struct ipxe_ib_sbft {
00076         /** The table header */
00077         struct sbft_table table;
00078         /** The SCSI subtable */
00079         struct sbft_scsi_subtable scsi;
00080         /** The SRP subtable */
00081         struct sbft_srp_subtable srp;
00082         /** The Infiniband subtable */
00083         struct sbft_ib_subtable ib;
00084 };
00085 
00086 /** An Infiniband SRP device */
00087 struct ib_srp_device {
00088         /** Reference count */
00089         struct refcnt refcnt;
00090 
00091         /** SRP transport interface */
00092         struct interface srp;
00093         /** CMRC interface */
00094         struct interface cmrc;
00095 
00096         /** Infiniband device */
00097         struct ib_device *ibdev;
00098 
00099         /** ACPI descriptor */
00100         struct acpi_descriptor desc;
00101         /** Boot firmware table parameters */
00102         struct ipxe_ib_sbft sbft;
00103 };
00104 
00105 /**
00106  * Free IB SRP device
00107  *
00108  * @v refcnt            Reference count
00109  */
00110 static void ib_srp_free ( struct refcnt *refcnt ) {
00111         struct ib_srp_device *ib_srp =
00112                 container_of ( refcnt, struct ib_srp_device, refcnt );
00113 
00114         ibdev_put ( ib_srp->ibdev );
00115         free ( ib_srp );
00116 }
00117 
00118 /**
00119  * Close IB SRP device
00120  *
00121  * @v ib_srp            IB SRP device
00122  * @v rc                Reason for close
00123  */
00124 static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
00125 
00126         /* Shut down interfaces */
00127         intf_shutdown ( &ib_srp->cmrc, rc );
00128         intf_shutdown ( &ib_srp->srp, rc );
00129 }
00130 
00131 /**
00132  * Get IB SRP ACPI descriptor
00133  *
00134  * @v ib_srp            IB SRP device
00135  * @ret desc            ACPI descriptor
00136  */
00137 static struct acpi_descriptor *
00138 ib_srp_describe ( struct ib_srp_device *ib_srp ) {
00139 
00140         return &ib_srp->desc;
00141 }
00142 
00143 /** IB SRP CMRC interface operations */
00144 static struct interface_operation ib_srp_cmrc_op[] = {
00145         INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
00146 };
00147 
00148 /** IB SRP CMRC interface descriptor */
00149 static struct interface_descriptor ib_srp_cmrc_desc =
00150         INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp );
00151 
00152 /** IB SRP SRP interface operations */
00153 static struct interface_operation ib_srp_srp_op[] = {
00154         INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ),
00155         INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
00156 };
00157 
00158 /** IB SRP SRP interface descriptor */
00159 static struct interface_descriptor ib_srp_srp_desc =
00160         INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc );
00161 
00162 /**
00163  * Open IB SRP device
00164  *
00165  * @v block             Block control interface
00166  * @v ibdev             Infiniband device
00167  * @v dgid              Destination GID
00168  * @v service_id        Service ID
00169  * @v initiator         Initiator port ID
00170  * @v target            Target port ID
00171  * @v lun               SCSI LUN
00172  * @ret rc              Return status code
00173  */
00174 static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
00175                          union ib_gid *dgid, union ib_guid *service_id,
00176                          union srp_port_id *initiator,
00177                          union srp_port_id *target, struct scsi_lun *lun ) {
00178         struct ib_srp_device *ib_srp;
00179         struct ipxe_ib_sbft *sbft;
00180         int rc;
00181 
00182         /* Allocate and initialise structure */
00183         ib_srp = zalloc ( sizeof ( *ib_srp ) );
00184         if ( ! ib_srp ) {
00185                 rc = -ENOMEM;
00186                 goto err_zalloc;
00187         }
00188         ref_init ( &ib_srp->refcnt, ib_srp_free );
00189         intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
00190         intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
00191         ib_srp->ibdev = ibdev_get ( ibdev );
00192         acpi_init ( &ib_srp->desc, &ib_sbft_model, &ib_srp->refcnt );
00193         DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
00194                ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
00195 
00196         /* Preserve parameters required for boot firmware table */
00197         sbft = &ib_srp->sbft;
00198         memcpy ( &sbft->scsi.lun, lun, sizeof ( sbft->scsi.lun ) );
00199         memcpy ( &sbft->srp.initiator, initiator,
00200                  sizeof ( sbft->srp.initiator ) );
00201         memcpy ( &sbft->srp.target, target, sizeof ( sbft->srp.target ) );
00202         memcpy ( &sbft->ib.dgid, dgid, sizeof ( sbft->ib.dgid ) );
00203         memcpy ( &sbft->ib.service_id, service_id,
00204                  sizeof ( sbft->ib.service_id ) );
00205 
00206         /* Open CMRC socket */
00207         if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
00208                                    service_id, "SRP" ) ) != 0 ) {
00209                 DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n",
00210                        ib_srp, strerror ( rc ) );
00211                 goto err_cmrc_open;
00212         }
00213 
00214         /* Attach SRP device to parent interface */
00215         if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target,
00216                                ibdev->rdma_key, lun ) ) != 0 ) {
00217                 DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n",
00218                        ib_srp, strerror ( rc ) );
00219                 goto err_srp_open;
00220         }
00221 
00222         /* Mortalise self and return */
00223         ref_put ( &ib_srp->refcnt );
00224         return 0;
00225 
00226  err_srp_open:
00227  err_cmrc_open:
00228         ib_srp_close ( ib_srp, rc );
00229         ref_put ( &ib_srp->refcnt );
00230  err_zalloc:
00231         return rc;
00232 }
00233 
00234 /******************************************************************************
00235  *
00236  * IB SRP URIs
00237  *
00238  ******************************************************************************
00239  */
00240 
00241 /** IB SRP parse flags */
00242 enum ib_srp_parse_flags {
00243         IB_SRP_PARSE_REQUIRED = 0x0000,
00244         IB_SRP_PARSE_OPTIONAL = 0x8000,
00245         IB_SRP_PARSE_FLAG_MASK = 0xf000,
00246 };
00247 
00248 /** IB SRP root path parameters */
00249 struct ib_srp_root_path {
00250         /** Source GID */
00251         union ib_gid sgid;
00252         /** Initiator port ID */
00253         union ib_srp_initiator_port_id initiator;
00254         /** Destination GID */
00255         union ib_gid dgid;
00256         /** Partition key */
00257         uint16_t pkey;
00258         /** Service ID */
00259         union ib_guid service_id;
00260         /** SCSI LUN */
00261         struct scsi_lun lun;
00262         /** Target port ID */
00263         union ib_srp_target_port_id target;
00264 };
00265 
00266 /**
00267  * Parse IB SRP root path byte-string value
00268  *
00269  * @v rp_comp           Root path component string
00270  * @v default_value     Default value to use if component string is empty
00271  * @ret value           Value
00272  */
00273 static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
00274                                       unsigned int size_flags ) {
00275         size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
00276         size_t rp_comp_len = strlen ( rp_comp );
00277         int decoded_size;
00278 
00279         /* Allow optional components to be empty */
00280         if ( ( rp_comp_len == 0 ) &&
00281              ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
00282                 return 0;
00283 
00284         /* Check string length */
00285         if ( rp_comp_len != ( 2 * size ) )
00286                 return -EINVAL_BYTE_STRING_LEN;
00287 
00288         /* Parse byte string */
00289         decoded_size = base16_decode ( rp_comp, bytes, size );
00290         if ( decoded_size < 0 )
00291                 return decoded_size;
00292 
00293         return 0;
00294 }
00295 
00296 /**
00297  * Parse IB SRP root path integer value
00298  *
00299  * @v rp_comp           Root path component string
00300  * @v default_value     Default value to use if component string is empty
00301  * @ret value           Value
00302  */
00303 static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
00304         int value;
00305         char *end;
00306 
00307         value = strtoul ( rp_comp, &end, 16 );
00308         if ( *end )
00309                 return -EINVAL_INTEGER;
00310 
00311         if ( end == rp_comp )
00312                 return default_value;
00313 
00314         return value;
00315 }
00316 
00317 /**
00318  * Parse IB SRP root path source GID
00319  *
00320  * @v rp_comp           Root path component string
00321  * @v rp                IB SRP root path
00322  * @ret rc              Return status code
00323  */
00324 static int ib_srp_parse_sgid ( const char *rp_comp,
00325                                struct ib_srp_root_path *rp ) {
00326         struct ib_device *ibdev;
00327 
00328         /* Default to the GID of the last opened Infiniband device */
00329         if ( ( ibdev = last_opened_ibdev() ) != NULL )
00330                 memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) );
00331 
00332         return ib_srp_parse_byte_string ( rp_comp, rp->sgid.bytes,
00333                                           ( sizeof ( rp->sgid ) |
00334                                             IB_SRP_PARSE_OPTIONAL ) );
00335 }
00336 
00337 /**
00338  * Parse IB SRP root path initiator identifier extension
00339  *
00340  * @v rp_comp           Root path component string
00341  * @v rp                IB SRP root path
00342  * @ret rc              Return status code
00343  */
00344 static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
00345                                            struct ib_srp_root_path *rp ) {
00346         union ib_srp_initiator_port_id *port_id = &rp->initiator;
00347 
00348         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
00349                                           ( sizeof ( port_id->ib.id_ext ) |
00350                                             IB_SRP_PARSE_OPTIONAL ) );
00351 }
00352 
00353 /**
00354  * Parse IB SRP root path initiator HCA GUID
00355  *
00356  * @v rp_comp           Root path component string
00357  * @v rp                IB SRP root path
00358  * @ret rc              Return status code
00359  */
00360 static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
00361                                              struct ib_srp_root_path *rp ) {
00362         union ib_srp_initiator_port_id *port_id = &rp->initiator;
00363 
00364         /* Default to the GUID portion of the source GID */
00365         memcpy ( &port_id->ib.hca_guid, &rp->sgid.s.guid,
00366                  sizeof ( port_id->ib.hca_guid ) );
00367 
00368         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.bytes,
00369                                           ( sizeof ( port_id->ib.hca_guid ) |
00370                                             IB_SRP_PARSE_OPTIONAL ) );
00371 }
00372 
00373 /**
00374  * Parse IB SRP root path destination GID
00375  *
00376  * @v rp_comp           Root path component string
00377  * @v rp                IB SRP root path
00378  * @ret rc              Return status code
00379  */
00380 static int ib_srp_parse_dgid ( const char *rp_comp,
00381                                struct ib_srp_root_path *rp ) {
00382         return ib_srp_parse_byte_string ( rp_comp, rp->dgid.bytes,
00383                                           ( sizeof ( rp->dgid ) |
00384                                             IB_SRP_PARSE_REQUIRED ) );
00385 }
00386 
00387 /**
00388  * Parse IB SRP root path partition key
00389  *
00390  * @v rp_comp           Root path component string
00391  * @v rp                IB SRP root path
00392  * @ret rc              Return status code
00393  */
00394 static int ib_srp_parse_pkey ( const char *rp_comp,
00395                                struct ib_srp_root_path *rp ) {
00396         int pkey;
00397 
00398         if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
00399                 return pkey;
00400         rp->pkey = pkey;
00401         return 0;
00402 }
00403 
00404 /**
00405  * Parse IB SRP root path service ID
00406  *
00407  * @v rp_comp           Root path component string
00408  * @v rp                IB SRP root path
00409  * @ret rc              Return status code
00410  */
00411 static int ib_srp_parse_service_id ( const char *rp_comp,
00412                                      struct ib_srp_root_path *rp ) {
00413         return ib_srp_parse_byte_string ( rp_comp, rp->service_id.bytes,
00414                                           ( sizeof ( rp->service_id ) |
00415                                             IB_SRP_PARSE_REQUIRED ) );
00416 }
00417 
00418 /**
00419  * Parse IB SRP root path LUN
00420  *
00421  * @v rp_comp           Root path component string
00422  * @v rp                IB SRP root path
00423  * @ret rc              Return status code
00424  */
00425 static int ib_srp_parse_lun ( const char *rp_comp,
00426                               struct ib_srp_root_path *rp ) {
00427         return scsi_parse_lun ( rp_comp, &rp->lun );
00428 }
00429 
00430 /**
00431  * Parse IB SRP root path target identifier extension
00432  *
00433  * @v rp_comp           Root path component string
00434  * @v rp                IB SRP root path
00435  * @ret rc              Return status code
00436  */
00437 static int ib_srp_parse_target_id_ext ( const char *rp_comp,
00438                                         struct ib_srp_root_path *rp ) {
00439         union ib_srp_target_port_id *port_id = &rp->target;
00440 
00441         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
00442                                           ( sizeof ( port_id->ib.id_ext ) |
00443                                             IB_SRP_PARSE_REQUIRED ) );
00444 }
00445 
00446 /**
00447  * Parse IB SRP root path target I/O controller GUID
00448  *
00449  * @v rp_comp           Root path component string
00450  * @v rp                IB SRP root path
00451  * @ret rc              Return status code
00452  */
00453 static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
00454                                           struct ib_srp_root_path *rp ) {
00455         union ib_srp_target_port_id *port_id = &rp->target;
00456 
00457         return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.bytes,
00458                                           ( sizeof ( port_id->ib.ioc_guid ) |
00459                                             IB_SRP_PARSE_REQUIRED ) );
00460 }
00461 
00462 /** IB SRP root path component parser */
00463 struct ib_srp_root_path_parser {
00464         /**
00465          * Parse IB SRP root path component
00466          *
00467          * @v rp_comp           Root path component string
00468          * @v rp                IB SRP root path
00469          * @ret rc              Return status code
00470          */
00471         int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
00472 };
00473 
00474 /** IB SRP root path components */
00475 static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
00476         { ib_srp_parse_sgid },
00477         { ib_srp_parse_initiator_id_ext },
00478         { ib_srp_parse_initiator_hca_guid },
00479         { ib_srp_parse_dgid },
00480         { ib_srp_parse_pkey },
00481         { ib_srp_parse_service_id },
00482         { ib_srp_parse_lun },
00483         { ib_srp_parse_target_id_ext },
00484         { ib_srp_parse_target_ioc_guid },
00485 };
00486 
00487 /** Number of IB SRP root path components */
00488 #define IB_SRP_NUM_RP_COMPONENTS \
00489         ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
00490 
00491 /**
00492  * Parse IB SRP root path
00493  *
00494  * @v rp_string         Root path string
00495  * @v rp                IB SRP root path
00496  * @ret rc              Return status code
00497  */
00498 static int ib_srp_parse_root_path ( const char *rp_string,
00499                                     struct ib_srp_root_path *rp ) {
00500         struct ib_srp_root_path_parser *parser;
00501         char rp_string_copy[ strlen ( rp_string ) + 1 ];
00502         char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
00503         char *rp_string_tmp = rp_string_copy;
00504         unsigned int i = 0;
00505         int rc;
00506 
00507         /* Split root path into component parts */
00508         strcpy ( rp_string_copy, rp_string );
00509         while ( 1 ) {
00510                 rp_comp[i++] = rp_string_tmp;
00511                 if ( i == IB_SRP_NUM_RP_COMPONENTS )
00512                         break;
00513                 for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
00514                         if ( ! *rp_string_tmp ) {
00515                                 DBG ( "IBSRP root path \"%s\" too short\n",
00516                                       rp_string );
00517                                 return -EINVAL_RP_TOO_SHORT;
00518                         }
00519                 }
00520                 *(rp_string_tmp++) = '\0';
00521         }
00522 
00523         /* Parse root path components */
00524         for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
00525                 parser = &ib_srp_rp_parser[i];
00526                 if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) {
00527                         DBG ( "IBSRP could not parse \"%s\" in root path "
00528                               "\"%s\": %s\n", rp_comp[i], rp_string,
00529                               strerror ( rc ) );
00530                         return rc;
00531                 }
00532         }
00533 
00534         return 0;
00535 }
00536 
00537 /**
00538  * Open IB SRP URI
00539  *
00540  * @v parent            Parent interface
00541  * @v uri               URI
00542  * @ret rc              Return status code
00543  */
00544 static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) {
00545         struct ib_srp_root_path rp;
00546         struct ib_device *ibdev;
00547         int rc;
00548 
00549         /* Parse URI */
00550         if ( ! uri->opaque )
00551                 return -EINVAL;
00552         memset ( &rp, 0, sizeof ( rp ) );
00553         if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 )
00554                 return rc;
00555 
00556         /* Identify Infiniband device */
00557         ibdev = find_ibdev ( &rp.sgid );
00558         if ( ! ibdev ) {
00559                 DBG ( "IBSRP could not identify Infiniband device\n" );
00560                 return -ENODEV;
00561         }
00562 
00563         /* Open IB SRP device */
00564         if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id,
00565                                   &rp.initiator.srp, &rp.target.srp,
00566                                   &rp.lun ) ) != 0 )
00567                 return rc;
00568 
00569         return 0;
00570 }
00571 
00572 /** IB SRP URI opener */
00573 struct uri_opener ib_srp_uri_opener __uri_opener = {
00574         .scheme = "ib_srp",
00575         .open = ib_srp_open_uri,
00576 };
00577 
00578 /******************************************************************************
00579  *
00580  * IB SRP boot firmware table (sBFT)
00581  *
00582  ******************************************************************************
00583  */
00584 
00585 /**
00586  * Check if IB SRP boot firmware table descriptor is complete
00587  *
00588  * @v desc              ACPI descriptor
00589  * @ret rc              Return status code
00590  */
00591 static int ib_sbft_complete ( struct acpi_descriptor *desc __unused ) {
00592         return 0;
00593 }
00594 
00595 /**
00596  * Install IB SRP boot firmware table(s)
00597  *
00598  * @v install           Installation method
00599  * @ret rc              Return status code
00600  */
00601 static int ib_sbft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
00602         struct ib_srp_device *ib_srp;
00603         struct ipxe_ib_sbft *sbft;
00604         struct ib_device *ibdev;
00605         int rc;
00606 
00607         list_for_each_entry ( ib_srp, &ib_sbft_model.descs, desc.list ) {
00608 
00609                 /* Complete table */
00610                 sbft = &ib_srp->sbft;
00611                 ibdev = ib_srp->ibdev;
00612                 sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG );
00613                 sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) );
00614                 sbft->table.acpi.revision = 1;
00615                 sbft->table.scsi_offset =
00616                         cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) );
00617                 sbft->table.srp_offset =
00618                         cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) );
00619                 sbft->table.ib_offset =
00620                         cpu_to_le16 ( offsetof ( typeof ( *sbft ), ib ) );
00621                 memcpy ( &sbft->ib.sgid, &ibdev->gid, sizeof ( sbft->ib.sgid ));
00622                 sbft->ib.pkey = cpu_to_le16 ( ibdev->pkey );
00623 
00624                 /* Install table */
00625                 if ( ( rc = install ( &sbft->table.acpi ) ) != 0 ) {
00626                         DBGC ( ib_srp, "IBSRP %p could not install sBFT: %s\n",
00627                                ib_srp, strerror ( rc ) );
00628                         return rc;
00629                 }
00630         }
00631 
00632         return 0;
00633 }
00634 
00635 /** IB sBFT model */
00636 struct acpi_model ib_sbft_model __acpi_model = {
00637         .descs = LIST_HEAD_INIT ( ib_sbft_model.descs ),
00638         .complete = ib_sbft_complete,
00639         .install = ib_sbft_install,
00640 };