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.

sanboot.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. /**
  25. * @file
  26. *
  27. * SAN booting
  28. *
  29. */
  30. #include <stdint.h>
  31. #include <stdlib.h>
  32. #include <errno.h>
  33. #include <assert.h>
  34. #include <ipxe/xfer.h>
  35. #include <ipxe/open.h>
  36. #include <ipxe/timer.h>
  37. #include <ipxe/process.h>
  38. #include <ipxe/iso9660.h>
  39. #include <ipxe/dhcp.h>
  40. #include <ipxe/settings.h>
  41. #include <ipxe/sanboot.h>
  42. /**
  43. * Default SAN drive number
  44. *
  45. * The drive number is a meaningful concept only in a BIOS
  46. * environment, where it represents the INT13 drive number (0x80 for
  47. * the first hard disk). We retain it in other environments to allow
  48. * for a simple way for iPXE commands to refer to SAN drives.
  49. */
  50. #define SAN_DEFAULT_DRIVE 0x80
  51. /**
  52. * Timeout for block device commands (in ticks)
  53. *
  54. * Underlying devices should ideally never become totally stuck.
  55. * However, if they do, then the blocking SAN APIs provide no means
  56. * for the caller to cancel the operation, and the machine appears to
  57. * hang. Use an overall timeout for all commands to avoid this
  58. * problem and bounce timeout failures to the caller.
  59. */
  60. #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
  61. /**
  62. * Default number of times to retry commands
  63. *
  64. * We may need to retry commands. For example, the underlying
  65. * connection may be closed by the SAN target due to an inactivity
  66. * timeout, or the SAN target may return pointless "error" messages
  67. * such as "SCSI power-on occurred".
  68. */
  69. #define SAN_DEFAULT_RETRIES 10
  70. /**
  71. * Delay between reopening attempts
  72. *
  73. * Some SAN targets will always accept connections instantly and
  74. * report a temporary unavailability by e.g. failing the TEST UNIT
  75. * READY command. Avoid bombarding such targets by introducing a
  76. * small delay between attempts.
  77. */
  78. #define SAN_REOPEN_DELAY_SECS 5
  79. /** List of SAN devices */
  80. LIST_HEAD ( san_devices );
  81. /** Number of times to retry commands */
  82. static unsigned long san_retries = SAN_DEFAULT_RETRIES;
  83. /**
  84. * Find SAN device by drive number
  85. *
  86. * @v drive Drive number
  87. * @ret sandev SAN device, or NULL
  88. */
  89. struct san_device * sandev_find ( unsigned int drive ) {
  90. struct san_device *sandev;
  91. list_for_each_entry ( sandev, &san_devices, list ) {
  92. if ( sandev->drive == drive )
  93. return sandev;
  94. }
  95. return NULL;
  96. }
  97. /**
  98. * Free SAN device
  99. *
  100. * @v refcnt Reference count
  101. */
  102. static void sandev_free ( struct refcnt *refcnt ) {
  103. struct san_device *sandev =
  104. container_of ( refcnt, struct san_device, refcnt );
  105. unsigned int i;
  106. assert ( ! timer_running ( &sandev->timer ) );
  107. assert ( ! sandev->active );
  108. assert ( list_empty ( &sandev->opened ) );
  109. for ( i = 0 ; i < sandev->paths ; i++ )
  110. uri_put ( sandev->path[i].uri );
  111. free ( sandev );
  112. }
  113. /**
  114. * Close SAN device command
  115. *
  116. * @v sandev SAN device
  117. * @v rc Reason for close
  118. */
  119. static void sandev_command_close ( struct san_device *sandev, int rc ) {
  120. /* Stop timer */
  121. stop_timer ( &sandev->timer );
  122. /* Restart interface */
  123. intf_restart ( &sandev->command, rc );
  124. /* Record command status */
  125. sandev->command_rc = rc;
  126. }
  127. /**
  128. * Record SAN device capacity
  129. *
  130. * @v sandev SAN device
  131. * @v capacity SAN device capacity
  132. */
  133. static void sandev_command_capacity ( struct san_device *sandev,
  134. struct block_device_capacity *capacity ) {
  135. /* Record raw capacity information */
  136. memcpy ( &sandev->capacity, capacity, sizeof ( sandev->capacity ) );
  137. }
  138. /** SAN device command interface operations */
  139. static struct interface_operation sandev_command_op[] = {
  140. INTF_OP ( intf_close, struct san_device *, sandev_command_close ),
  141. INTF_OP ( block_capacity, struct san_device *,
  142. sandev_command_capacity ),
  143. };
  144. /** SAN device command interface descriptor */
  145. static struct interface_descriptor sandev_command_desc =
  146. INTF_DESC ( struct san_device, command, sandev_command_op );
  147. /**
  148. * Handle SAN device command timeout
  149. *
  150. * @v retry Retry timer
  151. */
  152. static void sandev_command_expired ( struct retry_timer *timer,
  153. int over __unused ) {
  154. struct san_device *sandev =
  155. container_of ( timer, struct san_device, timer );
  156. sandev_command_close ( sandev, -ETIMEDOUT );
  157. }
  158. /**
  159. * Open SAN path
  160. *
  161. * @v sanpath SAN path
  162. * @ret rc Return status code
  163. */
  164. static int sanpath_open ( struct san_path *sanpath ) {
  165. struct san_device *sandev = sanpath->sandev;
  166. int rc;
  167. /* Sanity check */
  168. list_check_contains_entry ( sanpath, &sandev->closed, list );
  169. /* Open interface */
  170. if ( ( rc = xfer_open_uri ( &sanpath->block, sanpath->uri ) ) != 0 ) {
  171. DBGC ( sandev, "SAN %#02x.%d could not (re)open URI: "
  172. "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
  173. return rc;
  174. }
  175. /* Start process */
  176. process_add ( &sanpath->process );
  177. /* Mark as opened */
  178. list_del ( &sanpath->list );
  179. list_add_tail ( &sanpath->list, &sandev->opened );
  180. /* Record as in progress */
  181. sanpath->path_rc = -EINPROGRESS;
  182. return 0;
  183. }
  184. /**
  185. * Close SAN path
  186. *
  187. * @v sanpath SAN path
  188. * @v rc Reason for close
  189. */
  190. static void sanpath_close ( struct san_path *sanpath, int rc ) {
  191. struct san_device *sandev = sanpath->sandev;
  192. /* Record status */
  193. sanpath->path_rc = rc;
  194. /* Mark as closed */
  195. list_del ( &sanpath->list );
  196. list_add_tail ( &sanpath->list, &sandev->closed );
  197. /* Stop process */
  198. process_del ( &sanpath->process );
  199. /* Restart interfaces, avoiding potential loops */
  200. if ( sanpath == sandev->active ) {
  201. intfs_restart ( rc, &sandev->command, &sanpath->block, NULL );
  202. sandev->active = NULL;
  203. sandev_command_close ( sandev, rc );
  204. } else {
  205. intf_restart ( &sanpath->block, rc );
  206. }
  207. }
  208. /**
  209. * Handle closure of underlying block device interface
  210. *
  211. * @v sanpath SAN path
  212. * @v rc Reason for close
  213. */
  214. static void sanpath_block_close ( struct san_path *sanpath, int rc ) {
  215. struct san_device *sandev = sanpath->sandev;
  216. /* Any closure is an error from our point of view */
  217. if ( rc == 0 )
  218. rc = -ENOTCONN;
  219. DBGC ( sandev, "SAN %#02x.%d closed: %s\n",
  220. sandev->drive, sanpath->index, strerror ( rc ) );
  221. /* Close path */
  222. sanpath_close ( sanpath, rc );
  223. }
  224. /**
  225. * Check flow control window
  226. *
  227. * @v sanpath SAN path
  228. */
  229. static size_t sanpath_block_window ( struct san_path *sanpath __unused ) {
  230. /* We are never ready to receive data via this interface.
  231. * This prevents objects that support both block and stream
  232. * interfaces from attempting to send us stream data.
  233. */
  234. return 0;
  235. }
  236. /**
  237. * SAN path process
  238. *
  239. * @v sanpath SAN path
  240. */
  241. static void sanpath_step ( struct san_path *sanpath ) {
  242. struct san_device *sandev = sanpath->sandev;
  243. /* Ignore if we are already the active device */
  244. if ( sanpath == sandev->active )
  245. return;
  246. /* Wait until path has become available */
  247. if ( ! xfer_window ( &sanpath->block ) )
  248. return;
  249. /* Record status */
  250. sanpath->path_rc = 0;
  251. /* Mark as active path or close as applicable */
  252. if ( ! sandev->active ) {
  253. DBGC ( sandev, "SAN %#02x.%d is active\n",
  254. sandev->drive, sanpath->index );
  255. sandev->active = sanpath;
  256. } else {
  257. DBGC ( sandev, "SAN %#02x.%d is available\n",
  258. sandev->drive, sanpath->index );
  259. sanpath_close ( sanpath, 0 );
  260. }
  261. }
  262. /** SAN path block interface operations */
  263. static struct interface_operation sanpath_block_op[] = {
  264. INTF_OP ( intf_close, struct san_path *, sanpath_block_close ),
  265. INTF_OP ( xfer_window, struct san_path *, sanpath_block_window ),
  266. INTF_OP ( xfer_window_changed, struct san_path *, sanpath_step ),
  267. };
  268. /** SAN path block interface descriptor */
  269. static struct interface_descriptor sanpath_block_desc =
  270. INTF_DESC ( struct san_path, block, sanpath_block_op );
  271. /** SAN path process descriptor */
  272. static struct process_descriptor sanpath_process_desc =
  273. PROC_DESC_ONCE ( struct san_path, process, sanpath_step );
  274. /**
  275. * Restart SAN device interface
  276. *
  277. * @v sandev SAN device
  278. * @v rc Reason for restart
  279. */
  280. static void sandev_restart ( struct san_device *sandev, int rc ) {
  281. struct san_path *sanpath;
  282. /* Restart all block device interfaces */
  283. while ( ( sanpath = list_first_entry ( &sandev->opened,
  284. struct san_path, list ) ) ) {
  285. sanpath_close ( sanpath, rc );
  286. }
  287. /* Clear active path */
  288. sandev->active = NULL;
  289. /* Close any outstanding command */
  290. sandev_command_close ( sandev, rc );
  291. }
  292. /**
  293. * (Re)open SAN device
  294. *
  295. * @v sandev SAN device
  296. * @ret rc Return status code
  297. *
  298. * This function will block until the device is available.
  299. */
  300. int sandev_reopen ( struct san_device *sandev ) {
  301. struct san_path *sanpath;
  302. int rc;
  303. /* Close any outstanding command and restart interfaces */
  304. sandev_restart ( sandev, -ECONNRESET );
  305. assert ( sandev->active == NULL );
  306. assert ( list_empty ( &sandev->opened ) );
  307. /* Open all paths */
  308. while ( ( sanpath = list_first_entry ( &sandev->closed,
  309. struct san_path, list ) ) ) {
  310. if ( ( rc = sanpath_open ( sanpath ) ) != 0 )
  311. goto err_open;
  312. }
  313. /* Wait for any device to become available, or for all devices
  314. * to fail.
  315. */
  316. while ( sandev->active == NULL ) {
  317. step();
  318. if ( list_empty ( &sandev->opened ) ) {
  319. /* Get status of the first device to be
  320. * closed. Do this on the basis that earlier
  321. * errors (e.g. "invalid IQN") are probably
  322. * more interesting than later errors
  323. * (e.g. "TCP timeout").
  324. */
  325. rc = -ENODEV;
  326. list_for_each_entry ( sanpath, &sandev->closed, list ) {
  327. rc = sanpath->path_rc;
  328. break;
  329. }
  330. DBGC ( sandev, "SAN %#02x never became available: %s\n",
  331. sandev->drive, strerror ( rc ) );
  332. goto err_none;
  333. }
  334. }
  335. assert ( ! list_empty ( &sandev->opened ) );
  336. return 0;
  337. err_none:
  338. err_open:
  339. sandev_restart ( sandev, rc );
  340. return rc;
  341. }
  342. /** SAN device read/write command parameters */
  343. struct san_command_rw_params {
  344. /** SAN device read/write operation */
  345. int ( * block_rw ) ( struct interface *control, struct interface *data,
  346. uint64_t lba, unsigned int count,
  347. userptr_t buffer, size_t len );
  348. /** Data buffer */
  349. userptr_t buffer;
  350. /** Starting LBA */
  351. uint64_t lba;
  352. /** Block count */
  353. unsigned int count;
  354. };
  355. /** SAN device command parameters */
  356. union san_command_params {
  357. /** Read/write command parameters */
  358. struct san_command_rw_params rw;
  359. };
  360. /**
  361. * Initiate SAN device read/write command
  362. *
  363. * @v sandev SAN device
  364. * @v params Command parameters
  365. * @ret rc Return status code
  366. */
  367. static int sandev_command_rw ( struct san_device *sandev,
  368. const union san_command_params *params ) {
  369. struct san_path *sanpath = sandev->active;
  370. size_t len = ( params->rw.count * sandev->capacity.blksize );
  371. int rc;
  372. /* Sanity check */
  373. assert ( sanpath != NULL );
  374. /* Initiate read/write command */
  375. if ( ( rc = params->rw.block_rw ( &sanpath->block, &sandev->command,
  376. params->rw.lba, params->rw.count,
  377. params->rw.buffer, len ) ) != 0 ) {
  378. DBGC ( sandev, "SAN %#02x.%d could not initiate read/write: "
  379. "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
  380. return rc;
  381. }
  382. return 0;
  383. }
  384. /**
  385. * Initiate SAN device read capacity command
  386. *
  387. * @v sandev SAN device
  388. * @v params Command parameters
  389. * @ret rc Return status code
  390. */
  391. static int
  392. sandev_command_read_capacity ( struct san_device *sandev,
  393. const union san_command_params *params __unused){
  394. struct san_path *sanpath = sandev->active;
  395. int rc;
  396. /* Sanity check */
  397. assert ( sanpath != NULL );
  398. /* Initiate read capacity command */
  399. if ( ( rc = block_read_capacity ( &sanpath->block,
  400. &sandev->command ) ) != 0 ) {
  401. DBGC ( sandev, "SAN %#02x.%d could not initiate read capacity: "
  402. "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
  403. return rc;
  404. }
  405. return 0;
  406. }
  407. /**
  408. * Execute a single SAN device command and wait for completion
  409. *
  410. * @v sandev SAN device
  411. * @v command Command
  412. * @v params Command parameters (if required)
  413. * @ret rc Return status code
  414. */
  415. static int
  416. sandev_command ( struct san_device *sandev,
  417. int ( * command ) ( struct san_device *sandev,
  418. const union san_command_params *params ),
  419. const union san_command_params *params ) {
  420. unsigned int retries = 0;
  421. int rc;
  422. /* Sanity check */
  423. assert ( ! timer_running ( &sandev->timer ) );
  424. /* (Re)try command */
  425. do {
  426. /* Reopen block device if applicable */
  427. if ( sandev_needs_reopen ( sandev ) &&
  428. ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
  429. /* Delay reopening attempts */
  430. sleep_fixed ( SAN_REOPEN_DELAY_SECS );
  431. /* Retry opening indefinitely for multipath devices */
  432. if ( sandev->paths <= 1 )
  433. retries++;
  434. continue;
  435. }
  436. /* Initiate command */
  437. if ( ( rc = command ( sandev, params ) ) != 0 ) {
  438. retries++;
  439. continue;
  440. }
  441. /* Start expiry timer */
  442. start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
  443. /* Wait for command to complete */
  444. while ( timer_running ( &sandev->timer ) )
  445. step();
  446. /* Check command status */
  447. if ( ( rc = sandev->command_rc ) != 0 ) {
  448. retries++;
  449. continue;
  450. }
  451. return 0;
  452. } while ( retries <= san_retries );
  453. /* Sanity check */
  454. assert ( ! timer_running ( &sandev->timer ) );
  455. return rc;
  456. }
  457. /**
  458. * Reset SAN device
  459. *
  460. * @v sandev SAN device
  461. * @ret rc Return status code
  462. */
  463. int sandev_reset ( struct san_device *sandev ) {
  464. int rc;
  465. DBGC ( sandev, "SAN %#02x reset\n", sandev->drive );
  466. /* Close and reopen underlying block device */
  467. if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
  468. return rc;
  469. return 0;
  470. }
  471. /**
  472. * Read from or write to SAN device
  473. *
  474. * @v sandev SAN device
  475. * @v lba Starting logical block address
  476. * @v count Number of logical blocks
  477. * @v buffer Data buffer
  478. * @v block_rw Block read/write method
  479. * @ret rc Return status code
  480. */
  481. int sandev_rw ( struct san_device *sandev, uint64_t lba,
  482. unsigned int count, userptr_t buffer,
  483. int ( * block_rw ) ( struct interface *control,
  484. struct interface *data,
  485. uint64_t lba, unsigned int count,
  486. userptr_t buffer, size_t len ) ) {
  487. union san_command_params params;
  488. unsigned int remaining;
  489. size_t frag_len;
  490. int rc;
  491. /* Initialise command parameters */
  492. params.rw.block_rw = block_rw;
  493. params.rw.buffer = buffer;
  494. params.rw.lba = ( lba << sandev->blksize_shift );
  495. params.rw.count = sandev->capacity.max_count;
  496. remaining = ( count << sandev->blksize_shift );
  497. /* Read/write fragments */
  498. while ( remaining ) {
  499. /* Determine fragment length */
  500. if ( params.rw.count > remaining )
  501. params.rw.count = remaining;
  502. /* Execute command */
  503. if ( ( rc = sandev_command ( sandev, sandev_command_rw,
  504. &params ) ) != 0 )
  505. return rc;
  506. /* Move to next fragment */
  507. frag_len = ( sandev->capacity.blksize * params.rw.count );
  508. params.rw.buffer = userptr_add ( params.rw.buffer, frag_len );
  509. params.rw.lba += params.rw.count;
  510. remaining -= params.rw.count;
  511. }
  512. return 0;
  513. }
  514. /**
  515. * Configure SAN device as a CD-ROM, if applicable
  516. *
  517. * @v sandev SAN device
  518. * @ret rc Return status code
  519. *
  520. * Both BIOS and UEFI require SAN devices to be accessed with a block
  521. * size of 2048. While we could require the user to configure the
  522. * block size appropriately, this is non-trivial and would impose a
  523. * substantial learning effort on the user. Instead, we check for the
  524. * presence of the ISO9660 primary volume descriptor and, if found,
  525. * then we force a block size of 2048 and map read/write requests
  526. * appropriately.
  527. */
  528. static int sandev_parse_iso9660 ( struct san_device *sandev ) {
  529. static const struct iso9660_primary_descriptor_fixed primary_check = {
  530. .type = ISO9660_TYPE_PRIMARY,
  531. .id = ISO9660_ID,
  532. };
  533. union {
  534. struct iso9660_primary_descriptor primary;
  535. char bytes[ISO9660_BLKSIZE];
  536. } *scratch;
  537. unsigned int blksize;
  538. unsigned int blksize_shift;
  539. unsigned int lba;
  540. unsigned int count;
  541. int rc;
  542. /* Calculate required blocksize shift for potential CD-ROM access */
  543. blksize = sandev->capacity.blksize;
  544. blksize_shift = 0;
  545. while ( blksize < ISO9660_BLKSIZE ) {
  546. blksize <<= 1;
  547. blksize_shift++;
  548. }
  549. if ( blksize > ISO9660_BLKSIZE ) {
  550. /* Cannot be a CD-ROM. This is not an error. */
  551. rc = 0;
  552. goto invalid_blksize;
  553. }
  554. lba = ( ISO9660_PRIMARY_LBA << blksize_shift );
  555. count = ( 1 << blksize_shift );
  556. /* Allocate scratch area */
  557. scratch = malloc ( ISO9660_BLKSIZE );
  558. if ( ! scratch ) {
  559. rc = -ENOMEM;
  560. goto err_alloc;
  561. }
  562. /* Read primary volume descriptor */
  563. if ( ( rc = sandev_rw ( sandev, lba, count, virt_to_user ( scratch ),
  564. block_read ) ) != 0 ) {
  565. DBGC ( sandev, "SAN %#02x could not read ISO9660 primary"
  566. "volume descriptor: %s\n",
  567. sandev->drive, strerror ( rc ) );
  568. goto err_rw;
  569. }
  570. /* Configure as CD-ROM if applicable */
  571. if ( memcmp ( &scratch->primary.fixed, &primary_check,
  572. sizeof ( primary_check ) ) == 0 ) {
  573. DBGC ( sandev, "SAN %#02x contains an ISO9660 filesystem; "
  574. "treating as CD-ROM\n", sandev->drive );
  575. sandev->blksize_shift = blksize_shift;
  576. sandev->is_cdrom = 1;
  577. }
  578. err_rw:
  579. free ( scratch );
  580. err_alloc:
  581. invalid_blksize:
  582. return rc;
  583. }
  584. /**
  585. * Allocate SAN device
  586. *
  587. * @v uris List of URIs
  588. * @v count Number of URIs
  589. * @v priv_size Size of private data
  590. * @ret sandev SAN device, or NULL
  591. */
  592. struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
  593. size_t priv_size ) {
  594. struct san_device *sandev;
  595. struct san_path *sanpath;
  596. size_t size;
  597. unsigned int i;
  598. /* Allocate and initialise structure */
  599. size = ( sizeof ( *sandev ) + ( count * sizeof ( sandev->path[0] ) ) );
  600. sandev = zalloc ( size + priv_size );
  601. if ( ! sandev )
  602. return NULL;
  603. ref_init ( &sandev->refcnt, sandev_free );
  604. intf_init ( &sandev->command, &sandev_command_desc, &sandev->refcnt );
  605. timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
  606. sandev->priv = ( ( ( void * ) sandev ) + size );
  607. sandev->paths = count;
  608. INIT_LIST_HEAD ( &sandev->opened );
  609. INIT_LIST_HEAD ( &sandev->closed );
  610. for ( i = 0 ; i < count ; i++ ) {
  611. sanpath = &sandev->path[i];
  612. sanpath->sandev = sandev;
  613. sanpath->index = i;
  614. sanpath->uri = uri_get ( uris[i] );
  615. list_add_tail ( &sanpath->list, &sandev->closed );
  616. intf_init ( &sanpath->block, &sanpath_block_desc,
  617. &sandev->refcnt );
  618. process_init_stopped ( &sanpath->process, &sanpath_process_desc,
  619. &sandev->refcnt );
  620. sanpath->path_rc = -EINPROGRESS;
  621. }
  622. return sandev;
  623. }
  624. /**
  625. * Register SAN device
  626. *
  627. * @v sandev SAN device
  628. * @ret rc Return status code
  629. */
  630. int register_sandev ( struct san_device *sandev ) {
  631. int rc;
  632. /* Check that drive number is not in use */
  633. if ( sandev_find ( sandev->drive ) != NULL ) {
  634. DBGC ( sandev, "SAN %#02x is already in use\n", sandev->drive );
  635. rc = -EADDRINUSE;
  636. goto err_in_use;
  637. }
  638. /* Check that device is capable of being opened (i.e. that all
  639. * URIs are well-formed and that at least one path is
  640. * working).
  641. */
  642. if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
  643. goto err_reopen;
  644. /* Read device capacity */
  645. if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
  646. NULL ) ) != 0 )
  647. goto err_capacity;
  648. /* Configure as a CD-ROM, if applicable */
  649. if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 )
  650. goto err_iso9660;
  651. /* Add to list of SAN devices */
  652. list_add_tail ( &sandev->list, &san_devices );
  653. DBGC ( sandev, "SAN %#02x registered\n", sandev->drive );
  654. return 0;
  655. list_del ( &sandev->list );
  656. err_iso9660:
  657. err_capacity:
  658. err_reopen:
  659. sandev_restart ( sandev, rc );
  660. err_in_use:
  661. return rc;
  662. }
  663. /**
  664. * Unregister SAN device
  665. *
  666. * @v sandev SAN device
  667. */
  668. void unregister_sandev ( struct san_device *sandev ) {
  669. /* Sanity check */
  670. assert ( ! timer_running ( &sandev->timer ) );
  671. /* Remove from list of SAN devices */
  672. list_del ( &sandev->list );
  673. /* Shut down interfaces */
  674. sandev_restart ( sandev, 0 );
  675. DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
  676. }
  677. /** The "san-drive" setting */
  678. const struct setting san_drive_setting __setting ( SETTING_SANBOOT_EXTRA,
  679. san-drive ) = {
  680. .name = "san-drive",
  681. .description = "SAN drive number",
  682. .tag = DHCP_EB_SAN_DRIVE,
  683. .type = &setting_type_uint8,
  684. };
  685. /**
  686. * Get default SAN drive number
  687. *
  688. * @ret drive Default drive number
  689. */
  690. unsigned int san_default_drive ( void ) {
  691. unsigned long drive;
  692. /* Use "san-drive" setting, if specified */
  693. if ( fetch_uint_setting ( NULL, &san_drive_setting, &drive ) >= 0 )
  694. return drive;
  695. /* Otherwise, default to booting from first hard disk */
  696. return SAN_DEFAULT_DRIVE;
  697. }
  698. /** The "san-retries" setting */
  699. const struct setting san_retries_setting __setting ( SETTING_SANBOOT_EXTRA,
  700. san-retries ) = {
  701. .name = "san-retries",
  702. .description = "SAN retry count",
  703. .tag = DHCP_EB_SAN_RETRY,
  704. .type = &setting_type_int8,
  705. };
  706. /**
  707. * Apply SAN boot settings
  708. *
  709. * @ret rc Return status code
  710. */
  711. static int sandev_apply ( void ) {
  712. /* Apply "san-retries" setting */
  713. if ( fetch_uint_setting ( NULL, &san_retries_setting,
  714. &san_retries ) < 0 ) {
  715. san_retries = SAN_DEFAULT_RETRIES;
  716. }
  717. return 0;
  718. }
  719. /** Settings applicator */
  720. struct settings_applicator sandev_applicator __settings_applicator = {
  721. .apply = sandev_apply,
  722. };