iPXE
usbblk.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 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 (at your option) 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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <ipxe/usb.h>
30 #include <ipxe/scsi.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/uri.h>
33 #include <ipxe/open.h>
34 #include <ipxe/efi/efi_path.h>
35 #include "usbblk.h"
36 
37 /** @file
38  *
39  * USB mass storage driver
40  *
41  */
42 
43 static void usbblk_stop ( struct usbblk_device *usbblk, int rc );
44 
45 /** List of USB block devices */
46 static LIST_HEAD ( usbblk_devices );
47 
48 /******************************************************************************
49  *
50  * Endpoint management
51  *
52  ******************************************************************************
53  */
54 
55 /**
56  * Open endpoints
57  *
58  * @v usbblk USB block device
59  * @ret rc Return status code
60  */
61 static int usbblk_open ( struct usbblk_device *usbblk ) {
62  struct usb_device *usb = usbblk->func->usb;
63  unsigned int interface = usbblk->func->interface[0];
64  int rc;
65 
66  /* Sanity checks */
67  assert ( ! usbblk->in.open );
68  assert ( ! usbblk->out.open );
69 
70  /* Issue reset */
71  if ( ( rc = usb_control ( usb, USBBLK_RESET, 0, interface,
72  NULL, 0 ) ) != 0 ) {
73  DBGC ( usbblk, "USBBLK %s could not issue reset: %s\n",
74  usbblk->func->name, strerror ( rc ) );
75  goto err_reset;
76  }
77 
78  /* Open bulk OUT endpoint */
79  if ( ( rc = usb_endpoint_open ( &usbblk->out ) ) != 0 ) {
80  DBGC ( usbblk, "USBBLK %s could not open bulk OUT: %s\n",
81  usbblk->func->name, strerror ( rc ) );
82  goto err_open_out;
83  }
84 
85  /* Clear any bulk OUT halt condition */
86  if ( ( rc = usb_endpoint_clear_halt ( &usbblk->out ) ) != 0 ) {
87  DBGC ( usbblk, "USBBLK %s could not reset bulk OUT: %s\n",
88  usbblk->func->name, strerror ( rc ) );
89  goto err_clear_out;
90  }
91 
92  /* Open bulk IN endpoint */
93  if ( ( rc = usb_endpoint_open ( &usbblk->in ) ) != 0 ) {
94  DBGC ( usbblk, "USBBLK %s could not open bulk IN: %s\n",
95  usbblk->func->name, strerror ( rc ) );
96  goto err_open_in;
97  }
98 
99  /* Clear any bulk IN halt condition */
100  if ( ( rc = usb_endpoint_clear_halt ( &usbblk->in ) ) != 0 ) {
101  DBGC ( usbblk, "USBBLK %s could not reset bulk IN: %s\n",
102  usbblk->func->name, strerror ( rc ) );
103  goto err_clear_in;
104  }
105 
106  return 0;
107 
108  err_clear_in:
109  usb_endpoint_close ( &usbblk->in );
110  err_open_in:
111  err_clear_out:
112  usb_endpoint_close ( &usbblk->out );
113  err_open_out:
114  err_reset:
115  return rc;
116 }
117 
118 /**
119  * Close endpoints
120  *
121  * @v usbblk USB block device
122  */
123 static void usbblk_close ( struct usbblk_device *usbblk ) {
124 
125  /* Close bulk OUT endpoint */
126  if ( usbblk->out.open )
127  usb_endpoint_close ( &usbblk->out );
128 
129  /* Close bulk IN endpoint */
130  if ( usbblk->in.open )
131  usb_endpoint_close ( &usbblk->in );
132 }
133 
134 /******************************************************************************
135  *
136  * Bulk OUT endpoint
137  *
138  ******************************************************************************
139  */
140 
141 /**
142  * Issue bulk OUT command
143  *
144  * @v usbblk USB block device
145  * @ret rc Return status code
146  */
147 static int usbblk_out_command ( struct usbblk_device *usbblk ) {
148  struct usbblk_command *cmd = &usbblk->cmd;
149  struct usbblk_command_wrapper *wrapper;
150  struct io_buffer *iobuf;
151  int rc;
152 
153  /* Sanity checks */
154  assert ( cmd->tag );
155  assert ( ! ( cmd->scsi.data_in_len && cmd->scsi.data_out_len ) );
156 
157  /* Allocate I/O buffer */
158  iobuf = alloc_iob ( sizeof ( *wrapper ) );
159  if ( ! iobuf ) {
160  rc = -ENOMEM;
161  goto err_alloc;
162  }
163 
164  /* Populate command */
165  wrapper = iob_put ( iobuf, sizeof ( *wrapper ) );
166  memset ( wrapper, 0, sizeof ( *wrapper ) );
168  wrapper->tag = cmd->tag; /* non-endian */
169  if ( cmd->scsi.data_out_len ) {
170  wrapper->len = cpu_to_le32 ( cmd->scsi.data_out_len );
171  } else {
172  wrapper->len = cpu_to_le32 ( cmd->scsi.data_in_len );
173  wrapper->flags = USB_DIR_IN;
174  }
175  wrapper->lun = ntohs ( cmd->scsi.lun.u16[0] );
176  wrapper->cblen = sizeof ( wrapper->cb );
177  memcpy ( wrapper->cb, &cmd->scsi.cdb, sizeof ( wrapper->cb ) );
178 
179  /* Issue command */
180  if ( ( rc = usb_stream ( &usbblk->out, iobuf, 0 ) ) != 0 ) {
181  DBGC ( usbblk, "USBBLK %s bulk OUT could not issue command: "
182  "%s\n", usbblk->func->name, strerror ( rc ) );
183  goto err_stream;
184  }
185 
186  return 0;
187 
188  err_stream:
189  free_iob ( iobuf );
190  err_alloc:
191  return rc;
192 }
193 
194 /**
195  * Send bulk OUT data block
196  *
197  * @v usbblk USB block device
198  * @ret rc Return status code
199  */
200 static int usbblk_out_data ( struct usbblk_device *usbblk ) {
201  struct usbblk_command *cmd = &usbblk->cmd;
202  struct io_buffer *iobuf;
203  size_t len;
204  int rc;
205 
206  /* Calculate length */
207  assert ( cmd->tag );
208  assert ( cmd->scsi.data_out != UNULL );
209  assert ( cmd->offset < cmd->scsi.data_out_len );
210  len = ( cmd->scsi.data_out_len - cmd->offset );
211  if ( len > USBBLK_MAX_LEN )
213  assert ( ( len % usbblk->out.mtu ) == 0 );
214 
215  /* Allocate I/O buffer */
216  iobuf = alloc_iob ( len );
217  if ( ! iobuf ) {
218  rc = -ENOMEM;
219  goto err_alloc;
220  }
221 
222  /* Populate I/O buffer */
223  copy_from_user ( iob_put ( iobuf, len ), cmd->scsi.data_out,
224  cmd->offset, len );
225 
226  /* Send data */
227  if ( ( rc = usb_stream ( &usbblk->out, iobuf, 0 ) ) != 0 ) {
228  DBGC ( usbblk, "USBBLK %s bulk OUT could not send data: %s\n",
229  usbblk->func->name, strerror ( rc ) );
230  goto err_stream;
231  }
232 
233  /* Consume data */
234  cmd->offset += len;
235 
236  return 0;
237 
238  err_stream:
239  free_iob ( iobuf );
240  err_alloc:
241  return rc;
242 }
243 
244 /**
245  * Refill bulk OUT endpoint
246  *
247  * @v usbblk USB block device
248  * @ret rc Return status code
249  */
250 static int usbblk_out_refill ( struct usbblk_device *usbblk ) {
251  struct usbblk_command *cmd = &usbblk->cmd;
252  int rc;
253 
254  /* Sanity checks */
255  assert ( cmd->tag );
256 
257  /* Refill endpoint */
258  while ( ( cmd->offset < cmd->scsi.data_out_len ) &&
259  ( usbblk->out.fill < USBBLK_MAX_FILL ) ) {
260  if ( ( rc = usbblk_out_data ( usbblk ) ) != 0 )
261  return rc;
262  }
263 
264  return 0;
265 }
266 
267 /**
268  * Complete bulk OUT transfer
269  *
270  * @v ep USB endpoint
271  * @v iobuf I/O buffer
272  * @v rc Completion status code
273  */
274 static void usbblk_out_complete ( struct usb_endpoint *ep,
275  struct io_buffer *iobuf, int rc ) {
276  struct usbblk_device *usbblk =
277  container_of ( ep, struct usbblk_device, out );
278  struct usbblk_command *cmd = &usbblk->cmd;
279 
280  /* Ignore cancellations after closing endpoint */
281  if ( ! ep->open )
282  goto drop;
283 
284  /* Sanity check */
285  assert ( cmd->tag );
286 
287  /* Check for failures */
288  if ( rc != 0 ) {
289  DBGC ( usbblk, "USBBLK %s bulk OUT failed: %s\n",
290  usbblk->func->name, strerror ( rc ) );
291  goto err;
292  }
293 
294  /* Trigger refill process, if applicable */
295  if ( cmd->offset < cmd->scsi.data_out_len )
296  process_add ( &usbblk->process );
297 
298  drop:
299  /* Free I/O buffer */
300  free_iob ( iobuf );
301 
302  return;
303 
304  err:
305  free_iob ( iobuf );
306  usbblk_stop ( usbblk, rc );
307 }
308 
309 /** Bulk OUT endpoint operations */
312 };
313 
314 /******************************************************************************
315  *
316  * Bulk IN endpoint
317  *
318  ******************************************************************************
319  */
320 
321 /**
322  * Handle bulk IN data block
323  *
324  * @v usbblk USB block device
325  * @v data Data block
326  * @v len Length of data
327  * @ret rc Return status code
328  */
329 static int usbblk_in_data ( struct usbblk_device *usbblk, const void *data,
330  size_t len ) {
331  struct usbblk_command *cmd = &usbblk->cmd;
332 
333  /* Sanity checks */
334  assert ( cmd->tag );
335  assert ( cmd->scsi.data_in != UNULL );
336  assert ( cmd->offset <= cmd->scsi.data_in_len );
337  assert ( len <= ( cmd->scsi.data_in_len - cmd->offset ) );
338 
339  /* Store data */
340  copy_to_user ( cmd->scsi.data_in, cmd->offset, data, len );
341  cmd->offset += len;
342 
343  return 0;
344 }
345 
346 /**
347  * Handle bulk IN status
348  *
349  * @v usbblk USB block device
350  * @v data Status data
351  * @v len Length of status data
352  * @ret rc Return status code
353  */
354 static int usbblk_in_status ( struct usbblk_device *usbblk, const void *data,
355  size_t len ) {
356  struct usbblk_command *cmd = &usbblk->cmd;
357  const struct usbblk_status_wrapper *stat;
358 
359  /* Sanity checks */
360  assert ( cmd->tag );
361 
362  /* Validate length */
363  if ( len < sizeof ( *stat ) ) {
364  DBGC ( usbblk, "USBBLK %s bulk IN malformed status:\n",
365  usbblk->func->name );
366  DBGC_HDA ( usbblk, 0, data, len );
367  return -EIO;
368  }
369  stat = data;
370 
371  /* Validate signature */
372  if ( stat->signature != cpu_to_le32 ( USBBLK_STATUS_SIGNATURE ) ) {
373  DBGC ( usbblk, "USBBLK %s bulk IN invalid signature %08x:\n",
374  usbblk->func->name, le32_to_cpu ( stat->signature ) );
375  DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
376  return -EIO;
377  }
378 
379  /* Validate tag */
380  if ( stat->tag != cmd->tag ) {
381  DBGC ( usbblk, "USBBLK %s bulk IN tag mismatch (got %08x, "
382  "expected %08x):\n",
383  usbblk->func->name, stat->tag, cmd->tag );
384  DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
385  return -EIO;
386  }
387 
388  /* Check status */
389  if ( stat->status ) {
390  DBGC ( usbblk, "USBBLK %s bulk IN status %02x:\n",
391  usbblk->func->name, stat->status );
392  DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
393  return -EIO;
394  }
395 
396  /* Check for residual data */
397  if ( stat->residue ) {
398  DBGC ( usbblk, "USBBLK %s bulk IN residue %#x:\n",
399  usbblk->func->name, le32_to_cpu ( stat->residue ) );
400  return -EIO;
401  }
402 
403  /* Mark command as complete */
404  usbblk_stop ( usbblk, 0 );
405 
406  return 0;
407 }
408 
409 /**
410  * Refill bulk IN endpoint
411  *
412  * @v usbblk USB block device
413  * @ret rc Return status code
414  */
415 static int usbblk_in_refill ( struct usbblk_device *usbblk ) {
416  struct usbblk_command *cmd = &usbblk->cmd;
417  struct usbblk_status_wrapper *stat;
418  size_t remaining;
419  unsigned int max;
420  int rc;
421 
422  /* Sanity checks */
423  assert ( cmd->tag );
424 
425  /* Calculate maximum required refill */
426  remaining = sizeof ( *stat );
427  if ( cmd->scsi.data_in_len ) {
428  assert ( cmd->offset <= cmd->scsi.data_in_len );
429  remaining += ( cmd->scsi.data_in_len - cmd->offset );
430  }
431  max = ( ( remaining + USBBLK_MAX_LEN - 1 ) / USBBLK_MAX_LEN );
432 
433  /* Refill bulk IN endpoint */
434  if ( ( rc = usb_refill_limit ( &usbblk->in, max ) ) != 0 )
435  return rc;
436 
437  return 0;
438 }
439 
440 /**
441  * Complete bulk IN transfer
442  *
443  * @v ep USB endpoint
444  * @v iobuf I/O buffer
445  * @v rc Completion status code
446  */
447 static void usbblk_in_complete ( struct usb_endpoint *ep,
448  struct io_buffer *iobuf, int rc ) {
449  struct usbblk_device *usbblk =
450  container_of ( ep, struct usbblk_device, in );
451  struct usbblk_command *cmd = &usbblk->cmd;
452  size_t remaining;
453  size_t len;
454 
455  /* Ignore cancellations after closing endpoint */
456  if ( ! ep->open )
457  goto drop;
458 
459  /* Sanity check */
460  assert ( cmd->tag );
461 
462  /* Handle errors */
463  if ( rc != 0 ) {
464  DBGC ( usbblk, "USBBLK %s bulk IN failed: %s\n",
465  usbblk->func->name, strerror ( rc ) );
466  goto err;
467  }
468 
469  /* Trigger refill process */
470  process_add ( &usbblk->process );
471 
472  /* Handle data portion, if any */
473  if ( cmd->scsi.data_in_len ) {
474  assert ( cmd->offset <= cmd->scsi.data_in_len );
475  remaining = ( cmd->scsi.data_in_len - cmd->offset );
476  len = iob_len ( iobuf );
477  if ( len > remaining )
478  len = remaining;
479  if ( len ) {
480  if ( ( rc = usbblk_in_data ( usbblk, iobuf->data,
481  len ) ) != 0 )
482  goto err;
483  iob_pull ( iobuf, len );
484  }
485  }
486 
487  /* Handle status portion, if any */
488  len = iob_len ( iobuf );
489  if ( len ) {
490  if ( ( rc = usbblk_in_status ( usbblk, iobuf->data,
491  len ) ) != 0 )
492  goto err;
493  }
494 
495  drop:
496  /* Free I/O buffer */
497  free_iob ( iobuf );
498 
499  return;
500 
501  err:
502  free_iob ( iobuf );
503  usbblk_stop ( usbblk, rc );
504 }
505 
506 /** Bulk IN endpoint operations */
509 };
510 
511 /******************************************************************************
512  *
513  * Refill process
514  *
515  ******************************************************************************
516  */
517 
518 /**
519  * Refill endpoints
520  *
521  * @v usbblk USB block device
522  */
523 static void usbblk_step ( struct usbblk_device *usbblk ) {
524 
525  /* Refill bulk OUT endpoint */
526  usbblk_out_refill ( usbblk );
527 
528  /* Refill bulk IN endpoint */
529  usbblk_in_refill ( usbblk );
530 }
531 
532 /** Refill process descriptor */
535 
536 /******************************************************************************
537  *
538  * SCSI command management
539  *
540  ******************************************************************************
541  */
542 
543 /** Next command tag */
545 
546 /**
547  * Stop SCSI command
548  *
549  * @v usbblk USB block device
550  * @v rc Reason for stop
551  */
552 static void usbblk_stop ( struct usbblk_device *usbblk, int rc ) {
553 
554  /* Stop process */
555  process_del ( &usbblk->process );
556 
557  /* Reset command */
558  memset ( &usbblk->cmd, 0, sizeof ( usbblk->cmd ) );
559 
560  /* Close endpoints if an error occurred */
561  if ( rc != 0 ) {
562  DBGC ( usbblk, "USBBLK %s closing for error recovery\n",
563  usbblk->func->name );
564  usbblk_close ( usbblk );
565  }
566 
567  /* Terminate command */
568  intf_restart ( &usbblk->data, rc );
569 }
570 
571 /**
572  * Start new SCSI command
573  *
574  * @v usbblk USB block device
575  * @v scsicmd SCSI command
576  * @ret rc Return status code
577  */
578 static int usbblk_start ( struct usbblk_device *usbblk,
579  struct scsi_cmd *scsicmd ) {
580  struct usbblk_command *cmd = &usbblk->cmd;
581  int rc;
582 
583  /* Fail if command is in progress */
584  if ( cmd->tag ) {
585  rc = -EBUSY;
586  DBGC ( usbblk, "USBBLK %s cannot support multiple commands\n",
587  usbblk->func->name );
588  goto err_busy;
589  }
590 
591  /* Refuse bidirectional commands */
592  if ( scsicmd->data_in_len && scsicmd->data_out_len ) {
593  rc = -EOPNOTSUPP;
594  DBGC ( usbblk, "USBBLK %s cannot support bidirectional "
595  "commands\n", usbblk->func->name );
596  goto err_bidirectional;
597  }
598 
599  /* Sanity checks */
600  assert ( ! process_running ( &usbblk->process ) );
601  assert ( cmd->offset == 0 );
602 
603  /* Initialise command */
604  memcpy ( &cmd->scsi, scsicmd, sizeof ( cmd->scsi ) );
605  cmd->tag = ( USBBLK_TAG_MAGIC | ++usbblk_tag );
606 
607  /* Issue bulk OUT command */
608  if ( ( rc = usbblk_out_command ( usbblk ) ) != 0 )
609  goto err_command;
610 
611  /* Start refill process */
612  process_add ( &usbblk->process );
613 
614  return 0;
615 
616  err_command:
617  memset ( &usbblk->cmd, 0, sizeof ( usbblk->cmd ) );
618  err_bidirectional:
619  err_busy:
620  return rc;
621 }
622 
623 /******************************************************************************
624  *
625  * SCSI interfaces
626  *
627  ******************************************************************************
628  */
629 
630 /** SCSI data interface operations */
633 };
634 
635 /** SCSI data interface descriptor */
638 
639 /**
640  * Check SCSI command flow-control window
641  *
642  * @v usbblk USB block device
643  * @ret len Length of window
644  */
645 static size_t usbblk_scsi_window ( struct usbblk_device *usbblk ) {
646  struct usbblk_command *cmd = &usbblk->cmd;
647 
648  /* Allow a single command if no command is currently in progress */
649  return ( cmd->tag ? 0 : 1 );
650 }
651 
652 /**
653  * Issue SCSI command
654  *
655  * @v usbblk USB block device
656  * @v data SCSI data interface
657  * @v scsicmd SCSI command
658  * @ret tag Command tag, or negative error
659  */
660 static int usbblk_scsi_command ( struct usbblk_device *usbblk,
661  struct interface *data,
662  struct scsi_cmd *scsicmd ) {
663  struct usbblk_command *cmd = &usbblk->cmd;
664  int rc;
665 
666  /* (Re)open endpoints if needed */
667  if ( ( ! usbblk->in.open ) && ( ( rc = usbblk_open ( usbblk ) ) != 0 ) )
668  goto err_open;
669 
670  /* Start new command */
671  if ( ( rc = usbblk_start ( usbblk, scsicmd ) ) != 0 )
672  goto err_start;
673 
674  /* Attach to parent interface and return */
675  intf_plug_plug ( &usbblk->data, data );
676  return cmd->tag;
677 
678  usbblk_stop ( usbblk, rc );
679  err_start:
680  usbblk_close ( usbblk );
681  err_open:
682  return rc;
683 }
684 
685 /**
686  * Close SCSI interface
687  *
688  * @v usbblk USB block device
689  * @v rc Reason for close
690  */
691 static void usbblk_scsi_close ( struct usbblk_device *usbblk, int rc ) {
692 
693  /* Restart interfaces */
694  intfs_restart ( rc, &usbblk->scsi, &usbblk->data, NULL );
695 
696  /* Stop any in-progress command */
697  usbblk_stop ( usbblk, rc );
698 
699  /* Close endpoints */
700  usbblk_close ( usbblk );
701 
702  /* Flag as closed */
703  usbblk->opened = 0;
704 }
705 
706 /**
707  * Describe as an EFI device path
708  *
709  * @v usbblk USB block device
710  * @ret path EFI device path, or NULL on error
711  */
713 usbblk_efi_describe ( struct usbblk_device *usbblk ) {
714 
715  return efi_usb_path ( usbblk->func );
716 }
717 
718 /** SCSI command interface operations */
725 };
726 
727 /** SCSI command interface descriptor */
730 
731 /******************************************************************************
732  *
733  * SAN device interface
734  *
735  ******************************************************************************
736  */
737 
738 /**
739  * Find USB block device
740  *
741  * @v name USB block device name
742  * @ret usbblk USB block device, or NULL
743  */
744 static struct usbblk_device * usbblk_find ( const char *name ) {
745  struct usbblk_device *usbblk;
746 
747  /* Look for matching device */
748  list_for_each_entry ( usbblk, &usbblk_devices, list ) {
749  if ( strcmp ( usbblk->func->name, name ) == 0 )
750  return usbblk;
751  }
752 
753  return NULL;
754 }
755 
756 /**
757  * Open USB block device URI
758  *
759  * @v parent Parent interface
760  * @v uri URI
761  * @ret rc Return status code
762  */
763 static int usbblk_open_uri ( struct interface *parent, struct uri *uri ) {
764  static struct scsi_lun lun;
765  struct usbblk_device *usbblk;
766  int rc;
767 
768  /* Sanity check */
769  if ( ! uri->opaque )
770  return -EINVAL;
771 
772  /* Find matching device */
773  usbblk = usbblk_find ( uri->opaque );
774  if ( ! usbblk )
775  return -ENOENT;
776 
777  /* Fail if device is already open */
778  if ( usbblk->opened )
779  return -EBUSY;
780 
781  /* Open SCSI device */
782  if ( ( rc = scsi_open ( parent, &usbblk->scsi, &lun ) ) != 0 ) {
783  DBGC ( usbblk, "USBBLK %s could not open SCSI device: %s\n",
784  usbblk->func->name, strerror ( rc ) );
785  return rc;
786  }
787 
788  /* Mark as opened */
789  usbblk->opened = 1;
790 
791  return 0;
792 }
793 
794 /** USB block device URI opener */
795 struct uri_opener usbblk_uri_opener __uri_opener = {
796  .scheme = "usb",
797  .open = usbblk_open_uri,
798 };
799 
800 /******************************************************************************
801  *
802  * USB interface
803  *
804  ******************************************************************************
805  */
806 
807 /**
808  * Probe device
809  *
810  * @v func USB function
811  * @v config Configuration descriptor
812  * @ret rc Return status code
813  */
814 static int usbblk_probe ( struct usb_function *func,
815  struct usb_configuration_descriptor *config ) {
816  struct usb_device *usb = func->usb;
817  struct usbblk_device *usbblk;
818  struct usb_interface_descriptor *desc;
819  int rc;
820 
821  /* Allocate and initialise structure */
822  usbblk = zalloc ( sizeof ( *usbblk ) );
823  if ( ! usbblk ) {
824  rc = -ENOMEM;
825  goto err_alloc;
826  }
827  usbblk->func = func;
828  usb_endpoint_init ( &usbblk->out, usb, &usbblk_out_operations );
829  usb_endpoint_init ( &usbblk->in, usb, &usbblk_in_operations );
831  intf_init ( &usbblk->scsi, &usbblk_scsi_desc, &usbblk->refcnt );
832  intf_init ( &usbblk->data, &usbblk_data_desc, &usbblk->refcnt );
834  &usbblk->refcnt );
835 
836  /* Locate interface descriptor */
837  desc = usb_interface_descriptor ( config, func->interface[0], 0 );
838  if ( ! desc ) {
839  DBGC ( usbblk, "USBBLK %s missing interface descriptor\n",
840  usbblk->func->name );
841  rc = -ENOENT;
842  goto err_desc;
843  }
844 
845  /* Describe endpoints */
846  if ( ( rc = usb_endpoint_described ( &usbblk->out, config, desc,
847  USB_BULK_OUT, 0 ) ) != 0 ) {
848  DBGC ( usbblk, "USBBLK %s could not describe bulk OUT: %s\n",
849  usbblk->func->name, strerror ( rc ) );
850  goto err_out;
851  }
852  if ( ( rc = usb_endpoint_described ( &usbblk->in, config, desc,
853  USB_BULK_IN, 0 ) ) != 0 ) {
854  DBGC ( usbblk, "USBBLK %s could not describe bulk IN: %s\n",
855  usbblk->func->name, strerror ( rc ) );
856  goto err_in;
857  }
858 
859  /* Add to list of devices */
860  list_add_tail ( &usbblk->list, &usbblk_devices );
861 
862  usb_func_set_drvdata ( func, usbblk );
863  return 0;
864 
865  err_in:
866  err_out:
867  err_desc:
868  ref_put ( &usbblk->refcnt );
869  err_alloc:
870  return rc;
871 }
872 
873 /**
874  * Remove device
875  *
876  * @v func USB function
877  */
878 static void usbblk_remove ( struct usb_function *func ) {
879  struct usbblk_device *usbblk = usb_func_get_drvdata ( func );
880 
881  /* Remove from list of devices */
882  list_del ( &usbblk->list );
883 
884  /* Close all interfaces */
885  usbblk_scsi_close ( usbblk, -ENODEV );
886 
887  /* Shut down interfaces */
888  intfs_shutdown ( -ENODEV, &usbblk->scsi, &usbblk->data, NULL );
889 
890  /* Drop reference */
891  ref_put ( &usbblk->refcnt );
892 }
893 
894 /** Mass storage class device IDs */
895 static struct usb_device_id usbblk_ids[] = {
896  {
897  .name = "usbblk",
898  .vendor = USB_ANY_ID,
899  .product = USB_ANY_ID,
900  },
901 };
902 
903 /** Mass storage driver */
904 struct usb_driver usbblk_driver __usb_driver = {
905  .ids = usbblk_ids,
906  .id_count = ( sizeof ( usbblk_ids ) / sizeof ( usbblk_ids[0] ) ),
909  .score = USB_SCORE_NORMAL,
910  .probe = usbblk_probe,
911  .remove = usbblk_remove,
912 };
A process.
Definition: process.h:17
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
A USB driver.
Definition: usb.h:1381
#define EINVAL
Invalid argument.
Definition: errno.h:428
An object interface operation.
Definition: interface.h:17
struct usb_endpoint out
Bulk OUT endpoint.
Definition: usbblk.h:86
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
struct usbblk_command cmd
Current command (if any)
Definition: usbblk.h:100
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
A USB device ID.
Definition: usb.h:1335
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:337
#define USBBLK_MAX_FILL
Maximum endpoint fill level.
Definition: usbblk.h:119
struct process process
Command process.
Definition: usbblk.h:95
A USB mass storage command.
Definition: usbblk.h:67
#define iob_put(iobuf, len)
Definition: iobuf.h:120
static int usbblk_in_data(struct usbblk_device *usbblk, const void *data, size_t len)
Handle bulk IN data block.
Definition: usbblk.c:329
void(* complete)(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete transfer.
Definition: usb.h:481
size_t data_out_len
Data-out buffer length.
Definition: scsi.h:260
static void * usb_func_get_drvdata(struct usb_function *func)
Get USB function driver private data.
Definition: usb.h:703
#define EBUSY
Device or resource busy.
Definition: errno.h:338
#define max(x, y)
Definition: ath.h:39
uint8_t interface[0]
List of interface numbers.
Definition: usb.h:682
uint8_t cb[16]
Command block.
Definition: usbblk.h:45
const char * name
Name.
Definition: usb.h:661
__be32 in[4]
Definition: CIB_PRM.h:35
#define le32_to_cpu(value)
Definition: byteswap.h:113
const char * name
Name.
Definition: usb.h:1337
static int usbblk_start(struct usbblk_device *usbblk, struct scsi_cmd *scsicmd)
Start new SCSI command.
Definition: usbblk.c:578
int usb_refill_limit(struct usb_endpoint *ep, unsigned int max)
Refill endpoint up to specified limit.
Definition: usb.c:660
Error codes.
static int usbblk_out_data(struct usbblk_device *usbblk)
Send bulk OUT data block.
Definition: usbblk.c:200
USB mass storage driver.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define USB_PROTOCOL_MSC_BULK
Bulk-only transport protocol.
Definition: usbblk.h:24
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
uint8_t cblen
Command block length.
Definition: usbblk.h:43
size_t data_in_len
Data-in buffer length.
Definition: scsi.h:267
#define DBGC(...)
Definition: compiler.h:505
Command block wrapper.
Definition: usbblk.h:31
A process descriptor.
Definition: process.h:31
static struct usb_endpoint_driver_operations usbblk_in_operations
Bulk IN endpoint operations.
Definition: usbblk.c:507
#define ENOENT
No such file or directory.
Definition: errno.h:514
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:102
int usb_endpoint_clear_halt(struct usb_endpoint *ep)
Clear endpoint halt (if applicable)
Definition: usb.c:371
int usb_stream(struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate)
Enqueue USB stream transfer.
Definition: usb.c:545
int usb_endpoint_open(struct usb_endpoint *ep)
Open USB endpoint.
Definition: usb.c:293
static int usbblk_open_uri(struct interface *parent, struct uri *uri)
Open USB block device URI.
Definition: usbblk.c:763
static int usbblk_in_refill(struct usbblk_device *usbblk)
Refill bulk IN endpoint.
Definition: usbblk.c:415
struct usb_driver usbblk_driver __usb_driver
Mass storage driver.
Definition: usbblk.c:904
#define ntohs(value)
Definition: byteswap.h:136
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:51
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition: interface.c:320
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
Definition: scsi.c:980
Uniform Resource Identifiers.
void usb_endpoint_close(struct usb_endpoint *ep)
Close USB endpoint.
Definition: usb.c:399
int open
Endpoint is open.
Definition: usb.h:404
int usb_endpoint_described(struct usb_endpoint *ep, struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index)
Describe USB endpoint from device configuration.
Definition: usb.c:241
void process_del(struct process *process)
Remove process from process list.
Definition: process.c:79
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:129
uint32_t signature
Signature.
Definition: usbblk.h:33
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:115
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition: interface.c:380
int usb_control(struct usb_device *usb, unsigned int request, unsigned int value, unsigned int index, void *data, size_t len)
Issue USB control transaction.
Definition: usb.c:783
Data transfer interfaces.
static void usbblk_stop(struct usbblk_device *usbblk, int rc)
Stop SCSI command.
Definition: usbblk.c:552
static void usbblk_scsi_close(struct usbblk_device *usbblk, int rc)
Close SCSI interface.
Definition: usbblk.c:691
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
static uint16_t usbblk_tag
Next command tag.
Definition: usbblk.c:544
#define ENOMEM
Not enough space.
Definition: errno.h:534
A USB endpoint.
Definition: usb.h:389
void * memcpy(void *dest, const void *src, size_t len) __nonnull
A USB interface descriptor.
Definition: usb.h:230
struct refcnt refcnt
Reference count.
Definition: usbblk.h:79
struct interface scsi
SCSI command-issuing interface.
Definition: usbblk.h:91
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
A SCSI command.
Definition: scsi.c:262
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
An object interface.
Definition: interface.h:124
#define USBBLK_RESET
Mass storage reset command.
Definition: usbblk.h:27
uint8_t lun
LUN.
Definition: usbblk.h:41
#define USB_BULK_OUT
Bulk OUT endpoint (internal) type.
Definition: usb.h:281
A USB mass storage device.
Definition: usbblk.h:77
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#define DBGC_HDA(...)
Definition: compiler.h:506
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
static int usbblk_scsi_command(struct usbblk_device *usbblk, struct interface *data, struct scsi_cmd *scsicmd)
Issue SCSI command.
Definition: usbblk.c:660
static void usb_refill_init(struct usb_endpoint *ep, size_t reserve, size_t len, unsigned int max)
Initialise USB endpoint refill.
Definition: usb.h:602
const char * scheme
URI protocol name.
Definition: open.h:53
__be32 out[4]
Definition: CIB_PRM.h:36
static void usb_func_set_drvdata(struct usb_function *func, void *priv)
Set USB function driver private data.
Definition: usb.h:692
struct list_head list
List of devices.
Definition: usbblk.h:81
#define USB_DIR_IN
Data transfer is from device to host.
Definition: usb.h:83
uint8_t lun
Logical Unit Number.
Definition: edd.h:32
#define cpu_to_le32(value)
Definition: byteswap.h:107
A USB device.
Definition: usb.h:708
struct usb_interface_descriptor * usb_interface_descriptor(struct usb_configuration_descriptor *config, unsigned int interface, unsigned int alternate)
Locate USB interface descriptor.
Definition: usb.c:143
void process_add(struct process *process)
Add process to process list.
Definition: process.c:59
#define EFI_INTF_OP
Definition: efi.h:291
static int usbblk_open(struct usbblk_device *usbblk)
Open endpoints.
Definition: usbblk.c:61
An object interface descriptor.
Definition: interface.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define USBBLK_COMMAND_SIGNATURE
Command block wrapper signature.
Definition: usbblk.h:49
EFI_DEVICE_PATH_PROTOCOL * efi_usb_path(struct usb_function *func)
Construct EFI device path for USB function.
Definition: efi_path.c:435
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
#define USBBLK_MAX_LEN
Maximum length of USB data block.
Definition: usbblk.h:113
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
#define EOPNOTSUPP
Operation not supported on socket.
Definition: errno.h:604
#define USB_CLASS_ID(base, subclass, protocol)
Construct USB class ID.
Definition: usb.h:1363
#define USBBLK_STATUS_SIGNATURE
Command status wrapper signature.
Definition: usbblk.h:64
#define ENODEV
No such device.
Definition: errno.h:509
Normal driver.
Definition: usb.h:1427
Data transfer interface opening.
EFI device paths.
uint32_t residue
Data residue.
Definition: usbblk.h:58
static int usbblk_out_refill(struct usbblk_device *usbblk)
Refill bulk OUT endpoint.
Definition: usbblk.c:250
unsigned int fill
Buffer fill level.
Definition: usb.h:406
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition: process.h:145
struct usb_device * usb
USB device.
Definition: usb.h:663
static void usb_endpoint_init(struct usb_endpoint *ep, struct usb_device *usb, struct usb_endpoint_driver_operations *driver)
Initialise USB endpoint.
Definition: usb.h:525
static void usbblk_remove(struct usb_function *func)
Remove device.
Definition: usbblk.c:878
#define USB_SUBCLASS_MSC_SCSI
SCSI command set subclass code.
Definition: usbblk.h:21
struct usb_endpoint in
Bulk IN endpoint.
Definition: usbblk.h:88
size_t mtu
Maximum transfer size.
Definition: usb.h:397
static int process_running(struct process *process)
Check if process is running.
Definition: process.h:175
static struct interface_descriptor usbblk_data_desc
SCSI data interface descriptor.
Definition: usbblk.c:636
#define USB_BULK_IN
Bulk IN endpoint (internal) type.
Definition: usb.h:284
Command status wrapper.
Definition: usbblk.h:52
struct usb_function * func
USB function.
Definition: usbblk.h:84
uint32_t tag
Tag.
Definition: usbblk.h:35
static size_t usbblk_scsi_window(struct usbblk_device *usbblk)
Check SCSI command flow-control window.
Definition: usbblk.c:645
SCSI devices.
A SCSI command information unit.
Definition: scsi.h:249
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
A USB configuration descriptor.
Definition: usb.h:195
#define USBBLK_TAG_MAGIC
Command tag magic.
Definition: usbblk.h:107
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition: efi_path.c:491
uint32_t tag
Tag.
Definition: usbblk.h:56
#define UNULL
Equivalent of NULL for user pointers.
Definition: uaccess.h:36
uint32_t len
Length.
Definition: ena.h:14
static int usbblk_probe(struct usb_function *func, struct usb_configuration_descriptor *config)
Probe device.
Definition: usbblk.c:814
const char * opaque
Opaque part.
Definition: uri.h:56
static struct interface_descriptor usbblk_scsi_desc
SCSI command interface descriptor.
Definition: usbblk.c:728
#define USB_ANY_ID
Match-anything ID.
Definition: usb.h:1347
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:172
Universal Serial Bus (USB)
static struct interface_operation usbblk_scsi_operations[]
SCSI command interface operations.
Definition: usbblk.c:719
void * data
Start of data.
Definition: iobuf.h:48
static int usbblk_in_status(struct usbblk_device *usbblk, const void *data, size_t len)
Handle bulk IN status.
Definition: usbblk.c:354
#define PROC_DESC(object_type, process, _step)
Define a process descriptor.
Definition: process.h:82
#define EIO
Input/output error.
Definition: errno.h:433
static struct interface_operation usbblk_data_operations[]
SCSI data interface operations.
Definition: usbblk.c:631
uint8_t status
Status.
Definition: usbblk.h:60
static struct usbblk_device * usbblk_find(const char *name)
Find USB block device.
Definition: usbblk.c:744
int opened
Device opened flag.
Definition: usbblk.h:97
A Uniform Resource Identifier.
Definition: uri.h:50
static LIST_HEAD(usbblk_devices)
List of USB block devices.
A SCSI LUN.
Definition: scsi.h:236
struct uri_opener usbblk_uri_opener __uri_opener
USB block device URI opener.
Definition: usbblk.c:795
static void usbblk_step(struct usbblk_device *usbblk)
Refill endpoints.
Definition: usbblk.c:523
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define USB_CLASS_MSC
Mass storage class code.
Definition: usbblk.h:18
static void usbblk_out_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete bulk OUT transfer.
Definition: usbblk.c:274
uint32_t signature
Signature.
Definition: usbblk.h:54
USB endpoint driver operations.
Definition: usb.h:474
static void usbblk_close(struct usbblk_device *usbblk)
Close endpoints.
Definition: usbblk.c:123
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:188
A USB function.
Definition: usb.h:659
static EFI_DEVICE_PATH_PROTOCOL * usbblk_efi_describe(struct usbblk_device *usbblk)
Describe as an EFI device path.
Definition: usbblk.c:713
A URI opener.
Definition: open.h:47
uint32_t len
Data transfer length.
Definition: usbblk.h:37
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct golan_eqe_cmd cmd
Definition: CIB_PRM.h:29
static struct process_descriptor usbblk_process_desc
Refill process descriptor.
Definition: usbblk.c:533
static struct usb_endpoint_driver_operations usbblk_out_operations
Bulk OUT endpoint operations.
Definition: usbblk.c:310
static struct usb_device_id usbblk_ids[]
Mass storage class device IDs.
Definition: usbblk.c:895
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
struct interface data
SCSI data interface.
Definition: usbblk.h:93
struct usb_device_id * ids
USB ID table.
Definition: usb.h:1383
static int usbblk_out_command(struct usbblk_device *usbblk)
Issue bulk OUT command.
Definition: usbblk.c:147
void * memset(void *dest, int character, size_t len) __nonnull
uint8_t flags
Flags.
Definition: usbblk.h:39
A persistent I/O buffer.
Definition: iobuf.h:33
static void usbblk_in_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete bulk IN transfer.
Definition: usbblk.c:447