Commit fa879c641435bec4b79872ad14b9a90c8b7172f3
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
Showing
5 changed files
with
44 additions
and
15 deletions
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 | ... | ... |
vl.c
... | ... | @@ -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" | ... | ... |