Commit fa879c641435bec4b79872ad14b9a90c8b7172f3

Authored by aliguori
1 parent ff4b91c2

add "serial" parameter to -drive flag (Gleb Natapov)

Windows calculates HW "uniqueness" based on a hard drive serial number
among other things. The patch allows to specify drive serial number
from a command line.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6214 c046a42c-6fe2-441c-8c8c-71466251a162
hw/ide.c
@@ -386,6 +386,7 @@ typedef struct IDEState { @@ -386,6 +386,7 @@ typedef struct IDEState {
386 PCIDevice *pci_dev; 386 PCIDevice *pci_dev;
387 struct BMDMAState *bmdma; 387 struct BMDMAState *bmdma;
388 int drive_serial; 388 int drive_serial;
  389 + char drive_serial_str[21];
389 /* ide regs */ 390 /* ide regs */
390 uint8_t feature; 391 uint8_t feature;
391 uint8_t error; 392 uint8_t error;
@@ -531,7 +532,6 @@ static void ide_identify(IDEState *s) @@ -531,7 +532,6 @@ static void ide_identify(IDEState *s)
531 { 532 {
532 uint16_t *p; 533 uint16_t *p;
533 unsigned int oldsize; 534 unsigned int oldsize;
534 - char buf[20];  
535 535
536 if (s->identify_set) { 536 if (s->identify_set) {
537 memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); 537 memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -546,8 +546,7 @@ static void ide_identify(IDEState *s) @@ -546,8 +546,7 @@ static void ide_identify(IDEState *s)
546 put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */ 546 put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
547 put_le16(p + 5, 512); /* XXX: retired, remove ? */ 547 put_le16(p + 5, 512); /* XXX: retired, remove ? */
548 put_le16(p + 6, s->sectors); 548 put_le16(p + 6, s->sectors);
549 - snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);  
550 - padstr((char *)(p + 10), buf, 20); /* serial number */ 549 + padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
551 put_le16(p + 20, 3); /* XXX: retired, remove ? */ 550 put_le16(p + 20, 3); /* XXX: retired, remove ? */
552 put_le16(p + 21, 512); /* cache size in sectors */ 551 put_le16(p + 21, 512); /* cache size in sectors */
553 put_le16(p + 22, 4); /* ecc bytes */ 552 put_le16(p + 22, 4); /* ecc bytes */
@@ -601,7 +600,6 @@ static void ide_identify(IDEState *s) @@ -601,7 +600,6 @@ static void ide_identify(IDEState *s)
601 static void ide_atapi_identify(IDEState *s) 600 static void ide_atapi_identify(IDEState *s)
602 { 601 {
603 uint16_t *p; 602 uint16_t *p;
604 - char buf[20];  
605 603
606 if (s->identify_set) { 604 if (s->identify_set) {
607 memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); 605 memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -612,8 +610,7 @@ static void ide_atapi_identify(IDEState *s) @@ -612,8 +610,7 @@ static void ide_atapi_identify(IDEState *s)
612 p = (uint16_t *)s->io_buffer; 610 p = (uint16_t *)s->io_buffer;
613 /* Removable CDROM, 50us response, 12 byte packets */ 611 /* Removable CDROM, 50us response, 12 byte packets */
614 put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0)); 612 put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
615 - snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);  
616 - padstr((char *)(p + 10), buf, 20); /* serial number */ 613 + padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
617 put_le16(p + 20, 3); /* buffer type */ 614 put_le16(p + 20, 3); /* buffer type */
618 put_le16(p + 21, 512); /* cache size in sectors */ 615 put_le16(p + 21, 512); /* cache size in sectors */
619 put_le16(p + 22, 4); /* ecc bytes */ 616 put_le16(p + 22, 4); /* ecc bytes */
@@ -652,7 +649,6 @@ static void ide_cfata_identify(IDEState *s) @@ -652,7 +649,6 @@ static void ide_cfata_identify(IDEState *s)
652 { 649 {
653 uint16_t *p; 650 uint16_t *p;
654 uint32_t cur_sec; 651 uint32_t cur_sec;
655 - char buf[20];  
656 652
657 p = (uint16_t *) s->identify_data; 653 p = (uint16_t *) s->identify_data;
658 if (s->identify_set) 654 if (s->identify_set)
@@ -668,8 +664,7 @@ static void ide_cfata_identify(IDEState *s) @@ -668,8 +664,7 @@ static void ide_cfata_identify(IDEState *s)
668 put_le16(p + 6, s->sectors); /* Default sectors per track */ 664 put_le16(p + 6, s->sectors); /* Default sectors per track */
669 put_le16(p + 7, s->nb_sectors >> 16); /* Sectors per card */ 665 put_le16(p + 7, s->nb_sectors >> 16); /* Sectors per card */
670 put_le16(p + 8, s->nb_sectors); /* Sectors per card */ 666 put_le16(p + 8, s->nb_sectors); /* Sectors per card */
671 - snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);  
672 - padstr((char *)(p + 10), buf, 20); /* Serial number in ASCII */ 667 + padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
673 put_le16(p + 22, 0x0004); /* ECC bytes */ 668 put_le16(p + 22, 0x0004); /* ECC bytes */
674 padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */ 669 padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */
675 padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */ 670 padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
@@ -2714,6 +2709,11 @@ static void ide_init2(IDEState *ide_state, @@ -2714,6 +2709,11 @@ static void ide_init2(IDEState *ide_state,
2714 } 2709 }
2715 } 2710 }
2716 s->drive_serial = drive_serial++; 2711 s->drive_serial = drive_serial++;
  2712 + strncpy(s->drive_serial_str, drive_get_serial(s->bs),
  2713 + sizeof(s->drive_serial_str));
  2714 + if (strlen(s->drive_serial_str) == 0)
  2715 + snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
  2716 + "QM%05d", s->drive_serial);
2717 s->irq = irq; 2717 s->irq = irq;
2718 s->sector_write_timer = qemu_new_timer(vm_clock, 2718 s->sector_write_timer = qemu_new_timer(vm_clock,
2719 ide_sector_write_timer_cb, s); 2719 ide_sector_write_timer_cb, s);
hw/scsi-disk.c
@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
13 * the host adapter emulator. 13 * the host adapter emulator.
14 */ 14 */
15 15
  16 +#include <qemu-common.h>
  17 +#include <sysemu.h>
16 //#define DEBUG_SCSI 18 //#define DEBUG_SCSI
17 19
18 #ifdef DEBUG_SCSI 20 #ifdef DEBUG_SCSI
@@ -68,6 +70,7 @@ struct SCSIDeviceState @@ -68,6 +70,7 @@ struct SCSIDeviceState
68 or from the AIO completion routines. */ 70 or from the AIO completion routines. */
69 scsi_completionfn completion; 71 scsi_completionfn completion;
70 void *opaque; 72 void *opaque;
  73 + char drive_serial_str[21];
71 }; 74 };
72 75
73 /* Global pool of SCSIRequest structures. */ 76 /* Global pool of SCSIRequest structures. */
@@ -408,6 +411,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -408,6 +411,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
408 break; 411 break;
409 case 0x80: 412 case 0x80:
410 { 413 {
  414 + int l;
  415 +
411 /* Device serial number, optional */ 416 /* Device serial number, optional */
412 if (len < 4) { 417 if (len < 4) {
413 BADF("Error: EVPD[Serial number] Inquiry buffer " 418 BADF("Error: EVPD[Serial number] Inquiry buffer "
@@ -416,6 +421,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -416,6 +421,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
416 } 421 }
417 422
418 DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len); 423 DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
  424 + l = MIN(len, strlen(s->drive_serial_str));
419 425
420 r->buf_len = 0; 426 r->buf_len = 0;
421 427
@@ -428,9 +434,9 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, @@ -428,9 +434,9 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
428 434
429 outbuf[r->buf_len++] = 0x80; // this page 435 outbuf[r->buf_len++] = 0x80; // this page
430 outbuf[r->buf_len++] = 0x00; 436 outbuf[r->buf_len++] = 0x00;
431 - outbuf[r->buf_len++] = 0x01; // 1 byte data follow  
432 -  
433 - outbuf[r->buf_len++] = '0'; // 1 byte data follow 437 + outbuf[r->buf_len++] = l;
  438 + memcpy(&outbuf[r->buf_len], s->drive_serial_str, l);
  439 + r->buf_len += l;
434 } 440 }
435 441
436 break; 442 break;
@@ -812,7 +818,10 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq, @@ -812,7 +818,10 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
812 } else { 818 } else {
813 s->cluster_size = 1; 819 s->cluster_size = 1;
814 } 820 }
815 - 821 + strncpy(s->drive_serial_str, drive_get_serial(s->bdrv),
  822 + sizeof(s->drive_serial_str));
  823 + if (strlen(s->drive_serial_str) == 0)
  824 + strcpy(s->drive_serial_str, "0");
