From: Dhiru Kholia <[email protected]>

This patch adds the ability to override the Vendor ID, Product ID,
Manufacturer and Product strings for USB storage devices via properties.

This allows emulating specific USB storage devices more accurately.
When vid or pid is specified, a per-instance USB descriptor is
created to hold these values.

This helps with debugging and reversing of various VID+PID restricted
applications (e.g. Samsung SecretZone, SanDisk SecureAccess and others).

Usage:

-drive file=hdd.img,format=qcow2,if=none,id=disk \
-device usb-storage,drive=disk,vid=0x1,pid=0x2,manufacturer=A,product=B

Signed-off-by: Dhiru Kholia <[email protected]>
---
 hw/usb/dev-storage-bot.c     |  1 +
 hw/usb/dev-storage-classic.c |  1 +
 hw/usb/dev-storage.c         | 43 ++++++++++++++++++++++++++++++++++++
 include/hw/usb/msd.h         |  3 +++
 4 files changed, 48 insertions(+)

diff --git a/hw/usb/dev-storage-bot.c b/hw/usb/dev-storage-bot.c
index a7f8d80c17..9b8d12958c 100644
--- a/hw/usb/dev-storage-bot.c
+++ b/hw/usb/dev-storage-bot.c
@@ -30,6 +30,7 @@ static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
     DeviceState *d = DEVICE(dev);
 
     usb_desc_create_serial(dev);
+    usb_msd_init_desc(dev);
     usb_desc_init(dev);
     dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
     if (d->hotplugged) {
diff --git a/hw/usb/dev-storage-classic.c b/hw/usb/dev-storage-classic.c
index 977151c4a0..92cf125c8e 100644
--- a/hw/usb/dev-storage-classic.c
+++ b/hw/usb/dev-storage-classic.c
@@ -53,6 +53,7 @@ static void usb_msd_storage_realize(USBDevice *dev, Error 
**errp)
     s->conf.blk = NULL;
 
     usb_desc_create_serial(dev);
+    usb_msd_init_desc(dev);
     usb_desc_init(dev);
     dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
     scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev),
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 040cf15051..0f1389b2d5 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -567,6 +567,47 @@ void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
     return NULL;
 }
 
+static void usb_msd_unrealize(USBDevice *dev)
+{
+    if (dev->usb_desc != &desc) {
+        g_free((USBDesc *)dev->usb_desc);
+    }
+}
+
+void usb_msd_init_desc(USBDevice *dev)
+{
+    MSDState *s = USB_STORAGE_DEV(dev);
+    USBDesc *d;
+
+    if (s->vid || s->pid) {
+        d = g_new0(USBDesc, 1);
+        *d = desc;
+        if (s->vid) {
+            d->id.idVendor = s->vid;
+        }
+        if (s->pid) {
+            d->id.idProduct = s->pid;
+        }
+        dev->usb_desc = d;
+    } else {
+        dev->usb_desc = &desc;
+    }
+
+    if (s->manufacturer) {
+        usb_desc_set_string(dev, STR_MANUFACTURER, s->manufacturer);
+    }
+    if (s->product) {
+        usb_desc_set_string(dev, STR_PRODUCT, s->product);
+    }
+}
+
+static const Property msd_properties_common[] = {
+    DEFINE_PROP_UINT16("vid", MSDState, vid, 0),
+    DEFINE_PROP_UINT16("pid", MSDState, pid, 0),
+    DEFINE_PROP_STRING("manufacturer", MSDState, manufacturer),
+    DEFINE_PROP_STRING("product", MSDState, product),
+};
+
 static const VMStateDescription vmstate_usb_msd = {
     .name = "usb-storage",
     .version_id = 1,
@@ -597,9 +638,11 @@ static void usb_msd_class_initfn_common(ObjectClass 
*klass, const void *data)
     uc->handle_reset   = usb_msd_handle_reset;
     uc->handle_control = usb_msd_handle_control;
     uc->handle_data    = usb_msd_handle_data;
+    uc->unrealize      = usb_msd_unrealize;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     dc->fw_name = "storage";
     dc->vmsd = &vmstate_usb_msd;
+    device_class_set_props(dc, msd_properties_common);
 }
 
 static const TypeInfo usb_storage_dev_type_info = {
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
index 125d2c218f..1920938a20 100644
--- a/include/hw/usb/msd.h
+++ b/include/hw/usb/msd.h
@@ -41,6 +41,8 @@ struct MSDState {
     bool commandlog;
     SCSIDevice *scsi_dev;
     bool needs_reset;
+    uint16_t vid, pid;
+    char *manufacturer, *product;
 };
 
 typedef struct MSDState MSDState;
@@ -53,3 +55,4 @@ void usb_msd_command_complete(SCSIRequest *req, size_t resid);
 void usb_msd_request_cancelled(SCSIRequest *req);
 void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req);
 void usb_msd_handle_reset(USBDevice *dev);
+void usb_msd_init_desc(USBDevice *dev);
-- 
2.49.1

Reply via email to