Hi,
Recently I needed to sandbox some software, running it inside Qemu off
of a disk image of the USB stick it came on.
However, Qemu's USB mass storage device emulation (-usbdevice disk)
shows up as a "QEMU USB HARDDRIVE" with VID:PID of 46f4:0001.
The sandboxed software didn't like that at all, and refused to run. So
I patched Qemu to take VID, PID, serial etc. from the command line
arguments, like so:
"-usbdevice
disk:format=raw:vid=0a6b:pid=0001:manufacturer=Whoever:product=Whatever:serial=324324:/path/to/stick.img"
I'm posting the patch here for other people to find, should they
develop the same VID-faking needs.
I've read http://wiki.qemu.org/Contribute/SubmitAPatch and decided
to not post the patch to -dev as this is a one-off single-purpose
hack, not a proper solution. For instance, with this patch, adding more than one
'-usbdevice disk' type device will lead to spectacular failures. Beware!
Cheers, Wicher Minnaard
diff -Naur qemu-2.3.0_orig/hw/usb/dev-storage.c qemu-2.3.0/hw/usb/dev-storage.c
--- qemu-2.3.0_orig/hw/usb/dev-storage.c 2015-04-27 16:08:25.000000000 +0200
+++ qemu-2.3.0/hw/usb/dev-storage.c 2015-07-23 10:26:42.556779948 +0200
@@ -83,7 +83,7 @@
STR_CONFIG_SUPER,
};
-static const USBDescStrings desc_strings = {
+static USBDescStrings desc_strings = {
[STR_MANUFACTURER] = "QEMU",
[STR_PRODUCT] = "QEMU USB HARDDRIVE",
[STR_SERIALNUMBER] = "1",
@@ -199,7 +199,7 @@
},
};
-static const USBDesc desc = {
+static USBDesc desc = {
.id = {
.idVendor = 0x46f4, /* CRC16() of "QEMU" */
.idProduct = 0x0001,
@@ -675,7 +675,6 @@
QemuOpts *opts;
DriveInfo *dinfo;
USBDevice *dev;
- const char *p1;
char fmt[32];
/* parse -usbdevice disk: syntax into drive opts */
@@ -684,20 +683,53 @@
opts = qemu_opts_create(qemu_find_opts("drive"), id, 1, NULL);
} while (!opts);
- p1 = strchr(filename, ':');
- if (p1++) {
- const char *p2;
-
- if (strstart(filename, "format=", &p2)) {
- int len = MIN(p1 - p2, sizeof(fmt));
- pstrcpy(fmt, len, p2);
+ int filename_len = strlen(filename)+1;
+ char c_filename[filename_len];
+ pstrcpy(c_filename, filename_len, filename);
+ char* comp;
+ char delim = ':';
+ char subdelim = '=';
+
+ comp = strtok(c_filename, &delim); //this actually modifies the parsee in place, hence the copy.
+ while(comp){
+ const char *p;
+ if (strstart(comp, "format=", &p)) {
+ int len = MIN(comp - p, sizeof(fmt));
+ pstrcpy(fmt, len, p);
qemu_opt_set(opts, "format", fmt, &error_abort);
- } else if (*filename != ':') {
+ }
+ else if (strstart(comp, "vid=", &p)) {
+ desc.id.idVendor = (uint16_t) strtol(p, NULL, 16);
+ }
+ else if (strstart(comp, "pid=", &p)) {
+ desc.id.idProduct = (uint16_t) strtol(p, NULL, 16);
+ }
+ else if (strstart(comp, "manufacturer=", &p)) {
+ char* manuf = malloc(strlen(p)+1);
+ pstrcpy(manuf, strlen(p)+1, p);
+ desc_strings[STR_MANUFACTURER] = manuf;
+ }
+ else if (strstart(comp, "product=", &p)) {
+ char* product = malloc(strlen(p)+1);
+ pstrcpy(product, strlen(p)+1, p);
+ desc_strings[STR_PRODUCT] = product;
+ }
+ else if (strstart(comp, "serial=", &p)) {
+ char* serial = malloc(strlen(p)+1);
+ pstrcpy(serial, strlen(p)+1, p);
+ desc_strings[STR_SERIALNUMBER] = serial;
+ }
+ else if (index(comp, (int) subdelim) != NULL) {
error_report("unrecognized USB mass-storage option %s", filename);
return NULL;
}
- filename = p1;
+ else {
+ filename = comp;
+ }
+ comp = strtok(NULL, &delim); //advance to next token
}
+
+
if (!*filename) {
error_report("block device specification needed");
return NULL;