816 d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice)); 825 d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
817 d->state = s; 826 d->state = s;
818 d->destroy = scsi_destroy; 827 d->destroy = scsi_destroy;
qemu-doc.texi
@@ -274,6 +274,8 @@ These options have the same definition as they have in @option{-hdachs}. @@ -274,6 +274,8 @@ These options have the same definition as they have in @option{-hdachs}.
274 Specify which disk @var{format} will be used rather than detecting 274 Specify which disk @var{format} will be used rather than detecting
275 the format. Can be used to specifiy format=raw to avoid interpreting 275 the format. Can be used to specifiy format=raw to avoid interpreting
276 an untrusted format header. 276 an untrusted format header.
  277 +@item serial=@var{serial}
  278 +This option specifies the serial number to assign to the device.
277 @end table 279 @end table
278 280
279 By default, writethrough caching is used for all block device. This means that 281 By default, writethrough caching is used for all block device. This means that
sysemu.h
@@ -131,6 +131,7 @@ typedef struct DriveInfo { @@ -131,6 +131,7 @@ typedef struct DriveInfo {
131 BlockInterfaceType type; 131 BlockInterfaceType type;
132 int bus; 132 int bus;
133 int unit; 133 int unit;
  134 + char serial[21];
134 } DriveInfo; 135 } DriveInfo;
135 136
136 #define MAX_IDE_DEVS 2 137 #define MAX_IDE_DEVS 2
@@ -142,6 +143,7 @@ extern DriveInfo drives_table[MAX_DRIVES+1]; @@ -142,6 +143,7 @@ extern DriveInfo drives_table[MAX_DRIVES+1];
142 143
143 extern int drive_get_index(BlockInterfaceType type, int bus, int unit); 144 extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
144 extern int drive_get_max_bus(BlockInterfaceType type); 145 extern int drive_get_max_bus(BlockInterfaceType type);
  146 +extern const char *drive_get_serial(BlockDriverState *bdrv);
