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