qemu/hw/usb/dev-storage.c
<<
>>
Prefs
   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/osdep.h"
  11#include "qapi/error.h"
  12#include "qemu/error-report.h"
  13#include "qemu/module.h"
  14#include "qemu/option.h"
  15#include "qemu/config-file.h"
  16#include "hw/usb.h"
  17#include "desc.h"
  18#include "hw/qdev-properties.h"
  19#include "hw/scsi/scsi.h"
  20#include "migration/vmstate.h"
  21#include "sysemu/sysemu.h"
  22#include "sysemu/block-backend.h"
  23#include "qapi/visitor.h"
  24#include "qemu/cutils.h"
  25
  26//#define DEBUG_MSD
  27
  28#ifdef DEBUG_MSD
  29#define DPRINTF(fmt, ...) \
  30do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
  31#else
  32#define DPRINTF(fmt, ...) do {} while(0)
  33#endif
  34
  35/* USB requests.  */
  36#define MassStorageReset  0xff
  37#define GetMaxLun         0xfe
  38
  39enum USBMSDMode {
  40    USB_MSDM_CBW, /* Command Block.  */
  41    USB_MSDM_DATAOUT, /* Transfer data to device.  */
  42    USB_MSDM_DATAIN, /* Transfer data from device.  */
  43    USB_MSDM_CSW /* Command Status.  */
  44};
  45
  46struct usb_msd_csw {
  47    uint32_t sig;
  48    uint32_t tag;
  49    uint32_t residue;
  50    uint8_t status;
  51};
  52
  53typedef struct {
  54    USBDevice dev;
  55    enum USBMSDMode mode;
  56    uint32_t scsi_off;
  57    uint32_t scsi_len;
  58    uint32_t data_len;
  59    struct usb_msd_csw csw;
  60    SCSIRequest *req;
  61    SCSIBus bus;
  62    /* For async completion.  */
  63    USBPacket *packet;
  64    /* usb-storage only */
  65    BlockConf conf;
  66    uint32_t removable;
  67    SCSIDevice *scsi_dev;
  68} MSDState;
  69
  70#define TYPE_USB_STORAGE "usb-storage-dev"
  71#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE)
  72
  73struct usb_msd_cbw {
  74    uint32_t sig;
  75    uint32_t tag;
  76    uint32_t data_len;
  77    uint8_t flags;
  78    uint8_t lun;
  79    uint8_t cmd_len;
  80    uint8_t cmd[16];
  81};
  82
  83enum {
  84    STR_MANUFACTURER = 1,
  85    STR_PRODUCT,
  86    STR_SERIALNUMBER,
  87    STR_CONFIG_FULL,
  88    STR_CONFIG_HIGH,
  89    STR_CONFIG_SUPER,
  90};
  91
  92static const USBDescStrings desc_strings = {
  93    [STR_MANUFACTURER] = "QEMU",
  94    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
  95    [STR_SERIALNUMBER] = "1",
  96    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
  97    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
  98    [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
  99};
 100
 101static const USBDescIface desc_iface_full = {
 102    .bInterfaceNumber              = 0,
 103    .bNumEndpoints                 = 2,
 104    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
 105    .bInterfaceSubClass            = 0x06, /* SCSI */
 106    .bInterfaceProtocol            = 0x50, /* Bulk */
 107    .eps = (USBDescEndpoint[]) {
 108        {
 109            .bEndpointAddress      = USB_DIR_IN | 0x01,
 110            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 111            .wMaxPacketSize        = 64,
 112        },{
 113            .bEndpointAddress      = USB_DIR_OUT | 0x02,
 114            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 115            .wMaxPacketSize        = 64,
 116        },
 117    }
 118};
 119
 120static const USBDescDevice desc_device_full = {
 121    .bcdUSB                        = 0x0200,
 122    .bMaxPacketSize0               = 8,
 123    .bNumConfigurations            = 1,
 124    .confs = (USBDescConfig[]) {
 125        {
 126            .bNumInterfaces        = 1,
 127            .bConfigurationValue   = 1,
 128            .iConfiguration        = STR_CONFIG_FULL,
 129            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
 130            .nif = 1,
 131            .ifs = &desc_iface_full,
 132        },
 133    },
 134};
 135
 136static const USBDescIface desc_iface_high = {
 137    .bInterfaceNumber              = 0,
 138    .bNumEndpoints                 = 2,
 139    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
 140    .bInterfaceSubClass            = 0x06, /* SCSI */
 141    .bInterfaceProtocol            = 0x50, /* Bulk */
 142    .eps = (USBDescEndpoint[]) {
 143        {
 144            .bEndpointAddress      = USB_DIR_IN | 0x01,
 145            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 146            .wMaxPacketSize        = 512,
 147        },{
 148            .bEndpointAddress      = USB_DIR_OUT | 0x02,
 149            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 150            .wMaxPacketSize        = 512,
 151        },
 152    }
 153};
 154
 155static const USBDescDevice desc_device_high = {
 156    .bcdUSB                        = 0x0200,
 157    .bMaxPacketSize0               = 64,
 158    .bNumConfigurations            = 1,
 159    .confs = (USBDescConfig[]) {
 160        {
 161            .bNumInterfaces        = 1,
 162            .bConfigurationValue   = 1,
 163            .iConfiguration        = STR_CONFIG_HIGH,
 164            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
 165            .nif = 1,
 166            .ifs = &desc_iface_high,
 167        },
 168    },
 169};
 170
 171static const USBDescIface desc_iface_super = {
 172    .bInterfaceNumber              = 0,
 173    .bNumEndpoints                 = 2,
 174    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
 175    .bInterfaceSubClass            = 0x06, /* SCSI */
 176    .bInterfaceProtocol            = 0x50, /* Bulk */
 177    .eps = (USBDescEndpoint[]) {
 178        {
 179            .bEndpointAddress      = USB_DIR_IN | 0x01,
 180            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 181            .wMaxPacketSize        = 1024,
 182            .bMaxBurst             = 15,
 183        },{
 184            .bEndpointAddress      = USB_DIR_OUT | 0x02,
 185            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 186            .wMaxPacketSize        = 1024,
 187            .bMaxBurst             = 15,
 188        },
 189    }
 190};
 191
 192static const USBDescDevice desc_device_super = {
 193    .bcdUSB                        = 0x0300,
 194    .bMaxPacketSize0               = 9,
 195    .bNumConfigurations            = 1,
 196    .confs = (USBDescConfig[]) {
 197        {
 198            .bNumInterfaces        = 1,
 199            .bConfigurationValue   = 1,
 200            .iConfiguration        = STR_CONFIG_SUPER,
 201            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
 202            .nif = 1,
 203            .ifs = &desc_iface_super,
 204        },
 205    },
 206};
 207
 208static const USBDesc desc = {
 209    .id = {
 210        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
 211        .idProduct         = 0x0001,
 212        .bcdDevice         = 0,
 213        .iManufacturer     = STR_MANUFACTURER,
 214        .iProduct          = STR_PRODUCT,
 215        .iSerialNumber     = STR_SERIALNUMBER,
 216    },
 217    .full  = &desc_device_full,
 218    .high  = &desc_device_high,
 219    .super = &desc_device_super,
 220    .str   = desc_strings,
 221};
 222
 223static void usb_msd_copy_data(MSDState *s, USBPacket *p)
 224{
 225    uint32_t len;
 226    len = p->iov.size - p->actual_length;
 227    if (len > s->scsi_len)
 228        len = s->scsi_len;
 229    usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
 230    s->scsi_len -= len;
 231    s->scsi_off += len;
 232    if (len > s->data_len) {
 233        len = s->data_len;
 234    }
 235    s->data_len -= len;
 236    if (s->scsi_len == 0 || s->data_len == 0) {
 237        scsi_req_continue(s->req);
 238    }
 239}
 240
 241static void usb_msd_send_status(MSDState *s, USBPacket *p)
 242{
 243    int len;
 244
 245    DPRINTF("Command status %d tag 0x%x, len %zd\n",
 246            s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size);
 247
 248    assert(s->csw.sig == cpu_to_le32(0x53425355));
 249    len = MIN(sizeof(s->csw), p->iov.size);
 250    usb_packet_copy(p, &s->csw, len);
 251    memset(&s->csw, 0, sizeof(s->csw));
 252}
 253
 254static void usb_msd_packet_complete(MSDState *s)
 255{
 256    USBPacket *p = s->packet;
 257
 258    /* Set s->packet to NULL before calling usb_packet_complete
 259       because another request may be issued before
 260       usb_packet_complete returns.  */
 261    DPRINTF("Packet complete %p\n", p);
 262    s->packet = NULL;
 263    usb_packet_complete(&s->dev, p);
 264}
 265
 266static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
 267{
 268    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
 269    USBPacket *p = s->packet;
 270
 271    assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
 272    s->scsi_len = len;
 273    s->scsi_off = 0;
 274    if (p) {
 275        usb_msd_copy_data(s, p);
 276        p = s->packet;
 277        if (p && p->actual_length == p->iov.size) {
 278            p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
 279            usb_msd_packet_complete(s);
 280        }
 281    }
 282}
 283
 284static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
 285{
 286    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
 287    USBPacket *p = s->packet;
 288
 289    DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
 290
 291    s->csw.sig = cpu_to_le32(0x53425355);
 292    s->csw.tag = cpu_to_le32(req->tag);
 293    s->csw.residue = cpu_to_le32(s->data_len);
 294    s->csw.status = status != 0;
 295
 296    if (s->packet) {
 297        if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
 298            /* A deferred packet with no write data remaining must be
 299               the status read packet.  */
 300            usb_msd_send_status(s, p);
 301            s->mode = USB_MSDM_CBW;
 302        } else if (s->mode == USB_MSDM_CSW) {
 303            usb_msd_send_status(s, p);
 304            s->mode = USB_MSDM_CBW;
 305        } else {
 306            if (s->data_len) {
 307                int len = (p->iov.size - p->actual_length);
 308                usb_packet_skip(p, len);
 309                if (len > s->data_len) {
 310                    len = s->data_len;
 311                }
 312                s->data_len -= len;
 313            }
 314            if (s->data_len == 0) {
 315                s->mode = USB_MSDM_CSW;
 316            }
 317        }
 318        p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
 319        usb_msd_packet_complete(s);
 320    } else if (s->data_len == 0) {
 321        s->mode = USB_MSDM_CSW;
 322    }
 323    scsi_req_unref(req);
 324    s->req = NULL;
 325}
 326
 327static void usb_msd_request_cancelled(SCSIRequest *req)
 328{
 329    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
 330
 331    if (req == s->req) {
 332        scsi_req_unref(s->req);
 333        s->req = NULL;
 334        s->scsi_len = 0;
 335    }
 336}
 337
 338static void usb_msd_handle_reset(USBDevice *dev)
 339{
 340    MSDState *s = (MSDState *)dev;
 341
 342    DPRINTF("Reset\n");
 343    if (s->req) {
 344        scsi_req_cancel(s->req);
 345    }
 346    assert(s->req == NULL);
 347
 348    if (s->packet) {
 349        s->packet->status = USB_RET_STALL;
 350        usb_msd_packet_complete(s);
 351    }
 352
 353    s->mode = USB_MSDM_CBW;
 354}
 355
 356static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 357               int request, int value, int index, int length, uint8_t *data)
 358{
 359    MSDState *s = (MSDState *)dev;
 360    SCSIDevice *scsi_dev;
 361    int ret, maxlun;
 362
 363    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 364    if (ret >= 0) {
 365        return;
 366    }
 367
 368    switch (request) {
 369    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 370        break;
 371        /* Class specific requests.  */
 372    case ClassInterfaceOutRequest | MassStorageReset:
 373        /* Reset state ready for the next CBW.  */
 374        s->mode = USB_MSDM_CBW;
 375        break;
 376    case ClassInterfaceRequest | GetMaxLun:
 377        maxlun = 0;
 378        for (;;) {
 379            scsi_dev = scsi_device_find(&s->bus, 0, 0, maxlun+1);
 380            if (scsi_dev == NULL) {
 381                break;
 382            }
 383            if (scsi_dev->lun != maxlun+1) {
 384                break;
 385            }
 386            maxlun++;
 387        }
 388        DPRINTF("MaxLun %d\n", maxlun);
 389        data[0] = maxlun;
 390        p->actual_length = 1;
 391        break;
 392    default:
 393        p->status = USB_RET_STALL;
 394        break;
 395    }
 396}
 397
 398static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
 399{
 400    MSDState *s = USB_STORAGE_DEV(dev);
 401
 402    assert(s->packet == p);
 403    s->packet = NULL;
 404
 405    if (s->req) {
 406        scsi_req_cancel(s->req);
 407    }
 408}
 409
 410static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 411{
 412    MSDState *s = (MSDState *)dev;
 413    uint32_t tag;
 414    struct usb_msd_cbw cbw;
 415    uint8_t devep = p->ep->nr;
 416    SCSIDevice *scsi_dev;
 417    uint32_t len;
 418
 419    switch (p->pid) {
 420    case USB_TOKEN_OUT:
 421        if (devep != 2)
 422            goto fail;
 423
 424        switch (s->mode) {
 425        case USB_MSDM_CBW:
 426            if (p->iov.size != 31) {
 427                error_report("usb-msd: Bad CBW size");
 428                goto fail;
 429            }
 430            usb_packet_copy(p, &cbw, 31);
 431            if (le32_to_cpu(cbw.sig) != 0x43425355) {
 432                error_report("usb-msd: Bad signature %08x",
 433                             le32_to_cpu(cbw.sig));
 434                goto fail;
 435            }
 436            DPRINTF("Command on LUN %d\n", cbw.lun);
 437            scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun);
 438            if (scsi_dev == NULL) {
 439                error_report("usb-msd: Bad LUN %d", cbw.lun);
 440                goto fail;
 441            }
 442            tag = le32_to_cpu(cbw.tag);
 443            s->data_len = le32_to_cpu(cbw.data_len);
 444            if (s->data_len == 0) {
 445                s->mode = USB_MSDM_CSW;
 446            } else if (cbw.flags & 0x80) {
 447                s->mode = USB_MSDM_DATAIN;
 448            } else {
 449                s->mode = USB_MSDM_DATAOUT;
 450            }
 451            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
 452                    tag, cbw.flags, cbw.cmd_len, s->data_len);
 453            assert(le32_to_cpu(s->csw.residue) == 0);
 454            s->scsi_len = 0;
 455            s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL);
 456#ifdef DEBUG_MSD
 457            scsi_req_print(s->req);
 458#endif
 459            len = scsi_req_enqueue(s->req);
 460            if (len) {
 461                scsi_req_continue(s->req);
 462            }
 463            break;
 464
 465        case USB_MSDM_DATAOUT:
 466            DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
 467            if (p->iov.size > s->data_len) {
 468                goto fail;
 469            }
 470
 471            if (s->scsi_len) {
 472                usb_msd_copy_data(s, p);
 473            }
 474            if (le32_to_cpu(s->csw.residue)) {
 475                int len = p->iov.size - p->actual_length;
 476                if (len) {
 477                    usb_packet_skip(p, len);
 478                    if (len > s->data_len) {
 479                        len = s->data_len;
 480                    }
 481                    s->data_len -= len;
 482                    if (s->data_len == 0) {
 483                        s->mode = USB_MSDM_CSW;
 484                    }
 485                }
 486            }
 487            if (p->actual_length < p->iov.size) {
 488                DPRINTF("Deferring packet %p [wait data-out]\n", p);
 489                s->packet = p;
 490                p->status = USB_RET_ASYNC;
 491            }
 492            break;
 493
 494        default:
 495            DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
 496            goto fail;
 497        }
 498        break;
 499
 500    case USB_TOKEN_IN:
 501        if (devep != 1)
 502            goto fail;
 503
 504        switch (s->mode) {
 505        case USB_MSDM_DATAOUT:
 506            if (s->data_len != 0 || p->iov.size < 13) {
 507                goto fail;
 508            }
 509            /* Waiting for SCSI write to complete.  */
 510            s->packet = p;
 511            p->status = USB_RET_ASYNC;
 512            break;
 513
 514        case USB_MSDM_CSW:
 515            if (p->iov.size < 13) {
 516                goto fail;
 517            }
 518
 519            if (s->req) {
 520                /* still in flight */
 521                DPRINTF("Deferring packet %p [wait status]\n", p);
 522                s->packet = p;
 523                p->status = USB_RET_ASYNC;
 524            } else {
 525                usb_msd_send_status(s, p);
 526                s->mode = USB_MSDM_CBW;
 527            }
 528            break;
 529
 530        case USB_MSDM_DATAIN:
 531            DPRINTF("Data in %zd/%d, scsi_len %d\n",
 532                    p->iov.size, s->data_len, s->scsi_len);
 533            if (s->scsi_len) {
 534                usb_msd_copy_data(s, p);
 535            }
 536            if (le32_to_cpu(s->csw.residue)) {
 537                int len = p->iov.size - p->actual_length;
 538                if (len) {
 539                    usb_packet_skip(p, len);
 540                    if (len > s->data_len) {
 541                        len = s->data_len;
 542                    }
 543                    s->data_len -= len;
 544                    if (s->data_len == 0) {
 545                        s->mode = USB_MSDM_CSW;
 546                    }
 547                }
 548            }
 549            if (p->actual_length < p->iov.size && s->mode == USB_MSDM_DATAIN) {
 550                DPRINTF("Deferring packet %p [wait data-in]\n", p);
 551                s->packet = p;
 552                p->status = USB_RET_ASYNC;
 553            }
 554            break;
 555
 556        default:
 557            DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
 558            goto fail;
 559        }
 560        break;
 561
 562    default:
 563        DPRINTF("Bad token\n");
 564    fail:
 565        p->status = USB_RET_STALL;
 566        break;
 567    }
 568}
 569
 570static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
 571{
 572    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
 573
 574    /* nothing to load, just store req in our state struct */
 575    assert(s->req == NULL);
 576    scsi_req_ref(req);
 577    s->req = req;
 578    return NULL;
 579}
 580
 581static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
 582    .tcq = false,
 583    .max_target = 0,
 584    .max_lun = 0,
 585
 586    .transfer_data = usb_msd_transfer_data,
 587    .complete = usb_msd_command_complete,
 588    .cancel = usb_msd_request_cancelled,
 589    .load_request = usb_msd_load_request,
 590};
 591
 592static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
 593    .tcq = false,
 594    .max_target = 0,
 595    .max_lun = 15,
 596
 597    .transfer_data = usb_msd_transfer_data,
 598    .complete = usb_msd_command_complete,
 599    .cancel = usb_msd_request_cancelled,
 600    .load_request = usb_msd_load_request,
 601};
 602
 603static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
 604{
 605    MSDState *s = USB_STORAGE_DEV(dev);
 606    BlockBackend *blk = s->conf.blk;
 607    SCSIDevice *scsi_dev;
 608
 609    if (!blk) {
 610        error_setg(errp, "drive property not set");
 611        return;
 612    }
 613
 614    if (!blkconf_blocksizes(&s->conf, errp)) {
 615        return;
 616    }
 617
 618    if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
 619                                       errp)) {
 620        return;
 621    }
 622
 623    /*
 624     * Hack alert: this pretends to be a block device, but it's really
 625     * a SCSI bus that can serve only a single device, which it
 626     * creates automatically.  But first it needs to detach from its
 627     * blockdev, or else scsi_bus_legacy_add_drive() dies when it
 628     * attaches again. We also need to take another reference so that
 629     * blk_detach_dev() doesn't free blk while we still need it.
 630     *
 631     * The hack is probably a bad idea.
 632     */
 633    blk_ref(blk);
 634    blk_detach_dev(blk, DEVICE(s));
 635    s->conf.blk = NULL;
 636
 637    usb_desc_create_serial(dev);
 638    usb_desc_init(dev);
 639    scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
 640                 &usb_msd_scsi_info_storage, NULL);
 641    scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
 642                                         s->conf.bootindex, s->conf.share_rw,
 643                                         s->conf.rerror, s->conf.werror,
 644                                         dev->serial,
 645                                         errp);
 646    blk_unref(blk);
 647    if (!scsi_dev) {
 648        return;
 649    }
 650    usb_msd_handle_reset(dev);
 651    s->scsi_dev = scsi_dev;
 652}
 653
 654static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
 655{
 656    MSDState *s = USB_STORAGE_DEV(dev);
 657    DeviceState *d = DEVICE(dev);
 658
 659    usb_desc_create_serial(dev);
 660    usb_desc_init(dev);
 661    if (d->hotplugged) {
 662        s->dev.auto_attach = 0;
 663    }
 664
 665    scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
 666                 &usb_msd_scsi_info_bot, NULL);
 667    usb_msd_handle_reset(dev);
 668}
 669
 670static const VMStateDescription vmstate_usb_msd = {
 671    .name = "usb-storage",
 672    .version_id = 1,
 673    .minimum_version_id = 1,
 674    .fields = (VMStateField[]) {
 675        VMSTATE_USB_DEVICE(dev, MSDState),
 676        VMSTATE_UINT32(mode, MSDState),
 677        VMSTATE_UINT32(scsi_len, MSDState),
 678        VMSTATE_UINT32(scsi_off, MSDState),
 679        VMSTATE_UINT32(data_len, MSDState),
 680        VMSTATE_UINT32(csw.sig, MSDState),
 681        VMSTATE_UINT32(csw.tag, MSDState),
 682        VMSTATE_UINT32(csw.residue, MSDState),
 683        VMSTATE_UINT8(csw.status, MSDState),
 684        VMSTATE_END_OF_LIST()
 685    }
 686};
 687
 688static Property msd_properties[] = {
 689    DEFINE_BLOCK_PROPERTIES(MSDState, conf),
 690    DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
 691    DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
 692    DEFINE_PROP_END_OF_LIST(),
 693};
 694
 695static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
 696{
 697    DeviceClass *dc = DEVICE_CLASS(klass);
 698    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 699
 700    uc->product_desc   = "QEMU USB MSD";
 701    uc->usb_desc       = &desc;
 702    uc->cancel_packet  = usb_msd_cancel_io;
 703    uc->handle_attach  = usb_desc_attach;
 704    uc->handle_reset   = usb_msd_handle_reset;
 705    uc->handle_control = usb_msd_handle_control;
 706    uc->handle_data    = usb_msd_handle_data;
 707    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 708    dc->fw_name = "storage";
 709    dc->vmsd = &vmstate_usb_msd;
 710}
 711
 712static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
 713{
 714    DeviceClass *dc = DEVICE_CLASS(klass);
 715    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 716
 717    uc->realize = usb_msd_storage_realize;
 718    device_class_set_props(dc, msd_properties);
 719}
 720
 721static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
 722                                  void *opaque, Error **errp)
 723{
 724    USBDevice *dev = USB_DEVICE(obj);
 725    MSDState *s = USB_STORAGE_DEV(dev);
 726
 727    visit_type_int32(v, name, &s->conf.bootindex, errp);
 728}
 729
 730static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
 731                                  void *opaque, Error **errp)
 732{
 733    USBDevice *dev = USB_DEVICE(obj);
 734    MSDState *s = USB_STORAGE_DEV(dev);
 735    int32_t boot_index;
 736    Error *local_err = NULL;
 737
 738    if (!visit_type_int32(v, name, &boot_index, errp)) {
 739        return;
 740    }
 741    /* check whether bootindex is present in fw_boot_order list  */
 742    check_boot_index(boot_index, &local_err);
 743    if (local_err) {
 744        goto out;
 745    }
 746    /* change bootindex to a new one */
 747    s->conf.bootindex = boot_index;
 748
 749    if (s->scsi_dev) {
 750        object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index,
 751                                &error_abort);
 752    }
 753
 754out:
 755    error_propagate(errp, local_err);
 756}
 757
 758static const TypeInfo usb_storage_dev_type_info = {
 759    .name = TYPE_USB_STORAGE,
 760    .parent = TYPE_USB_DEVICE,
 761    .instance_size = sizeof(MSDState),
 762    .abstract = true,
 763    .class_init = usb_msd_class_initfn_common,
 764};
 765
 766static void usb_msd_instance_init(Object *obj)
 767{
 768    object_property_add(obj, "bootindex", "int32",
 769                        usb_msd_get_bootindex,
 770                        usb_msd_set_bootindex, NULL, NULL);
 771    object_property_set_int(obj, "bootindex", -1, NULL);
 772}
 773
 774static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
 775{
 776    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 777
 778    uc->realize = usb_msd_bot_realize;
 779    uc->attached_settable = true;
 780}
 781
 782static const TypeInfo msd_info = {
 783    .name          = "usb-storage",
 784    .parent        = TYPE_USB_STORAGE,
 785    .class_init    = usb_msd_class_storage_initfn,
 786    .instance_init = usb_msd_instance_init,
 787};
 788
 789static const TypeInfo bot_info = {
 790    .name          = "usb-bot",
 791    .parent        = TYPE_USB_STORAGE,
 792    .class_init    = usb_msd_class_bot_initfn,
 793};
 794
 795static void usb_msd_register_types(void)
 796{
 797    type_register_static(&usb_storage_dev_type_info);
 798    type_register_static(&msd_info);
 799    type_register_static(&bot_info);
 800}
 801
 802type_init(usb_msd_register_types)
 803