145 147
146 /* serial ports */ 148 /* serial ports */
147 149
@@ -2196,6 +2196,17 @@ int drive_get_max_bus(BlockInterfaceType type) @@ -2196,6 +2196,17 @@ int drive_get_max_bus(BlockInterfaceType type)
2196 return max_bus; 2196 return max_bus;
2197 } 2197 }
2198 2198
  2199 +const char *drive_get_serial(BlockDriverState *bdrv)
  2200 +{
  2201 + int index;
  2202 +
  2203 + for (index = 0; index < nb_drives; index++)
  2204 + if (drives_table[index].bdrv == bdrv)
  2205 + return drives_table[index].serial;
  2206 +
  2207 + return "\0";
  2208 +}
  2209 +
2199 static void bdrv_format_print(void *opaque, const char *name) 2210 static void bdrv_format_print(void *opaque, const char *name)
2200 { 2211 {
2201 fprintf(stderr, " %s", name); 2212 fprintf(stderr, " %s", name);
@@ -2207,6 +2218,7 @@ static int drive_init(struct drive_opt *arg, int snapshot, @@ -2207,6 +2218,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
2207 char buf[128]; 2218 char buf[128];
2208 char file[1024]; 2219 char file[1024];
2209 char devname[128]; 2220 char devname[128];
  2221 + char serial[21];
2210 const char *mediastr = ""; 2222 const char *mediastr = "";
2211 BlockInterfaceType type; 2223 BlockInterfaceType type;
2212 enum { MEDIA_DISK, MEDIA_CDROM } media; 2224 enum { MEDIA_DISK, MEDIA_CDROM } media;
@@ -2222,7 +2234,7 @@ static int drive_init(struct drive_opt *arg, int snapshot, @@ -2222,7 +2234,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
2222 static const char * const params[] = { "bus", "unit", "if", "index", 2234 static const char * const params[] = { "bus", "unit", "if", "index",
2223 "cyls", "heads", "secs", "trans", 2235 "cyls", "heads", "secs", "trans",
2224 "media", "snapshot", "file", 2236 "media", "snapshot", "file",
2225 - "cache", "format", NULL }; 2237 + "cache", "format", "serial", NULL };
2226 2238
2227 if (check_params(buf, sizeof(buf), params, str) < 0) { 2239 if (check_params(buf, sizeof(buf), params, str) < 0) {
2228 fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n", 2240 fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
@@ -2409,6 +2421,9 @@ static int drive_init(struct drive_opt *arg, int snapshot, @@ -2409,6 +2421,9 @@ static int drive_init(struct drive_opt *arg, int snapshot,
2409 else 2421 else
2410 pstrcpy(file, sizeof(file), arg->file); 2422 pstrcpy(file, sizeof(file), arg->file);
2411 2423
  2424 + if (!get_param_value(serial, sizeof(serial), "serial", str))
  2425 + memset(serial, 0, sizeof(serial));
  2426 +
2412 /* compute bus and unit according index */ 2427 /* compute bus and unit according index */
2413 2428
2414 if (index != -1) { 2429 if (index != -1) {
@@ -2472,6 +2487,7 @@ static int drive_init(struct drive_opt *arg, int snapshot, @@ -2472,6 +2487,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
2472 drives_table[nb_drives].type = type; 2487 drives_table[nb_drives].type = type;
2473 drives_table[nb_drives].bus = bus_id; 2488 drives_table[nb_drives].bus = bus_id;
2474 drives_table[nb_drives].unit = unit_id; 2489 drives_table[nb_drives].unit = unit_id;
  2490 + strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
2475 nb_drives++; 2491 nb_drives++;
2476 2492
2477 switch(type) { 2493 switch(type) {
@@ -3826,7 +3842,7 @@ static void help(int exitcode) @@ -3826,7 +3842,7 @@ static void help(int exitcode)
3826 "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" 3842 "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
3827 "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n" 3843 "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
3828 " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n" 3844 " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
3829 - " [,cache=writethrough|writeback|none][,format=f]\n" 3845 + " [,cache=writethrough|writeback|none][,format=f][,serial=s]\n"
3830 " use 'file' as a drive image\n" 3846 " use 'file' as a drive image\n"
3831 "-mtdblock file use 'file' as on-board Flash memory image\n" 3847 "-mtdblock file use 'file' as on-board Flash memory image\n"
3832 "-sd file use 'file' as SecureDigital card image\n" 3848 "-sd file use 'file' as SecureDigital card image\n"