You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ib_srp.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*
  2. * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  22. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  26. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  28. * OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. FILE_LICENCE ( BSD2 );
  31. #include <stdlib.h>
  32. #include <errno.h>
  33. #include <ipxe/interface.h>
  34. #include <ipxe/uri.h>
  35. #include <ipxe/open.h>
  36. #include <ipxe/base16.h>
  37. #include <ipxe/acpi.h>
  38. #include <ipxe/srp.h>
  39. #include <ipxe/infiniband.h>
  40. #include <ipxe/ib_cmrc.h>
  41. #include <ipxe/ib_srp.h>
  42. /**
  43. * @file
  44. *
  45. * SCSI RDMA Protocol over Infiniband
  46. *
  47. */
  48. /* Disambiguate the various possible EINVALs */
  49. #define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN )
  50. #define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \
  51. ( EINFO_EINVAL, 0x01, "Invalid byte string length" )
  52. #define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER )
  53. #define EINFO_EINVAL_INTEGER __einfo_uniqify \
  54. ( EINFO_EINVAL, 0x03, "Invalid integer" )
  55. #define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT )
  56. #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \
  57. ( EINFO_EINVAL, 0x04, "Root path too short" )
  58. struct acpi_model ib_sbft_model __acpi_model;
  59. /******************************************************************************
  60. *
  61. * IB SRP devices
  62. *
  63. ******************************************************************************
  64. */
  65. /**
  66. * An IB SRP sBFT created by iPXE
  67. */
  68. struct ipxe_ib_sbft {
  69. /** The table header */
  70. struct sbft_table table;
  71. /** The SCSI subtable */
  72. struct sbft_scsi_subtable scsi;
  73. /** The SRP subtable */
  74. struct sbft_srp_subtable srp;
  75. /** The Infiniband subtable */
  76. struct sbft_ib_subtable ib;
  77. };
  78. /** An Infiniband SRP device */
  79. struct ib_srp_device {
  80. /** Reference count */
  81. struct refcnt refcnt;
  82. /** SRP transport interface */
  83. struct interface srp;
  84. /** CMRC interface */
  85. struct interface cmrc;
  86. /** Infiniband device */
  87. struct ib_device *ibdev;
  88. /** ACPI descriptor */
  89. struct acpi_descriptor desc;
  90. /** Boot firmware table parameters */
  91. struct ipxe_ib_sbft sbft;
  92. };
  93. /**
  94. * Free IB SRP device
  95. *
  96. * @v refcnt Reference count
  97. */
  98. static void ib_srp_free ( struct refcnt *refcnt ) {
  99. struct ib_srp_device *ib_srp =
  100. container_of ( refcnt, struct ib_srp_device, refcnt );
  101. ibdev_put ( ib_srp->ibdev );
  102. free ( ib_srp );
  103. }
  104. /**
  105. * Close IB SRP device
  106. *
  107. * @v ib_srp IB SRP device
  108. * @v rc Reason for close
  109. */
  110. static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) {
  111. /* Shut down interfaces */
  112. intf_shutdown ( &ib_srp->cmrc, rc );
  113. intf_shutdown ( &ib_srp->srp, rc );
  114. }
  115. /**
  116. * Get IB SRP ACPI descriptor
  117. *
  118. * @v ib_srp IB SRP device
  119. * @ret desc ACPI descriptor
  120. */
  121. static struct acpi_descriptor *
  122. ib_srp_describe ( struct ib_srp_device *ib_srp ) {
  123. return &ib_srp->desc;
  124. }
  125. /** IB SRP CMRC interface operations */
  126. static struct interface_operation ib_srp_cmrc_op[] = {
  127. INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
  128. };
  129. /** IB SRP CMRC interface descriptor */
  130. static struct interface_descriptor ib_srp_cmrc_desc =
  131. INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp );
  132. /** IB SRP SRP interface operations */
  133. static struct interface_operation ib_srp_srp_op[] = {
  134. INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ),
  135. INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ),
  136. };
  137. /** IB SRP SRP interface descriptor */
  138. static struct interface_descriptor ib_srp_srp_desc =
  139. INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc );
  140. /**
  141. * Open IB SRP device
  142. *
  143. * @v block Block control interface
  144. * @v ibdev Infiniband device
  145. * @v dgid Destination GID
  146. * @v service_id Service ID
  147. * @v initiator Initiator port ID
  148. * @v target Target port ID
  149. * @v lun SCSI LUN
  150. * @ret rc Return status code
  151. */
  152. static int ib_srp_open ( struct interface *block, struct ib_device *ibdev,
  153. union ib_gid *dgid, union ib_guid *service_id,
  154. union srp_port_id *initiator,
  155. union srp_port_id *target, struct scsi_lun *lun ) {
  156. struct ib_srp_device *ib_srp;
  157. struct ipxe_ib_sbft *sbft;
  158. int rc;
  159. /* Allocate and initialise structure */
  160. ib_srp = zalloc ( sizeof ( *ib_srp ) );
  161. if ( ! ib_srp ) {
  162. rc = -ENOMEM;
  163. goto err_zalloc;
  164. }
  165. ref_init ( &ib_srp->refcnt, ib_srp_free );
  166. intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt );
  167. intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt );
  168. ib_srp->ibdev = ibdev_get ( ibdev );
  169. acpi_init ( &ib_srp->desc, &ib_sbft_model, &ib_srp->refcnt );
  170. DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n",
  171. ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) );
  172. /* Preserve parameters required for boot firmware table */
  173. sbft = &ib_srp->sbft;
  174. memcpy ( &sbft->scsi.lun, lun, sizeof ( sbft->scsi.lun ) );
  175. memcpy ( &sbft->srp.initiator, initiator,
  176. sizeof ( sbft->srp.initiator ) );
  177. memcpy ( &sbft->srp.target, target, sizeof ( sbft->srp.target ) );
  178. memcpy ( &sbft->ib.dgid, dgid, sizeof ( sbft->ib.dgid ) );
  179. memcpy ( &sbft->ib.service_id, service_id,
  180. sizeof ( sbft->ib.service_id ) );
  181. /* Open CMRC socket */
  182. if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid,
  183. service_id, "SRP" ) ) != 0 ) {
  184. DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n",
  185. ib_srp, strerror ( rc ) );
  186. goto err_cmrc_open;
  187. }
  188. /* Attach SRP device to parent interface */
  189. if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target,
  190. ibdev->rdma_key, lun ) ) != 0 ) {
  191. DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n",
  192. ib_srp, strerror ( rc ) );
  193. goto err_srp_open;
  194. }
  195. /* Mortalise self and return */
  196. ref_put ( &ib_srp->refcnt );
  197. return 0;
  198. err_srp_open:
  199. err_cmrc_open:
  200. ib_srp_close ( ib_srp, rc );
  201. ref_put ( &ib_srp->refcnt );
  202. err_zalloc:
  203. return rc;
  204. }
  205. /******************************************************************************
  206. *
  207. * IB SRP URIs
  208. *
  209. ******************************************************************************
  210. */
  211. /** IB SRP parse flags */
  212. enum ib_srp_parse_flags {
  213. IB_SRP_PARSE_REQUIRED = 0x0000,
  214. IB_SRP_PARSE_OPTIONAL = 0x8000,
  215. IB_SRP_PARSE_FLAG_MASK = 0xf000,
  216. };
  217. /** IB SRP root path parameters */
  218. struct ib_srp_root_path {
  219. /** Source GID */
  220. union ib_gid sgid;
  221. /** Initiator port ID */
  222. union ib_srp_initiator_port_id initiator;
  223. /** Destination GID */
  224. union ib_gid dgid;
  225. /** Partition key */
  226. uint16_t pkey;
  227. /** Service ID */
  228. union ib_guid service_id;
  229. /** SCSI LUN */
  230. struct scsi_lun lun;
  231. /** Target port ID */
  232. union ib_srp_target_port_id target;
  233. };
  234. /**
  235. * Parse IB SRP root path byte-string value
  236. *
  237. * @v rp_comp Root path component string
  238. * @v default_value Default value to use if component string is empty
  239. * @ret value Value
  240. */
  241. static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
  242. unsigned int size_flags ) {
  243. size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
  244. size_t rp_comp_len = strlen ( rp_comp );
  245. int decoded_size;
  246. /* Allow optional components to be empty */
  247. if ( ( rp_comp_len == 0 ) &&
  248. ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
  249. return 0;
  250. /* Check string length */
  251. if ( rp_comp_len != ( 2 * size ) )
  252. return -EINVAL_BYTE_STRING_LEN;
  253. /* Parse byte string */
  254. decoded_size = base16_decode ( rp_comp, bytes, size );
  255. if ( decoded_size < 0 )
  256. return decoded_size;
  257. return 0;
  258. }
  259. /**
  260. * Parse IB SRP root path integer value
  261. *
  262. * @v rp_comp Root path component string
  263. * @v default_value Default value to use if component string is empty
  264. * @ret value Value
  265. */
  266. static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
  267. int value;
  268. char *end;
  269. value = strtoul ( rp_comp, &end, 16 );
  270. if ( *end )
  271. return -EINVAL_INTEGER;
  272. if ( end == rp_comp )
  273. return default_value;
  274. return value;
  275. }
  276. /**
  277. * Parse IB SRP root path source GID
  278. *
  279. * @v rp_comp Root path component string
  280. * @v rp IB SRP root path
  281. * @ret rc Return status code
  282. */
  283. static int ib_srp_parse_sgid ( const char *rp_comp,
  284. struct ib_srp_root_path *rp ) {
  285. struct ib_device *ibdev;
  286. /* Default to the GID of the last opened Infiniband device */
  287. if ( ( ibdev = last_opened_ibdev() ) != NULL )
  288. memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) );
  289. return ib_srp_parse_byte_string ( rp_comp, rp->sgid.bytes,
  290. ( sizeof ( rp->sgid ) |
  291. IB_SRP_PARSE_OPTIONAL ) );
  292. }
  293. /**
  294. * Parse IB SRP root path initiator identifier extension
  295. *
  296. * @v rp_comp Root path component string
  297. * @v rp IB SRP root path
  298. * @ret rc Return status code
  299. */
  300. static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
  301. struct ib_srp_root_path *rp ) {
  302. union ib_srp_initiator_port_id *port_id = &rp->initiator;
  303. return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
  304. ( sizeof ( port_id->ib.id_ext ) |
  305. IB_SRP_PARSE_OPTIONAL ) );
  306. }
  307. /**
  308. * Parse IB SRP root path initiator HCA GUID
  309. *
  310. * @v rp_comp Root path component string
  311. * @v rp IB SRP root path
  312. * @ret rc Return status code
  313. */
  314. static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
  315. struct ib_srp_root_path *rp ) {
  316. union ib_srp_initiator_port_id *port_id = &rp->initiator;
  317. /* Default to the GUID portion of the source GID */
  318. memcpy ( &port_id->ib.hca_guid, &rp->sgid.s.guid,
  319. sizeof ( port_id->ib.hca_guid ) );
  320. return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.bytes,
  321. ( sizeof ( port_id->ib.hca_guid ) |
  322. IB_SRP_PARSE_OPTIONAL ) );
  323. }
  324. /**
  325. * Parse IB SRP root path destination GID
  326. *
  327. * @v rp_comp Root path component string
  328. * @v rp IB SRP root path
  329. * @ret rc Return status code
  330. */
  331. static int ib_srp_parse_dgid ( const char *rp_comp,
  332. struct ib_srp_root_path *rp ) {
  333. return ib_srp_parse_byte_string ( rp_comp, rp->dgid.bytes,
  334. ( sizeof ( rp->dgid ) |
  335. IB_SRP_PARSE_REQUIRED ) );
  336. }
  337. /**
  338. * Parse IB SRP root path partition key
  339. *
  340. * @v rp_comp Root path component string
  341. * @v rp IB SRP root path
  342. * @ret rc Return status code
  343. */
  344. static int ib_srp_parse_pkey ( const char *rp_comp,
  345. struct ib_srp_root_path *rp ) {
  346. int pkey;
  347. if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
  348. return pkey;
  349. rp->pkey = pkey;
  350. return 0;
  351. }
  352. /**
  353. * Parse IB SRP root path service ID
  354. *
  355. * @v rp_comp Root path component string
  356. * @v rp IB SRP root path
  357. * @ret rc Return status code
  358. */
  359. static int ib_srp_parse_service_id ( const char *rp_comp,
  360. struct ib_srp_root_path *rp ) {
  361. return ib_srp_parse_byte_string ( rp_comp, rp->service_id.bytes,
  362. ( sizeof ( rp->service_id ) |
  363. IB_SRP_PARSE_REQUIRED ) );
  364. }
  365. /**
  366. * Parse IB SRP root path LUN
  367. *
  368. * @v rp_comp Root path component string
  369. * @v rp IB SRP root path
  370. * @ret rc Return status code
  371. */
  372. static int ib_srp_parse_lun ( const char *rp_comp,
  373. struct ib_srp_root_path *rp ) {
  374. return scsi_parse_lun ( rp_comp, &rp->lun );
  375. }
  376. /**
  377. * Parse IB SRP root path target identifier extension
  378. *
  379. * @v rp_comp Root path component string
  380. * @v rp IB SRP root path
  381. * @ret rc Return status code
  382. */
  383. static int ib_srp_parse_target_id_ext ( const char *rp_comp,
  384. struct ib_srp_root_path *rp ) {
  385. union ib_srp_target_port_id *port_id = &rp->target;
  386. return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes,
  387. ( sizeof ( port_id->ib.id_ext ) |
  388. IB_SRP_PARSE_REQUIRED ) );
  389. }
  390. /**
  391. * Parse IB SRP root path target I/O controller GUID
  392. *
  393. * @v rp_comp Root path component string
  394. * @v rp IB SRP root path
  395. * @ret rc Return status code
  396. */
  397. static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
  398. struct ib_srp_root_path *rp ) {
  399. union ib_srp_target_port_id *port_id = &rp->target;
  400. return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.bytes,
  401. ( sizeof ( port_id->ib.ioc_guid ) |
  402. IB_SRP_PARSE_REQUIRED ) );
  403. }
  404. /** IB SRP root path component parser */
  405. struct ib_srp_root_path_parser {
  406. /**
  407. * Parse IB SRP root path component
  408. *
  409. * @v rp_comp Root path component string
  410. * @v rp IB SRP root path
  411. * @ret rc Return status code
  412. */
  413. int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
  414. };
  415. /** IB SRP root path components */
  416. static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
  417. { ib_srp_parse_sgid },
  418. { ib_srp_parse_initiator_id_ext },
  419. { ib_srp_parse_initiator_hca_guid },
  420. { ib_srp_parse_dgid },
  421. { ib_srp_parse_pkey },
  422. { ib_srp_parse_service_id },
  423. { ib_srp_parse_lun },
  424. { ib_srp_parse_target_id_ext },
  425. { ib_srp_parse_target_ioc_guid },
  426. };
  427. /** Number of IB SRP root path components */
  428. #define IB_SRP_NUM_RP_COMPONENTS \
  429. ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
  430. /**
  431. * Parse IB SRP root path
  432. *
  433. * @v rp_string Root path string
  434. * @v rp IB SRP root path
  435. * @ret rc Return status code
  436. */
  437. static int ib_srp_parse_root_path ( const char *rp_string,
  438. struct ib_srp_root_path *rp ) {
  439. struct ib_srp_root_path_parser *parser;
  440. char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
  441. char *rp_string_copy;
  442. char *rp_string_tmp;
  443. unsigned int i = 0;
  444. int rc;
  445. /* Create modifiable copy of root path */
  446. rp_string_copy = strdup ( rp_string );
  447. if ( ! rp_string_copy ) {
  448. rc = -ENOMEM;
  449. goto err_strdup;
  450. }
  451. rp_string_tmp = rp_string_copy;
  452. /* Split root path into component parts */
  453. while ( 1 ) {
  454. rp_comp[i++] = rp_string_tmp;
  455. if ( i == IB_SRP_NUM_RP_COMPONENTS )
  456. break;
  457. for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
  458. if ( ! *rp_string_tmp ) {
  459. DBG ( "IBSRP root path \"%s\" too short\n",
  460. rp_string );
  461. rc = -EINVAL_RP_TOO_SHORT;
  462. goto err_split;
  463. }
  464. }
  465. *(rp_string_tmp++) = '\0';
  466. }
  467. /* Parse root path components */
  468. for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
  469. parser = &ib_srp_rp_parser[i];
  470. if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) {
  471. DBG ( "IBSRP could not parse \"%s\" in root path "
  472. "\"%s\": %s\n", rp_comp[i], rp_string,
  473. strerror ( rc ) );
  474. goto err_parse;
  475. }
  476. }
  477. err_parse:
  478. err_split:
  479. free ( rp_string_copy );
  480. err_strdup:
  481. return rc;
  482. }
  483. /**
  484. * Open IB SRP URI
  485. *
  486. * @v parent Parent interface
  487. * @v uri URI
  488. * @ret rc Return status code
  489. */
  490. static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) {
  491. struct ib_srp_root_path rp;
  492. struct ib_device *ibdev;
  493. int rc;
  494. /* Parse URI */
  495. if ( ! uri->opaque )
  496. return -EINVAL;
  497. memset ( &rp, 0, sizeof ( rp ) );
  498. if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 )
  499. return rc;
  500. /* Identify Infiniband device */
  501. ibdev = find_ibdev ( &rp.sgid );
  502. if ( ! ibdev ) {
  503. DBG ( "IBSRP could not identify Infiniband device\n" );
  504. return -ENODEV;
  505. }
  506. /* Open IB SRP device */
  507. if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id,
  508. &rp.initiator.srp, &rp.target.srp,
  509. &rp.lun ) ) != 0 )
  510. return rc;
  511. return 0;
  512. }
  513. /** IB SRP URI opener */
  514. struct uri_opener ib_srp_uri_opener __uri_opener = {
  515. .scheme = "ib_srp",
  516. .open = ib_srp_open_uri,
  517. };
  518. /******************************************************************************
  519. *
  520. * IB SRP boot firmware table (sBFT)
  521. *
  522. ******************************************************************************
  523. */
  524. /**
  525. * Check if IB SRP boot firmware table descriptor is complete
  526. *
  527. * @v desc ACPI descriptor
  528. * @ret rc Return status code
  529. */
  530. static int ib_sbft_complete ( struct acpi_descriptor *desc __unused ) {
  531. return 0;
  532. }
  533. /**
  534. * Install IB SRP boot firmware table(s)
  535. *
  536. * @v install Installation method
  537. * @ret rc Return status code
  538. */
  539. static int ib_sbft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
  540. struct ib_srp_device *ib_srp;
  541. struct ipxe_ib_sbft *sbft;
  542. struct ib_device *ibdev;
  543. int rc;
  544. list_for_each_entry ( ib_srp, &ib_sbft_model.descs, desc.list ) {
  545. /* Complete table */
  546. sbft = &ib_srp->sbft;
  547. ibdev = ib_srp->ibdev;
  548. sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG );
  549. sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) );
  550. sbft->table.acpi.revision = 1;
  551. sbft->table.scsi_offset =
  552. cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) );
  553. sbft->table.srp_offset =
  554. cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) );
  555. sbft->table.ib_offset =
  556. cpu_to_le16 ( offsetof ( typeof ( *sbft ), ib ) );
  557. memcpy ( &sbft->ib.sgid, &ibdev->gid, sizeof ( sbft->ib.sgid ));
  558. sbft->ib.pkey = cpu_to_le16 ( ibdev->pkey );
  559. /* Install table */
  560. if ( ( rc = install ( &sbft->table.acpi ) ) != 0 ) {
  561. DBGC ( ib_srp, "IBSRP %p could not install sBFT: %s\n",
  562. ib_srp, strerror ( rc ) );
  563. return rc;
  564. }
  565. }
  566. return 0;
  567. }
  568. /** IB sBFT model */
  569. struct acpi_model ib_sbft_model __acpi_model = {
  570. .descs = LIST_HEAD_INIT ( ib_sbft_model.descs ),
  571. .complete = ib_sbft_complete,
  572. .install = ib_sbft_install,
  573. };