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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_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
45static void usbblk_stop ( struct usbblk_device *usbblk, int rc );
46
47/** List of USB block devices */
48static 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 */
63static 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 */
125static 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 */
149static 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 */
202static 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 */
252static 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 */
276static 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 */
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 */
331static 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 */
356static 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 */
417static int usbblk_in_refill ( struct usbblk_device *usbblk ) {
418 struct usbblk_command *cmd = &usbblk->cmd;
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 */
449static 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 */
512
513/******************************************************************************
514 *
515 * Refill process
516 *
517 ******************************************************************************
518 */
519
520/**
521 * Refill endpoints
522 *
523 * @v usbblk USB block device
524 */
525static 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 */
554static 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 */
580static 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 */
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 */
647static 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 */
662static 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 */
693static 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 */
716
717 return efi_usb_path ( usbblk->func );
718}
719
720/** SCSI command interface operations */
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 */
746static 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 */
765static 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 */
797struct 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 */
816static 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 */
880static 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 */
897static struct usb_device_id usbblk_ids[] = {
898 USB_ID ( 0xffff, 0xffff, "usbblk", "USB block device", 0 ),
899};
900
901/** Mass storage driver */
902struct usb_driver usbblk_driver __usb_driver = {
903 .ids = usbblk_ids,
904 .id_count = ( sizeof ( usbblk_ids ) / sizeof ( usbblk_ids[0] ) ),
907 .score = USB_SCORE_NORMAL,
908 .probe = usbblk_probe,
909 .remove = usbblk_remove,
910};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__be32 in[4]
Definition CIB_PRM.h:7
struct golan_eqe_cmd cmd
Definition CIB_PRM.h:1
__be32 out[4]
Definition CIB_PRM.h:8
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
const char * name
Definition ath9k_hw.c:1986
#define max(x, y)
Definition ath.h:41
uint32_t stat
Completion status.
Definition dwmac.h:1
ring len
Length.
Definition dwmac.h:226
uint8_t lun
Logical Unit Number.
Definition edd.h:3
EFI_DEVICE_PATH_PROTOCOL * efi_usb_path(struct usb_function *func)
Construct EFI device path for USB function.
Definition efi_path.c:697
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition efi_path.c:920
EFI device paths.
uint8_t data[48]
Additional event data.
Definition ena.h:11
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EOPNOTSUPP
Operation not supported on socket.
Definition errno.h:605
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EIO
Input/output error.
Definition errno.h:434
#define EBUSY
Device or resource busy.
Definition errno.h:339
#define ENODEV
No such device.
Definition errno.h:510
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define ntohs(value)
Definition byteswap.h:137
#define EFI_INTF_OP
Definition efi.h:374
Universal Serial Bus (USB)
#define USB_BULK_OUT
Bulk OUT endpoint (internal) type.
Definition usb.h:296
#define USB_DIR_IN
Data transfer is from device to host.
Definition usb.h:98
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
#define __usb_driver
Declare a USB driver.
Definition usb.h:1453
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
#define USB_CLASS_ID(base, subclass, protocol)
Construct USB class ID.
Definition usb.h:1401
#define USB_BULK_IN
Bulk IN endpoint (internal) type.
Definition usb.h:299
#define USB_ID(_vendor, _product, _name, _description, _data)
Definition usb.h:1373
static void usb_func_set_drvdata(struct usb_function *func, void *priv)
Set USB function driver private data.
Definition usb.h:707
@ USB_SCORE_NORMAL
Normal driver.
Definition usb.h:1465
static void * usb_func_get_drvdata(struct usb_function *func)
Get USB function driver private data.
Definition usb.h:718
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition interface.c:387
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition interface.c:327
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_pull(iobuf, len)
Definition iobuf.h:107
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Data transfer interface opening.
#define __uri_opener
Register a URI opener.
Definition open.h:68
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
static int process_running(struct process *process)
Check if process is running.
Definition process.h:176
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
#define PROC_DESC(object_type, process, _step)
Define a process descriptor.
Definition process.h:83
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
Definition scsi.c:985
SCSI devices.
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition DevicePath.h:46
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A SCSI command information unit.
Definition scsi.h:249
size_t data_out_len
Data-out buffer length.
Definition scsi.h:260
size_t data_in_len
Data-in buffer length.
Definition scsi.h:267
A SCSI command.
Definition scsi.c:263
A SCSI LUN.
Definition scsi.h:236
A URI opener.
Definition open.h:48
A Uniform Resource Identifier.
Definition uri.h:65
const char * opaque
Opaque part.
Definition uri.h:71
A USB configuration descriptor.
Definition usb.h:210
A USB device ID.
Definition usb.h:1361
A USB device.
Definition usb.h:723
A USB driver.
Definition usb.h:1419
USB endpoint driver operations.
Definition usb.h:489
A USB endpoint.
Definition usb.h:404
size_t mtu
Maximum transfer size.
Definition usb.h:412
unsigned int fill
Buffer fill level.
Definition usb.h:421
int open
Endpoint is open.
Definition usb.h:419
A USB function.
Definition usb.h:674
struct usb_device * usb
USB device.
Definition usb.h:678
uint8_t interface[0]
List of interface numbers.
Definition usb.h:697
const char * name
Name.
Definition usb.h:676
A USB interface descriptor.
Definition usb.h:245
Command block wrapper.
Definition usbblk.h:32
uint8_t lun
LUN.
Definition usbblk.h:42
uint8_t flags
Flags.
Definition usbblk.h:40
uint8_t cblen
Command block length.
Definition usbblk.h:44
uint32_t len
Data transfer length.
Definition usbblk.h:38
uint32_t tag
Tag.
Definition usbblk.h:36
uint8_t cb[16]
Command block.
Definition usbblk.h:46
uint32_t signature
Signature.
Definition usbblk.h:34
A USB mass storage command.
Definition usbblk.h:68
A USB mass storage device.
Definition usbblk.h:78
struct usb_endpoint in
Bulk IN endpoint.
Definition usbblk.h:89
struct process process
Command process.
Definition usbblk.h:96
struct usb_endpoint out
Bulk OUT endpoint.
Definition usbblk.h:87
struct refcnt refcnt
Reference count.
Definition usbblk.h:80
int opened
Device opened flag.
Definition usbblk.h:98
struct usb_function * func
USB function.
Definition usbblk.h:85
struct list_head list
List of devices.
Definition usbblk.h:82
struct usbblk_command cmd
Current command (if any)
Definition usbblk.h:101
struct interface scsi
SCSI command-issuing interface.
Definition usbblk.h:92
struct interface data
SCSI data interface.
Definition usbblk.h:94
Command status wrapper.
Definition usbblk.h:53
Uniform Resource Identifiers.
int usb_endpoint_open(struct usb_endpoint *ep)
Open USB endpoint.
Definition usb.c:294
void usb_endpoint_close(struct usb_endpoint *ep)
Close USB endpoint.
Definition usb.c:400
int usb_endpoint_clear_halt(struct usb_endpoint *ep)
Clear endpoint halt (if applicable)
Definition usb.c:372
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
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
int usb_refill_limit(struct usb_endpoint *ep, unsigned int max)
Refill endpoint up to specified limit.
Definition usb.c:661
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
int usb_stream(struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate)
Enqueue USB stream transfer.
Definition usb.c:546
static int usbblk_probe(struct usb_function *func, struct usb_configuration_descriptor *config)
Probe device.
Definition usbblk.c:816
static void usbblk_stop(struct usbblk_device *usbblk, int rc)
Stop SCSI command.
Definition usbblk.c:554
static int usbblk_scsi_command(struct usbblk_device *usbblk, struct interface *data, struct scsi_cmd *scsicmd)
Issue SCSI command.
Definition usbblk.c:662
static int usbblk_open(struct usbblk_device *usbblk)
Open endpoints.
Definition usbblk.c:63
static uint16_t usbblk_tag
Next command tag.
Definition usbblk.c:546
static void usbblk_in_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete bulk IN transfer.
Definition usbblk.c:449
static struct interface_operation usbblk_data_operations[]
SCSI data interface operations.
Definition usbblk.c:633
static void usbblk_step(struct usbblk_device *usbblk)
Refill endpoints.
Definition usbblk.c:525
static int usbblk_in_refill(struct usbblk_device *usbblk)
Refill bulk IN endpoint.
Definition usbblk.c:417
static int usbblk_in_status(struct usbblk_device *usbblk, const void *data, size_t len)
Handle bulk IN status.
Definition usbblk.c:356
static struct usb_device_id usbblk_ids[]
Mass storage class device IDs.
Definition usbblk.c:897
static struct interface_descriptor usbblk_scsi_desc
SCSI command interface descriptor.
Definition usbblk.c:730
static void usbblk_remove(struct usb_function *func)
Remove device.
Definition usbblk.c:880
static int usbblk_open_uri(struct interface *parent, struct uri *uri)
Open USB block device URI.
Definition usbblk.c:765
static struct usb_endpoint_driver_operations usbblk_in_operations
Bulk IN endpoint operations.
Definition usbblk.c:509
static size_t usbblk_scsi_window(struct usbblk_device *usbblk)
Check SCSI command flow-control window.
Definition usbblk.c:647
static void usbblk_scsi_close(struct usbblk_device *usbblk, int rc)
Close SCSI interface.
Definition usbblk.c:693
static void usbblk_out_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete bulk OUT transfer.
Definition usbblk.c:276
static int usbblk_out_data(struct usbblk_device *usbblk)
Send bulk OUT data block.
Definition usbblk.c:202
static int usbblk_start(struct usbblk_device *usbblk, struct scsi_cmd *scsicmd)
Start new SCSI command.
Definition usbblk.c:580
static EFI_DEVICE_PATH_PROTOCOL * usbblk_efi_describe(struct usbblk_device *usbblk)
Describe as an EFI device path.
Definition usbblk.c:715
static int usbblk_out_command(struct usbblk_device *usbblk)
Issue bulk OUT command.
Definition usbblk.c:149
static int usbblk_out_refill(struct usbblk_device *usbblk)
Refill bulk OUT endpoint.
Definition usbblk.c:252
static struct usb_endpoint_driver_operations usbblk_out_operations
Bulk OUT endpoint operations.
Definition usbblk.c:312
static void usbblk_close(struct usbblk_device *usbblk)
Close endpoints.
Definition usbblk.c:125
static struct process_descriptor usbblk_process_desc
Refill process descriptor.
Definition usbblk.c:535
static struct interface_descriptor usbblk_data_desc
SCSI data interface descriptor.
Definition usbblk.c:638
static struct interface_operation usbblk_scsi_operations[]
SCSI command interface operations.
Definition usbblk.c:721
static int usbblk_in_data(struct usbblk_device *usbblk, const void *data, size_t len)
Handle bulk IN data block.
Definition usbblk.c:331
static struct usbblk_device * usbblk_find(const char *name)
Find USB block device.
Definition usbblk.c:746
USB mass storage driver.
#define USBBLK_COMMAND_SIGNATURE
Command block wrapper signature.
Definition usbblk.h:50
#define USBBLK_STATUS_SIGNATURE
Command status wrapper signature.
Definition usbblk.h:65
#define USBBLK_MAX_LEN
Maximum length of USB data block.
Definition usbblk.h:114
#define USBBLK_RESET
Mass storage reset command.
Definition usbblk.h:28
#define USBBLK_MAX_FILL
Maximum endpoint fill level.
Definition usbblk.h:120
#define USB_PROTOCOL_MSC_BULK
Bulk-only transport protocol.
Definition usbblk.h:25
#define USB_CLASS_MSC
Mass storage class code.
Definition usbblk.h:19
#define USB_SUBCLASS_MSC_SCSI
SCSI command set subclass code.
Definition usbblk.h:22
#define USBBLK_TAG_MAGIC
Command tag magic.
Definition usbblk.h:108
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
Data transfer interfaces.