]> Git Repo - qemu.git/blob - hw/usb-msd.c
showing a splash picture when start
[qemu.git] / hw / usb-msd.c
1 /*
2  * USB Mass Storage Device emulation
3  *
4  * Copyright (c) 2006 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the LGPL.
8  */
9
10 #include "qemu-common.h"
11 #include "qemu-option.h"
12 #include "qemu-config.h"
13 #include "usb.h"
14 #include "usb-desc.h"
15 #include "scsi.h"
16 #include "console.h"
17 #include "monitor.h"
18 #include "sysemu.h"
19 #include "blockdev.h"
20
21 //#define DEBUG_MSD
22
23 #ifdef DEBUG_MSD
24 #define DPRINTF(fmt, ...) \
25 do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
26 #else
27 #define DPRINTF(fmt, ...) do {} while(0)
28 #endif
29
30 /* USB requests.  */
31 #define MassStorageReset  0xff
32 #define GetMaxLun         0xfe
33
34 enum USBMSDMode {
35     USB_MSDM_CBW, /* Command Block.  */
36     USB_MSDM_DATAOUT, /* Transfer data to device.  */
37     USB_MSDM_DATAIN, /* Transfer data from device.  */
38     USB_MSDM_CSW /* Command Status.  */
39 };
40
41 typedef struct {
42     USBDevice dev;
43     enum USBMSDMode mode;
44     uint32_t scsi_len;
45     uint8_t *scsi_buf;
46     uint32_t usb_len;
47     uint8_t *usb_buf;
48     uint32_t data_len;
49     uint32_t residue;
50     uint32_t tag;
51     SCSIRequest *req;
52     SCSIBus bus;
53     BlockConf conf;
54     char *serial;
55     SCSIDevice *scsi_dev;
56     uint32_t removable;
57     int result;
58     /* For async completion.  */
59     USBPacket *packet;
60 } MSDState;
61
62 struct usb_msd_cbw {
63     uint32_t sig;
64     uint32_t tag;
65     uint32_t data_len;
66     uint8_t flags;
67     uint8_t lun;
68     uint8_t cmd_len;
69     uint8_t cmd[16];
70 };
71
72 struct usb_msd_csw {
73     uint32_t sig;
74     uint32_t tag;
75     uint32_t residue;
76     uint8_t status;
77 };
78
79 enum {
80     STR_MANUFACTURER = 1,
81     STR_PRODUCT,
82     STR_SERIALNUMBER,
83     STR_CONFIG_FULL,
84     STR_CONFIG_HIGH,
85 };
86
87 static const USBDescStrings desc_strings = {
88     [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
89     [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
90     [STR_SERIALNUMBER] = "1",
91     [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
92     [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
93 };
94
95 static const USBDescIface desc_iface_full = {
96     .bInterfaceNumber              = 0,
97     .bNumEndpoints                 = 2,
98     .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
99     .bInterfaceSubClass            = 0x06, /* SCSI */
100     .bInterfaceProtocol            = 0x50, /* Bulk */
101     .eps = (USBDescEndpoint[]) {
102         {
103             .bEndpointAddress      = USB_DIR_IN | 0x01,
104             .bmAttributes          = USB_ENDPOINT_XFER_BULK,
105             .wMaxPacketSize        = 64,
106         },{
107             .bEndpointAddress      = USB_DIR_OUT | 0x02,
108             .bmAttributes          = USB_ENDPOINT_XFER_BULK,
109             .wMaxPacketSize        = 64,
110         },
111     }
112 };
113
114 static const USBDescDevice desc_device_full = {
115     .bcdUSB                        = 0x0200,
116     .bMaxPacketSize0               = 8,
117     .bNumConfigurations            = 1,
118     .confs = (USBDescConfig[]) {
119         {
120             .bNumInterfaces        = 1,
121             .bConfigurationValue   = 1,
122             .iConfiguration        = STR_CONFIG_FULL,
123             .bmAttributes          = 0xc0,
124             .nif = 1,
125             .ifs = &desc_iface_full,
126         },
127     },
128 };
129
130 static const USBDescIface desc_iface_high = {
131     .bInterfaceNumber              = 0,
132     .bNumEndpoints                 = 2,
133     .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
134     .bInterfaceSubClass            = 0x06, /* SCSI */
135     .bInterfaceProtocol            = 0x50, /* Bulk */
136     .eps = (USBDescEndpoint[]) {
137         {
138             .bEndpointAddress      = USB_DIR_IN | 0x01,
139             .bmAttributes          = USB_ENDPOINT_XFER_BULK,
140             .wMaxPacketSize        = 512,
141         },{
142             .bEndpointAddress      = USB_DIR_OUT | 0x02,
143             .bmAttributes          = USB_ENDPOINT_XFER_BULK,
144             .wMaxPacketSize        = 512,
145         },
146     }
147 };
148
149 static const USBDescDevice desc_device_high = {
150     .bcdUSB                        = 0x0200,
151     .bMaxPacketSize0               = 64,
152     .bNumConfigurations            = 1,
153     .confs = (USBDescConfig[]) {
154         {
155             .bNumInterfaces        = 1,
156             .bConfigurationValue   = 1,
157             .iConfiguration        = STR_CONFIG_HIGH,
158             .bmAttributes          = 0xc0,
159             .nif = 1,
160             .ifs = &desc_iface_high,
161         },
162     },
163 };
164
165 static const USBDesc desc = {
166     .id = {
167         .idVendor          = 0,
168         .idProduct         = 0,
169         .bcdDevice         = 0,
170         .iManufacturer     = STR_MANUFACTURER,
171         .iProduct          = STR_PRODUCT,
172         .iSerialNumber     = STR_SERIALNUMBER,
173     },
174     .full = &desc_device_full,
175     .high = &desc_device_high,
176     .str  = desc_strings,
177 };
178
179 static void usb_msd_copy_data(MSDState *s)
180 {
181     uint32_t len;
182     len = s->usb_len;
183     if (len > s->scsi_len)
184         len = s->scsi_len;
185     if (s->mode == USB_MSDM_DATAIN) {
186         memcpy(s->usb_buf, s->scsi_buf, len);
187     } else {
188         memcpy(s->scsi_buf, s->usb_buf, len);
189     }
190     s->usb_len -= len;
191     s->scsi_len -= len;
192     s->usb_buf += len;
193     s->scsi_buf += len;
194     s->data_len -= len;
195     if (s->scsi_len == 0 || s->data_len == 0) {
196         scsi_req_continue(s->req);
197     }
198 }
199
200 static void usb_msd_send_status(MSDState *s, USBPacket *p)
201 {
202     struct usb_msd_csw csw;
203     int len;
204
205     csw.sig = cpu_to_le32(0x53425355);
206     csw.tag = cpu_to_le32(s->tag);
207     csw.residue = s->residue;
208     csw.status = s->result;
209
210     len = MIN(sizeof(csw), p->len);
211     memcpy(p->data, &csw, len);
212 }
213
214 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
215 {
216     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
217     USBPacket *p = s->packet;
218
219     assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
220     s->scsi_len = len;
221     s->scsi_buf = scsi_req_get_buf(req);
222     if (p) {
223         usb_msd_copy_data(s);
224         if (s->packet && s->usb_len == 0) {
225             /* Set s->packet to NULL before calling usb_packet_complete
226                because another request may be issued before
227                usb_packet_complete returns.  */
228             DPRINTF("Packet complete %p\n", p);
229             s->packet = NULL;
230             usb_packet_complete(&s->dev, p);
231         }
232     }
233 }
234
235 static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
236 {
237     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
238     USBPacket *p = s->packet;
239
240     DPRINTF("Command complete %d\n", status);
241     s->residue = s->data_len;
242     s->result = status != 0;
243     if (s->packet) {
244         if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
245             /* A deferred packet with no write data remaining must be
246                the status read packet.  */
247             usb_msd_send_status(s, p);
248             s->mode = USB_MSDM_CBW;
249         } else {
250             if (s->data_len) {
251                 s->data_len -= s->usb_len;
252                 if (s->mode == USB_MSDM_DATAIN) {
253                     memset(s->usb_buf, 0, s->usb_len);
254                 }
255                 s->usb_len = 0;
256             }
257             if (s->data_len == 0) {
258                 s->mode = USB_MSDM_CSW;
259             }
260         }
261         s->packet = NULL;
262         usb_packet_complete(&s->dev, p);
263     } else if (s->data_len == 0) {
264         s->mode = USB_MSDM_CSW;
265     }
266     scsi_req_unref(req);
267     s->req = NULL;
268 }
269
270 static void usb_msd_request_cancelled(SCSIRequest *req)
271 {
272     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
273
274     if (req == s->req) {
275         scsi_req_unref(s->req);
276         s->req = NULL;
277         s->packet = NULL;
278         s->scsi_len = 0;
279     }
280 }
281
282 static void usb_msd_handle_reset(USBDevice *dev)
283 {
284     MSDState *s = (MSDState *)dev;
285
286     DPRINTF("Reset\n");
287     s->mode = USB_MSDM_CBW;
288 }
289
290 static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
291                int request, int value, int index, int length, uint8_t *data)
292 {
293     MSDState *s = (MSDState *)dev;
294     int ret;
295
296     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
297     if (ret >= 0) {
298         return ret;
299     }
300
301     ret = 0;
302     switch (request) {
303     case DeviceRequest | USB_REQ_GET_INTERFACE:
304         data[0] = 0;
305         ret = 1;
306         break;
307     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
308         ret = 0;
309         break;
310     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
311         ret = 0;
312         break;
313     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
314         ret = 0;
315         break;
316         /* Class specific requests.  */
317     case ClassInterfaceOutRequest | MassStorageReset:
318         /* Reset state ready for the next CBW.  */
319         s->mode = USB_MSDM_CBW;
320         ret = 0;
321         break;
322     case ClassInterfaceRequest | GetMaxLun:
323         data[0] = 0;
324         ret = 1;
325         break;
326     default:
327         ret = USB_RET_STALL;
328         break;
329     }
330     return ret;
331 }
332
333 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
334 {
335     MSDState *s = DO_UPCAST(MSDState, dev, dev);
336     scsi_req_cancel(s->req);
337 }
338
339 static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
340 {
341     MSDState *s = (MSDState *)dev;
342     int ret = 0;
343     struct usb_msd_cbw cbw;
344     uint8_t devep = p->devep;
345     uint8_t *data = p->data;
346     int len = p->len;
347
348     switch (p->pid) {
349     case USB_TOKEN_OUT:
350         if (devep != 2)
351             goto fail;
352
353         switch (s->mode) {
354         case USB_MSDM_CBW:
355             if (len != 31) {
356                 fprintf(stderr, "usb-msd: Bad CBW size");
357                 goto fail;
358             }
359             memcpy(&cbw, data, 31);
360             if (le32_to_cpu(cbw.sig) != 0x43425355) {
361                 fprintf(stderr, "usb-msd: Bad signature %08x\n",
362                         le32_to_cpu(cbw.sig));
363                 goto fail;
364             }
365             DPRINTF("Command on LUN %d\n", cbw.lun);
366             if (cbw.lun != 0) {
367                 fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
368                 goto fail;
369             }
370             s->tag = le32_to_cpu(cbw.tag);
371             s->data_len = le32_to_cpu(cbw.data_len);
372             if (s->data_len == 0) {
373                 s->mode = USB_MSDM_CSW;
374             } else if (cbw.flags & 0x80) {
375                 s->mode = USB_MSDM_DATAIN;
376             } else {
377                 s->mode = USB_MSDM_DATAOUT;
378             }
379             DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
380                     s->tag, cbw.flags, cbw.cmd_len, s->data_len);
381             s->residue = 0;
382             s->scsi_len = 0;
383             s->req = scsi_req_new(s->scsi_dev, s->tag, 0, NULL);
384             scsi_req_enqueue(s->req, cbw.cmd);
385             /* ??? Should check that USB and SCSI data transfer
386                directions match.  */
387             if (s->mode != USB_MSDM_CSW && s->residue == 0) {
388                 scsi_req_continue(s->req);
389             }
390             ret = len;
391             break;
392
393         case USB_MSDM_DATAOUT:
394             DPRINTF("Data out %d/%d\n", len, s->data_len);
395             if (len > s->data_len)
396                 goto fail;
397
398             s->usb_buf = data;
399             s->usb_len = len;
400             if (s->scsi_len) {
401                 usb_msd_copy_data(s);
402             }
403             if (s->residue && s->usb_len) {
404                 s->data_len -= s->usb_len;
405                 if (s->data_len == 0)
406                     s->mode = USB_MSDM_CSW;
407                 s->usb_len = 0;
408             }
409             if (s->usb_len) {
410                 DPRINTF("Deferring packet %p\n", p);
411                 s->packet = p;
412                 ret = USB_RET_ASYNC;
413             } else {
414                 ret = len;
415             }
416             break;
417
418         default:
419             DPRINTF("Unexpected write (len %d)\n", len);
420             goto fail;
421         }
422         break;
423
424     case USB_TOKEN_IN:
425         if (devep != 1)
426             goto fail;
427
428         switch (s->mode) {
429         case USB_MSDM_DATAOUT:
430             if (s->data_len != 0 || len < 13)
431                 goto fail;
432             /* Waiting for SCSI write to complete.  */
433             s->packet = p;
434             ret = USB_RET_ASYNC;
435             break;
436
437         case USB_MSDM_CSW:
438             DPRINTF("Command status %d tag 0x%x, len %d\n",
439                     s->result, s->tag, len);
440             if (len < 13)
441                 goto fail;
442
443             usb_msd_send_status(s, p);
444             s->mode = USB_MSDM_CBW;
445             ret = 13;
446             break;
447
448         case USB_MSDM_DATAIN:
449             DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
450             if (len > s->data_len)
451                 len = s->data_len;
452             s->usb_buf = data;
453             s->usb_len = len;
454             if (s->scsi_len) {
455                 usb_msd_copy_data(s);
456             }
457             if (s->residue && s->usb_len) {
458                 s->data_len -= s->usb_len;
459                 memset(s->usb_buf, 0, s->usb_len);
460                 if (s->data_len == 0)
461                     s->mode = USB_MSDM_CSW;
462                 s->usb_len = 0;
463             }
464             if (s->usb_len) {
465                 DPRINTF("Deferring packet %p\n", p);
466                 s->packet = p;
467                 ret = USB_RET_ASYNC;
468             } else {
469                 ret = len;
470             }
471             break;
472
473         default:
474             DPRINTF("Unexpected read (len %d)\n", len);
475             goto fail;
476         }
477         break;
478
479     default:
480         DPRINTF("Bad token\n");
481     fail:
482         ret = USB_RET_STALL;
483         break;
484     }
485
486     return ret;
487 }
488
489 static void usb_msd_password_cb(void *opaque, int err)
490 {
491     MSDState *s = opaque;
492
493     if (!err)
494         err = usb_device_attach(&s->dev);
495
496     if (err)
497         qdev_unplug(&s->dev.qdev);
498 }
499
500 static const struct SCSIBusOps usb_msd_scsi_ops = {
501     .transfer_data = usb_msd_transfer_data,
502     .complete = usb_msd_command_complete,
503     .cancel = usb_msd_request_cancelled
504 };
505
506 static int usb_msd_initfn(USBDevice *dev)
507 {
508     MSDState *s = DO_UPCAST(MSDState, dev, dev);
509     BlockDriverState *bs = s->conf.bs;
510     DriveInfo *dinfo;
511
512     if (!bs) {
513         error_report("usb-msd: drive property not set");
514         return -1;
515     }
516
517     /*
518      * Hack alert: this pretends to be a block device, but it's really
519      * a SCSI bus that can serve only a single device, which it
520      * creates automatically.  But first it needs to detach from its
521      * blockdev, or else scsi_bus_legacy_add_drive() dies when it
522      * attaches again.
523      *
524      * The hack is probably a bad idea.
525      */
526     bdrv_detach(bs, &s->dev.qdev);
527     s->conf.bs = NULL;
528
529     if (!s->serial) {
530         /* try to fall back to value set with legacy -drive serial=... */
531         dinfo = drive_get_by_blockdev(bs);
532         if (*dinfo->serial) {
533             s->serial = strdup(dinfo->serial);
534         }
535     }
536     if (s->serial) {
537         usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
538     }
539
540     usb_desc_init(dev);
541     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, &usb_msd_scsi_ops);
542     s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
543     if (!s->scsi_dev) {
544         return -1;
545     }
546     s->bus.qbus.allow_hotplug = 0;
547     usb_msd_handle_reset(dev);
548
549     if (bdrv_key_required(bs)) {
550         if (cur_mon) {
551             monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
552             s->dev.auto_attach = 0;
553         } else {
554             autostart = 0;
555         }
556     }
557
558     add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
559     return 0;
560 }
561
562 static USBDevice *usb_msd_init(const char *filename)
563 {
564     static int nr=0;
565     char id[8];
566     QemuOpts *opts;
567     DriveInfo *dinfo;
568     USBDevice *dev;
569     const char *p1;
570     char fmt[32];
571
572     /* parse -usbdevice disk: syntax into drive opts */
573     snprintf(id, sizeof(id), "usb%d", nr++);
574     opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
575
576     p1 = strchr(filename, ':');
577     if (p1++) {
578         const char *p2;
579
580         if (strstart(filename, "format=", &p2)) {
581             int len = MIN(p1 - p2, sizeof(fmt));
582             pstrcpy(fmt, len, p2);
583             qemu_opt_set(opts, "format", fmt);
584         } else if (*filename != ':') {
585             printf("unrecognized USB mass-storage option %s\n", filename);
586             return NULL;
587         }
588         filename = p1;
589     }
590     if (!*filename) {
591         printf("block device specification needed\n");
592         return NULL;
593     }
594     qemu_opt_set(opts, "file", filename);
595     qemu_opt_set(opts, "if", "none");
596
597     /* create host drive */
598     dinfo = drive_init(opts, 0);
599     if (!dinfo) {
600         qemu_opts_del(opts);
601         return NULL;
602     }
603
604     /* create guest device */
605     dev = usb_create(NULL /* FIXME */, "usb-storage");
606     if (!dev) {
607         return NULL;
608     }
609     if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
610         qdev_free(&dev->qdev);
611         return NULL;
612     }
613     if (qdev_init(&dev->qdev) < 0)
614         return NULL;
615
616     return dev;
617 }
618
619 static struct USBDeviceInfo msd_info = {
620     .product_desc   = "QEMU USB MSD",
621     .qdev.name      = "usb-storage",
622     .qdev.fw_name      = "storage",
623     .qdev.size      = sizeof(MSDState),
624     .usb_desc       = &desc,
625     .init           = usb_msd_initfn,
626     .handle_packet  = usb_generic_handle_packet,
627     .cancel_packet  = usb_msd_cancel_io,
628     .handle_attach  = usb_desc_attach,
629     .handle_reset   = usb_msd_handle_reset,
630     .handle_control = usb_msd_handle_control,
631     .handle_data    = usb_msd_handle_data,
632     .usbdevice_name = "disk",
633     .usbdevice_init = usb_msd_init,
634     .qdev.props     = (Property[]) {
635         DEFINE_BLOCK_PROPERTIES(MSDState, conf),
636         DEFINE_PROP_STRING("serial", MSDState, serial),
637         DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
638         DEFINE_PROP_END_OF_LIST(),
639     },
640 };
641
642 static void usb_msd_register_devices(void)
643 {
644     usb_qdev_register(&msd_info);
645 }
646 device_init(usb_msd_register_devices)
This page took 0.058586 seconds and 4 git commands to generate.