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