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 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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/sanboot.h>
  40. /**
  41. * Timeout for block device commands (in ticks)
  42. *
  43. * Underlying devices should ideally never become totally stuck.
  44. * However, if they do, then the blocking SAN APIs provide no means
  45. * for the caller to cancel the operation, and the machine appears to
  46. * hang. Use an overall timeout for all commands to avoid this
  47. * problem and bounce timeout failures to the caller.
  48. */
  49. #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
  50. /** List of SAN devices */
  51. LIST_HEAD ( san_devices );
  52. /**
  53. * Find SAN device by drive number
  54. *
  55. * @v drive Drive number
  56. * @ret sandev SAN device, or NULL
  57. */
  58. struct san_device * sandev_find ( unsigned int drive ) {
  59. struct san_device *sandev;
  60. list_for_each_entry ( sandev, &san_devices, list ) {
  61. if ( sandev->drive == drive )
  62. return sandev;
  63. }
  64. return NULL;
  65. }
  66. /**
  67. * Free SAN device
  68. *
  69. * @v refcnt Reference count
  70. */
  71. static void sandev_free ( struct refcnt *refcnt ) {
  72. struct san_device *sandev =
  73. container_of ( refcnt, struct san_device, refcnt );
  74. assert ( ! timer_running ( &sandev->timer ) );
  75. uri_put ( sandev->uri );
  76. free ( sandev );
  77. }
  78. /**
  79. * Close SAN device command
  80. *
  81. * @v sandev SAN device
  82. * @v rc Reason for close
  83. */
  84. static void sandev_command_close ( struct san_device *sandev, int rc ) {
  85. /* Stop timer */
  86. stop_timer ( &sandev->timer );
  87. /* Restart interface */
  88. intf_restart ( &sandev->command, rc );
  89. /* Record command status */
  90. sandev->command_rc = rc;
  91. }
  92. /**
  93. * Record SAN device capacity
  94. *
  95. * @v sandev SAN device
  96. * @v capacity SAN device capacity
  97. */
  98. static void sandev_command_capacity ( struct san_device *sandev,
  99. struct block_device_capacity *capacity ) {
  100. /* Record raw capacity information */
  101. memcpy ( &sandev->capacity, capacity, sizeof ( sandev->capacity ) );
  102. }
  103. /** SAN device command interface operations */
  104. static struct interface_operation sandev_command_op[] = {
  105. INTF_OP ( intf_close, struct san_device *, sandev_command_close ),
  106. INTF_OP ( block_capacity, struct san_device *,
  107. sandev_command_capacity ),
  108. };
  109. /** SAN device command interface descriptor */
  110. static struct interface_descriptor sandev_command_desc =
  111. INTF_DESC ( struct san_device, command, sandev_command_op );
  112. /**
  113. * Handle SAN device command timeout
  114. *
  115. * @v retry Retry timer
  116. */
  117. static void sandev_command_expired ( struct retry_timer *timer,
  118. int over __unused ) {
  119. struct san_device *sandev =
  120. container_of ( timer, struct san_device, timer );
  121. sandev_command_close ( sandev, -ETIMEDOUT );
  122. }
  123. /**
  124. * Restart SAN device interface
  125. *
  126. * @v sandev SAN device
  127. * @v rc Reason for restart
  128. */
  129. static void sandev_restart ( struct san_device *sandev, int rc ) {
  130. /* Restart block device interface */
  131. intf_nullify ( &sandev->command ); /* avoid potential loops */
  132. intf_restart ( &sandev->block, rc );
  133. /* Close any outstanding command */
  134. sandev_command_close ( sandev, rc );
  135. /* Record device error */
  136. sandev->block_rc = rc;
  137. }
  138. /**
  139. * (Re)open SAN device
  140. *
  141. * @v sandev SAN device
  142. * @ret rc Return status code
  143. *
  144. * This function will block until the device is available.
  145. */
  146. int sandev_reopen ( struct san_device *sandev ) {
  147. int rc;
  148. /* Close any outstanding command and restart interface */
  149. sandev_restart ( sandev, -ECONNRESET );
  150. /* Mark device as being not yet open */
  151. sandev->block_rc = -EINPROGRESS;
  152. /* Open block device interface */
  153. if ( ( rc = xfer_open_uri ( &sandev->block, sandev->uri ) ) != 0 ) {
  154. DBGC ( sandev, "SAN %#02x could not (re)open URI: %s\n",
  155. sandev->drive, strerror ( rc ) );
  156. return rc;
  157. }
  158. /* Wait for device to become available */
  159. while ( sandev->block_rc == -EINPROGRESS ) {
  160. step();
  161. if ( xfer_window ( &sandev->block ) != 0 ) {
  162. sandev->block_rc = 0;
  163. return 0;
  164. }
  165. }
  166. DBGC ( sandev, "SAN %#02x never became available: %s\n",
  167. sandev->drive, strerror ( sandev->block_rc ) );
  168. return sandev->block_rc;
  169. }
  170. /**
  171. * Handle closure of underlying block device interface
  172. *
  173. * @v sandev SAN device
  174. * @ret rc Reason for close
  175. */
  176. static void sandev_block_close ( struct san_device *sandev, int rc ) {
  177. /* Any closure is an error from our point of view */
  178. if ( rc == 0 )
  179. rc = -ENOTCONN;
  180. DBGC ( sandev, "SAN %#02x went away: %s\n",
  181. sandev->drive, strerror ( rc ) );
  182. /* Close any outstanding command and restart interface */
  183. sandev_restart ( sandev, rc );
  184. }
  185. /**
  186. * Check SAN device flow control window
  187. *
  188. * @v sandev SAN device
  189. */
  190. static size_t sandev_block_window ( struct san_device *sandev __unused ) {
  191. /* We are never ready to receive data via this interface.
  192. * This prevents objects that support both block and stream
  193. * interfaces from attempting to send us stream data.
  194. */
  195. return 0;
  196. }
  197. /** SAN device block interface operations */
  198. static struct interface_operation sandev_block_op[] = {
  199. INTF_OP ( intf_close, struct san_device *, sandev_block_close ),
  200. INTF_OP ( xfer_window, struct san_device *, sandev_block_window ),
  201. };
  202. /** SAN device block interface descriptor */
  203. static struct interface_descriptor sandev_block_desc =
  204. INTF_DESC ( struct san_device, block, sandev_block_op );
  205. /** SAN device read/write command parameters */
  206. struct san_command_rw_params {
  207. /** SAN device read/write operation */
  208. int ( * block_rw ) ( struct interface *control, struct interface *data,
  209. uint64_t lba, unsigned int count,
  210. userptr_t buffer, size_t len );
  211. /** Data buffer */
  212. userptr_t buffer;
  213. /** Starting LBA */
  214. uint64_t lba;
  215. /** Block count */
  216. unsigned int count;
  217. };
  218. /** SAN device command parameters */
  219. union san_command_params {
  220. /** Read/write command parameters */
  221. struct san_command_rw_params rw;
  222. };
  223. /**
  224. * Initiate SAN device read/write command
  225. *
  226. * @v sandev SAN device
  227. * @v params Command parameters
  228. * @ret rc Return status code
  229. */
  230. static int sandev_command_rw ( struct san_device *sandev,
  231. const union san_command_params *params ) {
  232. size_t len = ( params->rw.count * sandev->capacity.blksize );
  233. int rc;
  234. /* Initiate read/write command */
  235. if ( ( rc = params->rw.block_rw ( &sandev->block, &sandev->command,
  236. params->rw.lba, params->rw.count,
  237. params->rw.buffer, len ) ) != 0 ) {
  238. DBGC ( sandev, "SAN %#02x could not initiate read/write: "
  239. "%s\n", sandev->drive, strerror ( rc ) );
  240. return rc;
  241. }
  242. return 0;
  243. }
  244. /**
  245. * Initiate SAN device read capacity command
  246. *
  247. * @v sandev SAN device
  248. * @v params Command parameters
  249. * @ret rc Return status code
  250. */
  251. static int
  252. sandev_command_read_capacity ( struct san_device *sandev,
  253. const union san_command_params *params __unused){
  254. int rc;
  255. /* Initiate read capacity command */
  256. if ( ( rc = block_read_capacity ( &sandev->block,
  257. &sandev->command ) ) != 0 ) {
  258. DBGC ( sandev, "SAN %#02x could not initiate read capacity: "
  259. "%s\n", sandev->drive, strerror ( rc ) );
  260. return rc;
  261. }
  262. return 0;
  263. }
  264. /**
  265. * Execute a single SAN device command and wait for completion
  266. *
  267. * @v sandev SAN device
  268. * @v command Command
  269. * @v params Command parameters (if required)
  270. * @ret rc Return status code
  271. */
  272. static int
  273. sandev_command ( struct san_device *sandev,
  274. int ( * command ) ( struct san_device *sandev,
  275. const union san_command_params *params ),
  276. const union san_command_params *params ) {
  277. int rc;
  278. /* Sanity check */
  279. assert ( ! timer_running ( &sandev->timer ) );
  280. /* Reopen block device if applicable */
  281. if ( sandev_needs_reopen ( sandev ) &&
  282. ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
  283. goto err_reopen;
  284. }
  285. /* Start expiry timer */
  286. start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
  287. /* Initiate command */
  288. if ( ( rc = command ( sandev, params ) ) != 0 )
  289. goto err_op;
  290. /* Wait for command to complete */
  291. while ( timer_running ( &sandev->timer ) )
  292. step();
  293. /* Collect return status */
  294. rc = sandev->command_rc;
  295. return rc;
  296. err_op:
  297. stop_timer ( &sandev->timer );
  298. err_reopen:
  299. return rc;
  300. }
  301. /**
  302. * Reset SAN device
  303. *
  304. * @v sandev SAN device
  305. * @ret rc Return status code
  306. */
  307. int sandev_reset ( struct san_device *sandev ) {
  308. int rc;
  309. DBGC ( sandev, "SAN %#02x reset\n", sandev->drive );
  310. /* Close and reopen underlying block device */
  311. if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
  312. return rc;
  313. return 0;
  314. }
  315. /**
  316. * Read from or write to SAN device
  317. *
  318. * @v sandev SAN device
  319. * @v lba Starting logical block address
  320. * @v count Number of logical blocks
  321. * @v buffer Data buffer
  322. * @v block_rw Block read/write method
  323. * @ret rc Return status code
  324. */
  325. int sandev_rw ( struct san_device *sandev, uint64_t lba,
  326. unsigned int count, userptr_t buffer,
  327. int ( * block_rw ) ( struct interface *control,
  328. struct interface *data,
  329. uint64_t lba, unsigned int count,
  330. userptr_t buffer, size_t len ) ) {
  331. union san_command_params params;
  332. unsigned int remaining;
  333. size_t frag_len;
  334. int rc;
  335. /* Initialise command parameters */
  336. params.rw.block_rw = block_rw;
  337. params.rw.buffer = buffer;
  338. params.rw.lba = ( lba << sandev->blksize_shift );
  339. params.rw.count = sandev->capacity.max_count;
  340. remaining = ( count << sandev->blksize_shift );
  341. /* Read/write fragments */
  342. while ( remaining ) {
  343. /* Determine fragment length */
  344. if ( params.rw.count > remaining )
  345. params.rw.count = remaining;
  346. /* Execute command */
  347. if ( ( rc = sandev_command ( sandev, sandev_command_rw,
  348. &params ) ) != 0 )
  349. return rc;
  350. /* Move to next fragment */
  351. frag_len = ( sandev->capacity.blksize * params.rw.count );
  352. params.rw.buffer = userptr_add ( params.rw.buffer, frag_len );
  353. params.rw.lba += params.rw.count;
  354. remaining -= params.rw.count;
  355. }
  356. return 0;
  357. }
  358. /**
  359. * Configure SAN device as a CD-ROM, if applicable
  360. *
  361. * @v sandev SAN device
  362. * @ret rc Return status code
  363. *
  364. * Both BIOS and UEFI require SAN devices to be accessed with a block
  365. * size of 2048. While we could require the user to configure the
  366. * block size appropriately, this is non-trivial and would impose a
  367. * substantial learning effort on the user. Instead, we check for the
  368. * presence of the ISO9660 primary volume descriptor and, if found,
  369. * then we force a block size of 2048 and map read/write requests
  370. * appropriately.
  371. */
  372. static int sandev_parse_iso9660 ( struct san_device *sandev ) {
  373. static const struct iso9660_primary_descriptor_fixed primary_check = {
  374. .type = ISO9660_TYPE_PRIMARY,
  375. .id = ISO9660_ID,
  376. };
  377. struct iso9660_primary_descriptor *primary;
  378. unsigned int blksize;
  379. unsigned int blksize_shift;
  380. unsigned int lba;
  381. unsigned int count;
  382. int rc;
  383. /* Calculate required blocksize shift for potential CD-ROM access */
  384. blksize = sandev->capacity.blksize;
  385. blksize_shift = 0;
  386. while ( blksize < ISO9660_BLKSIZE ) {
  387. blksize <<= 1;
  388. blksize_shift++;
  389. }
  390. if ( blksize > ISO9660_BLKSIZE ) {
  391. /* Cannot be a CD-ROM. This is not an error. */
  392. rc = 0;
  393. goto invalid_blksize;
  394. }
  395. lba = ( ISO9660_PRIMARY_LBA << blksize_shift );
  396. count = ( 1 << blksize_shift );
  397. /* Allocate scratch area */
  398. primary = malloc ( ISO9660_BLKSIZE );
  399. if ( ! primary ) {
  400. rc = -ENOMEM;
  401. goto err_alloc;
  402. }
  403. /* Read primary volume descriptor */
  404. if ( ( rc = sandev_rw ( sandev, lba, count, virt_to_user ( primary ),
  405. block_read ) ) != 0 ) {
  406. DBGC ( sandev, "SAN %#02x could not read ISO9660 primary"
  407. "volume descriptor: %s\n",
  408. sandev->drive, strerror ( rc ) );
  409. goto err_rw;
  410. }
  411. /* Configure as CD-ROM if applicable */
  412. if ( memcmp ( primary, &primary_check, sizeof ( primary_check ) ) == 0){
  413. DBGC ( sandev, "SAN %#02x contains an ISO9660 filesystem; "
  414. "treating as CD-ROM\n", sandev->drive );
  415. sandev->blksize_shift = blksize_shift;
  416. sandev->is_cdrom = 1;
  417. }
  418. err_rw:
  419. free ( primary );
  420. err_alloc:
  421. invalid_blksize:
  422. return rc;
  423. }
  424. /**
  425. * Allocate SAN device
  426. *
  427. * @ret sandev SAN device, or NULL
  428. */
  429. struct san_device * alloc_sandev ( struct uri *uri, size_t priv_size ) {
  430. struct san_device *sandev;
  431. /* Allocate and initialise structure */
  432. sandev = zalloc ( sizeof ( *sandev ) + priv_size );
  433. if ( ! sandev )
  434. return NULL;
  435. ref_init ( &sandev->refcnt, sandev_free );
  436. sandev->uri = uri_get ( uri );
  437. intf_init ( &sandev->block, &sandev_block_desc, &sandev->refcnt );
  438. sandev->block_rc = -EINPROGRESS;
  439. intf_init ( &sandev->command, &sandev_command_desc, &sandev->refcnt );
  440. timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
  441. sandev->priv = ( ( ( void * ) sandev ) + sizeof ( *sandev ) );
  442. return sandev;
  443. }
  444. /**
  445. * Register SAN device
  446. *
  447. * @v sandev SAN device
  448. * @ret rc Return status code
  449. */
  450. int register_sandev ( struct san_device *sandev ) {
  451. int rc;
  452. /* Check that drive number is not in use */
  453. if ( sandev_find ( sandev->drive ) != NULL ) {
  454. DBGC ( sandev, "SAN %#02x is already in use\n", sandev->drive );
  455. return -EADDRINUSE;
  456. }
  457. /* Read device capacity */
  458. if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
  459. NULL ) ) != 0 )
  460. return rc;
  461. /* Configure as a CD-ROM, if applicable */
  462. if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 )
  463. return rc;
  464. /* Add to list of SAN devices */
  465. list_add_tail ( &sandev->list, &san_devices );
  466. return 0;
  467. }
  468. /**
  469. * Unregister SAN device
  470. *
  471. * @v sandev SAN device
  472. */
  473. void unregister_sandev ( struct san_device *sandev ) {
  474. /* Sanity check */
  475. assert ( ! timer_running ( &sandev->timer ) );
  476. /* Shut down interfaces */
  477. intfs_shutdown ( 0, &sandev->block, &sandev->command, NULL );
  478. /* Remove from list of SAN devices */
  479. list_del ( &sandev->list );
  480. }