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" | ... | ... |