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.

ibft.c 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. * Copyright Fen Systems Ltd. 2007. Portions of this code are derived
  3. * from IBM Corporation Sample Programs. Copyright IBM Corporation
  4. * 2004, 2007. All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  21. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  22. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE.
  25. *
  26. */
  27. FILE_LICENCE ( BSD2 );
  28. #include <stdint.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <byteswap.h>
  34. #include <ipxe/pci.h>
  35. #include <ipxe/acpi.h>
  36. #include <ipxe/in.h>
  37. #include <ipxe/netdevice.h>
  38. #include <ipxe/ethernet.h>
  39. #include <ipxe/vlan.h>
  40. #include <ipxe/tcpip.h>
  41. #include <ipxe/dhcp.h>
  42. #include <ipxe/iscsi.h>
  43. #include <ipxe/ibft.h>
  44. /** @file
  45. *
  46. * iSCSI boot firmware table
  47. *
  48. * The information in this file is derived from the document "iSCSI
  49. * Boot Firmware Table (iBFT)" as published by IBM at
  50. *
  51. * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf
  52. *
  53. */
  54. /**
  55. * iSCSI string buffer
  56. *
  57. * This is an internal structure that we use to keep track of the
  58. * allocation of string data.
  59. */
  60. struct ibft_strings {
  61. /** Strings data */
  62. char *data;
  63. /** Starting offset of strings */
  64. size_t start;
  65. /** Total length */
  66. size_t len;
  67. };
  68. /**
  69. * Align structure within iBFT
  70. *
  71. * @v len Unaligned length (or offset)
  72. * @ret len Aligned length (or offset)
  73. */
  74. static inline size_t ibft_align ( size_t len ) {
  75. return ( ( len + IBFT_ALIGN - 1 ) & ~( IBFT_ALIGN - 1 ) );
  76. }
  77. /**
  78. * Fill in an IP address field within iBFT
  79. *
  80. * @v ipaddr IP address field
  81. * @v in IPv4 address
  82. */
  83. static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
  84. memset ( ipaddr, 0, sizeof ( *ipaddr ) );
  85. if ( in.s_addr ) {
  86. ipaddr->in = in;
  87. ipaddr->ones = 0xffff;
  88. }
  89. }
  90. /**
  91. * Fill in an IP address within iBFT from configuration setting
  92. *
  93. * @v settings Parent settings block, or NULL
  94. * @v ipaddr IP address field
  95. * @v setting Configuration setting
  96. * @v count Maximum number of IP addresses
  97. */
  98. static void ibft_set_ipaddr_setting ( struct settings *settings,
  99. struct ibft_ipaddr *ipaddr,
  100. const struct setting *setting,
  101. unsigned int count ) {
  102. struct in_addr in[count];
  103. unsigned int i;
  104. fetch_ipv4_array_setting ( settings, setting, in, count );
  105. for ( i = 0 ; i < count ; i++ ) {
  106. ibft_set_ipaddr ( &ipaddr[i], in[i] );
  107. }
  108. }
  109. /**
  110. * Read IP address from iBFT (for debugging)
  111. *
  112. * @v strings iBFT string block descriptor
  113. * @v string String field
  114. * @ret ipaddr IP address string
  115. */
  116. static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
  117. return inet_ntoa ( ipaddr->in );
  118. }
  119. /**
  120. * Allocate a string within iBFT
  121. *
  122. * @v strings iBFT string block descriptor
  123. * @v string String field to fill in
  124. * @v len Length of string to allocate (excluding NUL)
  125. * @ret dest String destination, or NULL
  126. */
  127. static char * ibft_alloc_string ( struct ibft_strings *strings,
  128. struct ibft_string *string, size_t len ) {
  129. size_t new_len;
  130. char *new_data;
  131. char *dest;
  132. /* Extend string data buffer */
  133. new_len = ( strings->len + len + 1 /* NUL */ );
  134. new_data = realloc ( strings->data, new_len );
  135. if ( ! new_data )
  136. return NULL;
  137. strings->data = new_data;
  138. /* Fill in string field */
  139. string->offset = cpu_to_le16 ( strings->start + strings->len );
  140. string->len = cpu_to_le16 ( len );
  141. /* Zero string */
  142. dest = ( strings->data + strings->len );
  143. memset ( dest, 0, ( len + 1 /* NUL */ ) );
  144. /* Update allocated length */
  145. strings->len = new_len;
  146. return dest;
  147. }
  148. /**
  149. * Fill in a string field within iBFT
  150. *
  151. * @v strings iBFT string block descriptor
  152. * @v string String field
  153. * @v data String to fill in, or NULL
  154. * @ret rc Return status code
  155. */
  156. static int ibft_set_string ( struct ibft_strings *strings,
  157. struct ibft_string *string, const char *data ) {
  158. char *dest;
  159. if ( ! data )
  160. return 0;
  161. dest = ibft_alloc_string ( strings, string, strlen ( data ) );
  162. if ( ! dest )
  163. return -ENOBUFS;
  164. strcpy ( dest, data );
  165. return 0;
  166. }
  167. /**
  168. * Fill in a string field within iBFT from configuration setting
  169. *
  170. * @v settings Parent settings block, or NULL
  171. * @v strings iBFT string block descriptor
  172. * @v string String field
  173. * @v setting Configuration setting
  174. * @ret rc Return status code
  175. */
  176. static int ibft_set_string_setting ( struct settings *settings,
  177. struct ibft_strings *strings,
  178. struct ibft_string *string,
  179. const struct setting *setting ) {
  180. struct settings *origin;
  181. struct setting fetched;
  182. int len;
  183. char *dest;
  184. len = fetch_setting ( settings, setting, &origin, &fetched, NULL, 0 );
  185. if ( len < 0 ) {
  186. string->offset = 0;
  187. string->len = 0;
  188. return 0;
  189. }
  190. dest = ibft_alloc_string ( strings, string, len );
  191. if ( ! dest )
  192. return -ENOBUFS;
  193. fetch_string_setting ( origin, &fetched, dest, ( len + 1 ));
  194. return 0;
  195. }
  196. /**
  197. * Read string from iBFT (for debugging)
  198. *
  199. * @v strings iBFT string block descriptor
  200. * @v string String field
  201. * @ret data String content (or "<empty>")
  202. */
  203. static const char * ibft_string ( struct ibft_strings *strings,
  204. struct ibft_string *string ) {
  205. size_t offset = le16_to_cpu ( string->offset );
  206. return ( offset ? ( strings->data + offset - strings->start ) : NULL );
  207. }
  208. /**
  209. * Check if network device is required for the iBFT
  210. *
  211. * @v netdev Network device
  212. * @ret is_required Network device is required
  213. */
  214. static int ibft_netdev_is_required ( struct net_device *netdev ) {
  215. struct iscsi_session *iscsi;
  216. struct sockaddr_tcpip *st_target;
  217. list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
  218. st_target = ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
  219. if ( tcpip_netdev ( st_target ) == netdev )
  220. return 1;
  221. }
  222. return 0;
  223. }
  224. /**
  225. * Fill in NIC portion of iBFT
  226. *
  227. * @v nic NIC portion of iBFT
  228. * @v strings iBFT string block descriptor
  229. * @v netdev Network device
  230. * @ret rc Return status code
  231. */
  232. static int ibft_fill_nic ( struct ibft_nic *nic,
  233. struct ibft_strings *strings,
  234. struct net_device *netdev ) {
  235. struct ll_protocol *ll_protocol = netdev->ll_protocol;
  236. struct in_addr netmask_addr = { 0 };
  237. unsigned int netmask_count = 0;
  238. struct settings *parent = netdev_settings ( netdev );
  239. struct settings *origin;
  240. int rc;
  241. /* Fill in common header */
  242. nic->header.structure_id = IBFT_STRUCTURE_ID_NIC;
  243. nic->header.version = 1;
  244. nic->header.length = cpu_to_le16 ( sizeof ( *nic ) );
  245. nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID |
  246. IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED );
  247. DBG ( "iBFT NIC %d is %s\n", nic->header.index, netdev->name );
  248. /* Determine origin of IP address */
  249. fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 );
  250. nic->origin = ( ( origin == parent ) ?
  251. IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP );
  252. DBG ( "iBFT NIC %d origin = %d\n", nic->header.index, nic->origin );
  253. /* Extract values from configuration settings */
  254. ibft_set_ipaddr_setting ( parent, &nic->ip_address, &ip_setting, 1 );
  255. DBG ( "iBFT NIC %d IP = %s\n",
  256. nic->header.index, ibft_ipaddr ( &nic->ip_address ) );
  257. ibft_set_ipaddr_setting ( parent, &nic->gateway, &gateway_setting, 1 );
  258. DBG ( "iBFT NIC %d gateway = %s\n",
  259. nic->header.index, ibft_ipaddr ( &nic->gateway ) );
  260. ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting,
  261. ( sizeof ( nic->dns ) /
  262. sizeof ( nic->dns[0] ) ) );
  263. ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 );
  264. DBG ( "iBFT NIC %d DNS = %s",
  265. nic->header.index, ibft_ipaddr ( &nic->dns[0] ) );
  266. DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) );
  267. if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname,
  268. &hostname_setting ) ) != 0 )
  269. return rc;
  270. DBG ( "iBFT NIC %d hostname = %s\n",
  271. nic->header.index, ibft_string ( strings, &nic->hostname ) );
  272. /* Derive subnet mask prefix from subnet mask */
  273. fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr );
  274. while ( netmask_addr.s_addr ) {
  275. if ( netmask_addr.s_addr & 0x1 )
  276. netmask_count++;
  277. netmask_addr.s_addr >>= 1;
  278. }
  279. nic->subnet_mask_prefix = netmask_count;
  280. DBG ( "iBFT NIC %d subnet = /%d\n",
  281. nic->header.index, nic->subnet_mask_prefix );
  282. /* Extract values from net-device configuration */
  283. nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) );
  284. DBG ( "iBFT NIC %d VLAN = %02x\n",
  285. nic->header.index, le16_to_cpu ( nic->vlan ) );
  286. if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
  287. nic->mac_address ) ) != 0 ) {
  288. DBG ( "Could not determine %s MAC: %s\n",
  289. netdev->name, strerror ( rc ) );
  290. return rc;
  291. }
  292. DBG ( "iBFT NIC %d MAC = %s\n",
  293. nic->header.index, eth_ntoa ( nic->mac_address ) );
  294. nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location );
  295. DBG ( "iBFT NIC %d PCI = %04x\n",
  296. nic->header.index, le16_to_cpu ( nic->pci_bus_dev_func ) );
  297. return 0;
  298. }
  299. /**
  300. * Fill in Initiator portion of iBFT
  301. *
  302. * @v initiator Initiator portion of iBFT
  303. * @v strings iBFT string block descriptor
  304. * @v initiator_iqn Initiator IQN
  305. * @ret rc Return status code
  306. */
  307. static int ibft_fill_initiator ( struct ibft_initiator *initiator,
  308. struct ibft_strings *strings,
  309. const char *initiator_iqn ) {
  310. int rc;
  311. /* Fill in common header */
  312. initiator->header.structure_id = IBFT_STRUCTURE_ID_INITIATOR;
  313. initiator->header.version = 1;
  314. initiator->header.length = cpu_to_le16 ( sizeof ( *initiator ) );
  315. initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
  316. IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED );
  317. /* Fill in initiator name */
  318. if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
  319. initiator_iqn ) ) != 0 )
  320. return rc;
  321. DBG ( "iBFT initiator name = %s\n",
  322. ibft_string ( strings, &initiator->initiator_name ) );
  323. return 0;
  324. }
  325. /**
  326. * Fill in Target NIC association
  327. *
  328. * @v target Target portion of iBFT
  329. * @v iscsi iSCSI session
  330. * @ret rc Return status code
  331. */
  332. static int ibft_fill_target_nic_association ( struct ibft_target *target,
  333. struct iscsi_session *iscsi ) {
  334. struct sockaddr_tcpip *st_target =
  335. ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
  336. struct net_device *associated;
  337. struct net_device *netdev;
  338. /* Find network device used to reach target */
  339. associated = tcpip_netdev ( st_target );
  340. if ( ! associated ) {
  341. DBG ( "iBFT target %d has no net device\n",
  342. target->header.index );
  343. return -EHOSTUNREACH;
  344. }
  345. /* Calculate association */
  346. for_each_netdev ( netdev ) {
  347. if ( netdev == associated ) {
  348. DBG ( "iBFT target %d uses NIC %d (%s)\n",
  349. target->header.index, target->nic_association,
  350. netdev->name );
  351. return 0;
  352. }
  353. if ( ! ibft_netdev_is_required ( netdev ) )
  354. continue;
  355. target->nic_association++;
  356. }
  357. DBG ( "iBFT target %d has impossible NIC %s\n",
  358. target->header.index, netdev->name );
  359. return -EINVAL;
  360. }
  361. /**
  362. * Fill in Target CHAP portion of iBFT
  363. *
  364. * @v target Target portion of iBFT
  365. * @v strings iBFT string block descriptor
  366. * @v iscsi iSCSI session
  367. * @ret rc Return status code
  368. */
  369. static int ibft_fill_target_chap ( struct ibft_target *target,
  370. struct ibft_strings *strings,
  371. struct iscsi_session *iscsi ) {
  372. int rc;
  373. if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
  374. return 0;
  375. assert ( iscsi->initiator_username );
  376. assert ( iscsi->initiator_password );
  377. target->chap_type = IBFT_CHAP_ONE_WAY;
  378. if ( ( rc = ibft_set_string ( strings, &target->chap_name,
  379. iscsi->initiator_username ) ) != 0 )
  380. return rc;
  381. DBG ( "iBFT target %d username = %s\n", target->header.index,
  382. ibft_string ( strings, &target->chap_name ) );
  383. if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
  384. iscsi->initiator_password ) ) != 0 )
  385. return rc;
  386. DBG ( "iBFT target %d password = <redacted>\n", target->header.index );
  387. return 0;
  388. }
  389. /**
  390. * Fill in Target Reverse CHAP portion of iBFT
  391. *
  392. * @v target Target portion of iBFT
  393. * @v strings iBFT string block descriptor
  394. * @v iscsi iSCSI session
  395. * @ret rc Return status code
  396. */
  397. static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
  398. struct ibft_strings *strings,
  399. struct iscsi_session *iscsi ) {
  400. int rc;
  401. if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
  402. return 0;
  403. assert ( iscsi->initiator_username );
  404. assert ( iscsi->initiator_password );
  405. assert ( iscsi->target_username );
  406. assert ( iscsi->target_password );
  407. target->chap_type = IBFT_CHAP_MUTUAL;
  408. if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
  409. iscsi->target_username ) ) != 0 )
  410. return rc;
  411. DBG ( "iBFT target %d reverse username = %s\n", target->header.index,
  412. ibft_string ( strings, &target->chap_name ) );
  413. if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
  414. iscsi->target_password ) ) != 0 )
  415. return rc;
  416. DBG ( "iBFT target %d reverse password = <redacted>\n",
  417. target->header.index );
  418. return 0;
  419. }
  420. /**
  421. * Fill in Target portion of iBFT
  422. *
  423. * @v target Target portion of iBFT
  424. * @v strings iBFT string block descriptor
  425. * @v iscsi iSCSI session
  426. * @ret rc Return status code
  427. */
  428. static int ibft_fill_target ( struct ibft_target *target,
  429. struct ibft_strings *strings,
  430. struct iscsi_session *iscsi ) {
  431. struct sockaddr_tcpip *st_target =
  432. ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr;
  433. struct sockaddr_in *sin_target =
  434. ( struct sockaddr_in * ) &iscsi->target_sockaddr;
  435. int rc;
  436. /* Fill in common header */
  437. target->header.structure_id = IBFT_STRUCTURE_ID_TARGET;
  438. target->header.version = 1;
  439. target->header.length = cpu_to_le16 ( sizeof ( *target ) );
  440. target->header.flags = ( IBFT_FL_TARGET_BLOCK_VALID |
  441. IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED );
  442. /* Fill in Target values */
  443. ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
  444. DBG ( "iBFT target %d IP = %s\n",
  445. target->header.index, ibft_ipaddr ( &target->ip_address ) );
  446. target->socket = cpu_to_le16 ( ntohs ( st_target->st_port ) );
  447. DBG ( "iBFT target %d port = %d\n",
  448. target->header.index, target->socket );
  449. memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) );
  450. DBG ( "iBFT target %d boot LUN = " SCSI_LUN_FORMAT "\n",
  451. target->header.index, SCSI_LUN_DATA ( target->boot_lun ) );
  452. if ( ( rc = ibft_set_string ( strings, &target->target_name,
  453. iscsi->target_iqn ) ) != 0 )
  454. return rc;
  455. DBG ( "iBFT target %d name = %s\n", target->header.index,
  456. ibft_string ( strings, &target->target_name ) );
  457. if ( ( rc = ibft_fill_target_nic_association ( target, iscsi ) ) != 0 )
  458. return rc;
  459. if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
  460. return rc;
  461. if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
  462. iscsi ) ) != 0 )
  463. return rc;
  464. return 0;
  465. }
  466. /**
  467. * Check if iBFT descriptor is complete
  468. *
  469. * @v desc ACPI descriptor
  470. * @ret rc Return status code
  471. */
  472. static int ibft_complete ( struct acpi_descriptor *desc ) {
  473. struct iscsi_session *iscsi =
  474. container_of ( desc, struct iscsi_session, desc );
  475. /* Fail if we do not yet have the target address */
  476. if ( ! iscsi->target_sockaddr.sa_family )
  477. return -EAGAIN;
  478. return 0;
  479. }
  480. /**
  481. * Install iBFT
  482. *
  483. * @v install Installation method
  484. * @ret rc Return status code
  485. */
  486. static int ibft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
  487. struct net_device *netdev;
  488. struct iscsi_session *iscsi;
  489. struct ibft_table *table;
  490. struct ibft_initiator *initiator;
  491. struct ibft_nic *nic;
  492. struct ibft_target *target;
  493. struct ibft_strings strings;
  494. struct acpi_header *acpi;
  495. void *data;
  496. unsigned int targets = 0;
  497. unsigned int pairs = 0;
  498. size_t offset = 0;
  499. size_t table_len;
  500. size_t control_len;
  501. size_t initiator_offset;
  502. size_t nic_offset;
  503. size_t target_offset;
  504. size_t strings_offset;
  505. size_t len;
  506. unsigned int i;
  507. int rc;
  508. /* Calculate table sizes and offsets */
  509. list_for_each_entry ( iscsi, &ibft_model.descs, desc.list )
  510. targets++;
  511. pairs = ( sizeof ( table->control.pair ) /
  512. sizeof ( table->control.pair[0] ) );
  513. if ( pairs < targets )
  514. pairs = targets;
  515. offset = offsetof ( typeof ( *table ), control.pair );
  516. offset += ( pairs * sizeof ( table->control.pair[0] ) );
  517. table_len = offset;
  518. control_len = ( table_len - offsetof ( typeof ( *table ), control ) );
  519. offset = ibft_align ( offset );
  520. initiator_offset = offset;
  521. offset += ibft_align ( sizeof ( *initiator ) );
  522. nic_offset = offset;
  523. offset += ( pairs * ibft_align ( sizeof ( *nic ) ) );
  524. target_offset = offset;
  525. offset += ( pairs * ibft_align ( sizeof ( *target ) ) );
  526. strings_offset = offset;
  527. strings.data = NULL;
  528. strings.start = strings_offset;
  529. strings.len = 0;
  530. len = offset;
  531. /* Do nothing if no targets exist */
  532. if ( ! targets ) {
  533. rc = 0;
  534. goto no_targets;
  535. }
  536. /* Allocate table */
  537. data = zalloc ( len );
  538. if ( ! data ) {
  539. rc = -ENOMEM;
  540. goto err_alloc;
  541. }
  542. /* Fill in Control block */
  543. table = data;
  544. table->control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL;
  545. table->control.header.version = 1;
  546. table->control.header.length = cpu_to_le16 ( control_len );
  547. /* Fill in Initiator block */
  548. initiator = ( data + initiator_offset );
  549. table->control.initiator = cpu_to_le16 ( initiator_offset );
  550. iscsi = list_first_entry ( &ibft_model.descs, struct iscsi_session,
  551. desc.list );
  552. if ( ( rc = ibft_fill_initiator ( initiator, &strings,
  553. iscsi->initiator_iqn ) ) != 0 )
  554. goto err_initiator;
  555. /* Fill in NIC blocks */
  556. i = 0;
  557. for_each_netdev ( netdev ) {
  558. if ( ! ibft_netdev_is_required ( netdev ) )
  559. continue;
  560. assert ( i < pairs );
  561. table->control.pair[i].nic = nic_offset;
  562. nic = ( data + nic_offset );
  563. nic->header.index = i;
  564. if ( ( rc = ibft_fill_nic ( nic, &strings, netdev ) ) != 0 )
  565. goto err_nic;
  566. i++;
  567. nic_offset += ibft_align ( sizeof ( *nic ) );
  568. }
  569. /* Fill in Target blocks */
  570. i = 0;
  571. list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) {
  572. assert ( i < pairs );
  573. table->control.pair[i].target = target_offset;
  574. target = ( data + target_offset );
  575. target->header.index = i;
  576. if ( ( rc = ibft_fill_target ( target, &strings, iscsi ) ) != 0)
  577. goto err_target;
  578. i++;
  579. target_offset += ibft_align ( sizeof ( *target ) );
  580. }
  581. /* Reallocate table to include space for strings */
  582. len += strings.len;
  583. acpi = realloc ( data, len );
  584. if ( ! acpi )
  585. goto err_realloc;
  586. data = NULL;
  587. /* Fill in ACPI header */
  588. acpi->signature = cpu_to_le32 ( IBFT_SIG );
  589. acpi->length = cpu_to_le32 ( len );
  590. acpi->revision = 1;
  591. /* Append strings */
  592. memcpy ( ( ( ( void * ) acpi ) + strings_offset ), strings.data,
  593. strings.len );
  594. /* Install ACPI table */
  595. if ( ( rc = install ( acpi ) ) != 0 ) {
  596. DBG ( "iBFT could not install: %s\n", strerror ( rc ) );
  597. goto err_install;
  598. }
  599. err_install:
  600. free ( acpi );
  601. err_realloc:
  602. err_target:
  603. err_nic:
  604. err_initiator:
  605. free ( data );
  606. err_alloc:
  607. no_targets:
  608. free ( strings.data );
  609. return rc;
  610. }
  611. /** iBFT model */
  612. struct acpi_model ibft_model __acpi_model = {
  613. .descs = LIST_HEAD_INIT ( ibft_model.descs ),
  614. .complete = ibft_complete,
  615. .install = ibft_install,
  616. };