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, ...) \ 30 do { 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 39 enum 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 46 struct usb_msd_csw { 47 uint32_t sig; 48 uint32_t tag; 49 uint32_t residue; 50 uint8_t status; 51 }; 52 53 typedef 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 73 struct 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 83 enum { 84 STR_MANUFACTURER = 1, 85 STR_PRODUCT, 86 STR_SERIALNUMBER, 87 STR_CONFIG_FULL, 88 STR_CONFIG_HIGH, 89 STR_CONFIG_SUPER, 90 }; 91 92 static 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 101 static 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 120 static 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 136 static 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 155 static 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 171 static 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 192 static 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 208 static 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 223 static 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 s->data_len -= len; 233 if (s->scsi_len == 0 || s->data_len == 0) { 234 scsi_req_continue(s->req); 235 } 236 } 237 238 static void usb_msd_send_status(MSDState *s, USBPacket *p) 239 { 240 int len; 241 242 DPRINTF("Command status %d tag 0x%x, len %zd\n", 243 s->csw.status, le32_to_cpu(s->csw.tag), p->iov.size); 244 245 assert(s->csw.sig == cpu_to_le32(0x53425355)); 246 len = MIN(sizeof(s->csw), p->iov.size); 247 usb_packet_copy(p, &s->csw, len); 248 memset(&s->csw, 0, sizeof(s->csw)); 249 } 250 251 static void usb_msd_packet_complete(MSDState *s) 252 { 253 USBPacket *p = s->packet; 254 255 /* Set s->packet to NULL before calling usb_packet_complete 256 because another request may be issued before 257 usb_packet_complete returns. */ 258 DPRINTF("Packet complete %p\n", p); 259 s->packet = NULL; 260 usb_packet_complete(&s->dev, p); 261 } 262 263 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) 264 { 265 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); 266 USBPacket *p = s->packet; 267 268 assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV)); 269 s->scsi_len = len; 270 s->scsi_off = 0; 271 if (p) { 272 usb_msd_copy_data(s, p); 273 p = s->packet; 274 if (p && p->actual_length == p->iov.size) { 275 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ 276 usb_msd_packet_complete(s); 277 } 278 } 279 } 280 281 static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid) 282 { 283 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); 284 USBPacket *p = s->packet; 285 286 DPRINTF("Command complete %d tag 0x%x\n", status, req->tag); 287 288 s->csw.sig = cpu_to_le32(0x53425355); 289 s->csw.tag = cpu_to_le32(req->tag); 290 s->csw.residue = cpu_to_le32(s->data_len); 291 s->csw.status = status != 0; 292 293 if (s->packet) { 294 if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) { 295 /* A deferred packet with no write data remaining must be 296 the status read packet. */ 297 usb_msd_send_status(s, p); 298 s->mode = USB_MSDM_CBW; 299 } else if (s->mode == USB_MSDM_CSW) { 300 usb_msd_send_status(s, p); 301 s->mode = USB_MSDM_CBW; 302 } else { 303 if (s->data_len) { 304 int len = (p->iov.size - p->actual_length); 305 usb_packet_skip(p, len); 306 s->data_len -= len; 307 } 308 if (s->data_len == 0) { 309 s->mode = USB_MSDM_CSW; 310 } 311 } 312 p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ 313 usb_msd_packet_complete(s); 314 } else if (s->data_len == 0) { 315 s->mode = USB_MSDM_CSW; 316 } 317 scsi_req_unref(req); 318 s->req = NULL; 319 } 320 321 static void usb_msd_request_cancelled(SCSIRequest *req) 322 { 323 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); 324 325 if (req == s->req) { 326 scsi_req_unref(s->req); 327 s->req = NULL; 328 s->scsi_len = 0; 329 } 330 } 331 332 static void usb_msd_handle_reset(USBDevice *dev) 333 { 334 MSDState *s = (MSDState *)dev; 335 336 DPRINTF("Reset\n"); 337 if (s->req) { 338 scsi_req_cancel(s->req); 339 } 340 assert(s->req == NULL); 341 342 if (s->packet) { 343 s->packet->status = USB_RET_STALL; 344 usb_msd_packet_complete(s); 345 } 346 347 s->mode = USB_MSDM_CBW; 348 } 349 350 static void usb_msd_handle_control(USBDevice *dev, USBPacket *p, 351 int request, int value, int index, int length, uint8_t *data) 352 { 353 MSDState *s = (MSDState *)dev; 354 SCSIDevice *scsi_dev; 355 int ret, maxlun; 356 357 ret = usb_desc_handle_control(dev, p, request, value, index, length, data); 358 if (ret >= 0) { 359 return; 360 } 361 362 switch (request) { 363 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: 364 break; 365 /* Class specific requests. */ 366 case ClassInterfaceOutRequest | MassStorageReset: 367 /* Reset state ready for the next CBW. */ 368 s->mode = USB_MSDM_CBW; 369 break; 370 case ClassInterfaceRequest | GetMaxLun: 371 maxlun = 0; 372 for (;;) { 373 scsi_dev = scsi_device_find(&s->bus, 0, 0, maxlun+1); 374 if (scsi_dev == NULL) { 375 break; 376 } 377 if (scsi_dev->lun != maxlun+1) { 378 break; 379 } 380 maxlun++; 381 } 382 DPRINTF("MaxLun %d\n", maxlun); 383 data[0] = maxlun; 384 p->actual_length = 1; 385 break; 386 default: 387 p->status = USB_RET_STALL; 388 break; 389 } 390 } 391 392 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p) 393 { 394 MSDState *s = USB_STORAGE_DEV(dev); 395 396 assert(s->packet == p); 397 s->packet = NULL; 398 399 if (s->req) { 400 scsi_req_cancel(s->req); 401 } 402 } 403 404 static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) 405 { 406 MSDState *s = (MSDState *)dev; 407 uint32_t tag; 408 struct usb_msd_cbw cbw; 409 uint8_t devep = p->ep->nr; 410 SCSIDevice *scsi_dev; 411 uint32_t len; 412 413 switch (p->pid) { 414 case USB_TOKEN_OUT: 415 if (devep != 2) 416 goto fail; 417 418 switch (s->mode) { 419 case USB_MSDM_CBW: 420 if (p->iov.size != 31) { 421 error_report("usb-msd: Bad CBW size"); 422 goto fail; 423 } 424 usb_packet_copy(p, &cbw, 31); 425 if (le32_to_cpu(cbw.sig) != 0x43425355) { 426 error_report("usb-msd: Bad signature %08x", 427 le32_to_cpu(cbw.sig)); 428 goto fail; 429 } 430 DPRINTF("Command on LUN %d\n", cbw.lun); 431 scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun); 432 if (scsi_dev == NULL) { 433 error_report("usb-msd: Bad LUN %d", cbw.lun); 434 goto fail; 435 } 436 tag = le32_to_cpu(cbw.tag); 437 s->data_len = le32_to_cpu(cbw.data_len); 438 if (s->data_len == 0) { 439 s->mode = USB_MSDM_CSW; 440 } else if (cbw.flags & 0x80) { 441 s->mode = USB_MSDM_DATAIN; 442 } else { 443 s->mode = USB_MSDM_DATAOUT; 444 } 445 DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", 446 tag, cbw.flags, cbw.cmd_len, s->data_len); 447 assert(le32_to_cpu(s->csw.residue) == 0); 448 s->scsi_len = 0; 449 s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL); 450 #ifdef DEBUG_MSD 451 scsi_req_print(s->req); 452 #endif 453 len = scsi_req_enqueue(s->req); 454 if (len) { 455 scsi_req_continue(s->req); 456 } 457 break; 458 459 case USB_MSDM_DATAOUT: 460 DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len); 461 if (p->iov.size > s->data_len) { 462 goto fail; 463 } 464 465 if (s->scsi_len) { 466 usb_msd_copy_data(s, p); 467 } 468 if (le32_to_cpu(s->csw.residue)) { 469 int len = p->iov.size - p->actual_length; 470 if (len) { 471 usb_packet_skip(p, len); 472 s->data_len -= len; 473 if (s->data_len == 0) { 474 s->mode = USB_MSDM_CSW; 475 } 476 } 477 } 478 if (p->actual_length < p->iov.size) { 479 DPRINTF("Deferring packet %p [wait data-out]\n", p); 480 s->packet = p; 481 p->status = USB_RET_ASYNC; 482 } 483 break; 484 485 default: 486 DPRINTF("Unexpected write (len %zd)\n", p->iov.size); 487 goto fail; 488 } 489 break; 490 491 case USB_TOKEN_IN: 492 if (devep != 1) 493 goto fail; 494 495 switch (s->mode) { 496 case USB_MSDM_DATAOUT: 497 if (s->data_len != 0 || p->iov.size < 13) { 498 goto fail; 499 } 500 /* Waiting for SCSI write to complete. */ 501 s->packet = p; 502 p->status = USB_RET_ASYNC; 503 break; 504 505 case USB_MSDM_CSW: 506 if (p->iov.size < 13) { 507 goto fail; 508 } 509 510 if (s->req) { 511 /* still in flight */ 512 DPRINTF("Deferring packet %p [wait status]\n", p); 513 s->packet = p; 514 p->status = USB_RET_ASYNC; 515 } else { 516 usb_msd_send_status(s, p); 517 s->mode = USB_MSDM_CBW; 518 } 519 break; 520 521 case USB_MSDM_DATAIN: 522 DPRINTF("Data in %zd/%d, scsi_len %d\n", 523 p->iov.size, s->data_len, s->scsi_len); 524 if (s->scsi_len) { 525 usb_msd_copy_data(s, p); 526 } 527 if (le32_to_cpu(s->csw.residue)) { 528 int len = p->iov.size - p->actual_length; 529 if (len) { 530 usb_packet_skip(p, len); 531 s->data_len -= len; 532 if (s->data_len == 0) { 533 s->mode = USB_MSDM_CSW; 534 } 535 } 536 } 537 if (p->actual_length < p->iov.size) { 538 DPRINTF("Deferring packet %p [wait data-in]\n", p); 539 s->packet = p; 540 p->status = USB_RET_ASYNC; 541 } 542 break; 543 544 default: 545 DPRINTF("Unexpected read (len %zd)\n", p->iov.size); 546 goto fail; 547 } 548 break; 549 550 default: 551 DPRINTF("Bad token\n"); 552 fail: 553 p->status = USB_RET_STALL; 554 break; 555 } 556 } 557 558 static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req) 559 { 560 MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); 561 562 /* nothing to load, just store req in our state struct */ 563 assert(s->req == NULL); 564 scsi_req_ref(req); 565 s->req = req; 566 return NULL; 567 } 568 569 static const struct SCSIBusInfo usb_msd_scsi_info_storage = { 570 .tcq = false, 571 .max_target = 0, 572 .max_lun = 0, 573 574 .transfer_data = usb_msd_transfer_data, 575 .complete = usb_msd_command_complete, 576 .cancel = usb_msd_request_cancelled, 577 .load_request = usb_msd_load_request, 578 }; 579 580 static const struct SCSIBusInfo usb_msd_scsi_info_bot = { 581 .tcq = false, 582 .max_target = 0, 583 .max_lun = 15, 584 585 .transfer_data = usb_msd_transfer_data, 586 .complete = usb_msd_command_complete, 587 .cancel = usb_msd_request_cancelled, 588 .load_request = usb_msd_load_request, 589 }; 590 591 static void usb_msd_storage_realize(USBDevice *dev, Error **errp) 592 { 593 MSDState *s = USB_STORAGE_DEV(dev); 594 BlockBackend *blk = s->conf.blk; 595 SCSIDevice *scsi_dev; 596 597 if (!blk) { 598 error_setg(errp, "drive property not set"); 599 return; 600 } 601 602 blkconf_blocksizes(&s->conf); 603 if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, 604 errp)) { 605 return; 606 } 607 608 /* 609 * Hack alert: this pretends to be a block device, but it's really 610 * a SCSI bus that can serve only a single device, which it 611 * creates automatically. But first it needs to detach from its 612 * blockdev, or else scsi_bus_legacy_add_drive() dies when it 613 * attaches again. We also need to take another reference so that 614 * blk_detach_dev() doesn't free blk while we still need it. 615 * 616 * The hack is probably a bad idea. 617 */ 618 blk_ref(blk); 619 blk_detach_dev(blk, DEVICE(s)); 620 s->conf.blk = NULL; 621 622 usb_desc_create_serial(dev); 623 usb_desc_init(dev); 624 scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), 625 &usb_msd_scsi_info_storage, NULL); 626 scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, 627 s->conf.bootindex, s->conf.share_rw, 628 s->conf.rerror, s->conf.werror, 629 dev->serial, 630 errp); 631 blk_unref(blk); 632 if (!scsi_dev) { 633 return; 634 } 635 usb_msd_handle_reset(dev); 636 s->scsi_dev = scsi_dev; 637 } 638 639 static void usb_msd_bot_realize(USBDevice *dev, Error **errp) 640 { 641 MSDState *s = USB_STORAGE_DEV(dev); 642 DeviceState *d = DEVICE(dev); 643 644 usb_desc_create_serial(dev); 645 usb_desc_init(dev); 646 if (d->hotplugged) { 647 s->dev.auto_attach = 0; 648 } 649 650 scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), 651 &usb_msd_scsi_info_bot, NULL); 652 usb_msd_handle_reset(dev); 653 } 654 655 static const VMStateDescription vmstate_usb_msd = { 656 .name = "usb-storage", 657 .version_id = 1, 658 .minimum_version_id = 1, 659 .fields = (VMStateField[]) { 660 VMSTATE_USB_DEVICE(dev, MSDState), 661 VMSTATE_UINT32(mode, MSDState), 662 VMSTATE_UINT32(scsi_len, MSDState), 663 VMSTATE_UINT32(scsi_off, MSDState), 664 VMSTATE_UINT32(data_len, MSDState), 665 VMSTATE_UINT32(csw.sig, MSDState), 666 VMSTATE_UINT32(csw.tag, MSDState), 667 VMSTATE_UINT32(csw.residue, MSDState), 668 VMSTATE_UINT8(csw.status, MSDState), 669 VMSTATE_END_OF_LIST() 670 } 671 }; 672 673 static Property msd_properties[] = { 674 DEFINE_BLOCK_PROPERTIES(MSDState, conf), 675 DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf), 676 DEFINE_PROP_BIT("removable", MSDState, removable, 0, false), 677 DEFINE_PROP_END_OF_LIST(), 678 }; 679 680 static void usb_msd_class_initfn_common(ObjectClass *klass, void *data) 681 { 682 DeviceClass *dc = DEVICE_CLASS(klass); 683 USBDeviceClass *uc = USB_DEVICE_CLASS(klass); 684 685 uc->product_desc = "QEMU USB MSD"; 686 uc->usb_desc = &desc; 687 uc->cancel_packet = usb_msd_cancel_io; 688 uc->handle_attach = usb_desc_attach; 689 uc->handle_reset = usb_msd_handle_reset; 690 uc->handle_control = usb_msd_handle_control; 691 uc->handle_data = usb_msd_handle_data; 692 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 693 dc->fw_name = "storage"; 694 dc->vmsd = &vmstate_usb_msd; 695 } 696 697 static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data) 698 { 699 DeviceClass *dc = DEVICE_CLASS(klass); 700 USBDeviceClass *uc = USB_DEVICE_CLASS(klass); 701 702 uc->realize = usb_msd_storage_realize; 703 device_class_set_props(dc, msd_properties); 704 } 705 706 static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name, 707 void *opaque, Error **errp) 708 { 709 USBDevice *dev = USB_DEVICE(obj); 710 MSDState *s = USB_STORAGE_DEV(dev); 711 712 visit_type_int32(v, name, &s->conf.bootindex, errp); 713 } 714 715 static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name, 716 void *opaque, Error **errp) 717 { 718 USBDevice *dev = USB_DEVICE(obj); 719 MSDState *s = USB_STORAGE_DEV(dev); 720 int32_t boot_index; 721 Error *local_err = NULL; 722 723 visit_type_int32(v, name, &boot_index, &local_err); 724 if (local_err) { 725 goto out; 726 } 727 /* check whether bootindex is present in fw_boot_order list */ 728 check_boot_index(boot_index, &local_err); 729 if (local_err) { 730 goto out; 731 } 732 /* change bootindex to a new one */ 733 s->conf.bootindex = boot_index; 734 735 if (s->scsi_dev) { 736 object_property_set_int(OBJECT(s->scsi_dev), boot_index, "bootindex", 737 &error_abort); 738 } 739 740 out: 741 error_propagate(errp, local_err); 742 } 743 744 static const TypeInfo usb_storage_dev_type_info = { 745 .name = TYPE_USB_STORAGE, 746 .parent = TYPE_USB_DEVICE, 747 .instance_size = sizeof(MSDState), 748 .abstract = true, 749 .class_init = usb_msd_class_initfn_common, 750 }; 751 752 static void usb_msd_instance_init(Object *obj) 753 { 754 object_property_add(obj, "bootindex", "int32", 755 usb_msd_get_bootindex, 756 usb_msd_set_bootindex, NULL, NULL, NULL); 757 object_property_set_int(obj, -1, "bootindex", NULL); 758 } 759 760 static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data) 761 { 762 USBDeviceClass *uc = USB_DEVICE_CLASS(klass); 763 764 uc->realize = usb_msd_bot_realize; 765 uc->attached_settable = true; 766 } 767 768 static const TypeInfo msd_info = { 769 .name = "usb-storage", 770 .parent = TYPE_USB_STORAGE, 771 .class_init = usb_msd_class_storage_initfn, 772 .instance_init = usb_msd_instance_init, 773 }; 774 775 static const TypeInfo bot_info = { 776 .name = "usb-bot", 777 .parent = TYPE_USB_STORAGE, 778 .class_init = usb_msd_class_bot_initfn, 779 }; 780 781 static void usb_msd_register_types(void) 782 { 783 type_register_static(&usb_storage_dev_type_info); 784 type_register_static(&msd_info); 785 type_register_static(&bot_info); 786 } 787 788 type_init(usb_msd_register_types) 789