qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] add "serial" parameter to -drive flag


From: Gleb Natapov
Subject: [Qemu-devel] [PATCH v2] add "serial" parameter to -drive flag
Date: Wed, 24 Dec 2008 09:29:06 +0200

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 <address@hidden>

diff --git a/hw/ide.c b/hw/ide.c
index 69ab773..34b1482 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -386,6 +386,7 @@ typedef struct IDEState {
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
+    char drive_serial_str[21];
     /* ide regs */
     uint8_t feature;
     uint8_t error;
@@ -531,7 +532,6 @@ static void ide_identify(IDEState *s)
 {
     uint16_t *p;
     unsigned int oldsize;
-    char buf[20];
 
     if (s->identify_set) {
        memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -546,8 +546,7 @@ static void ide_identify(IDEState *s)
     put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
     put_le16(p + 5, 512); /* XXX: retired, remove ? */
     put_le16(p + 6, s->sectors);
-    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
-    padstr((char *)(p + 10), buf, 20); /* serial number */
+    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
     put_le16(p + 20, 3); /* XXX: retired, remove ? */
     put_le16(p + 21, 512); /* cache size in sectors */
     put_le16(p + 22, 4); /* ecc bytes */
@@ -601,7 +600,6 @@ static void ide_identify(IDEState *s)
 static void ide_atapi_identify(IDEState *s)
 {
     uint16_t *p;
-    char buf[20];
 
     if (s->identify_set) {
        memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -612,8 +610,7 @@ static void ide_atapi_identify(IDEState *s)
     p = (uint16_t *)s->io_buffer;
     /* Removable CDROM, 50us response, 12 byte packets */
     put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
-    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
-    padstr((char *)(p + 10), buf, 20); /* serial number */
+    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
     put_le16(p + 20, 3); /* buffer type */
     put_le16(p + 21, 512); /* cache size in sectors */
     put_le16(p + 22, 4); /* ecc bytes */
@@ -652,7 +649,6 @@ static void ide_cfata_identify(IDEState *s)
 {
     uint16_t *p;
     uint32_t cur_sec;
-    char buf[20];
 
     p = (uint16_t *) s->identify_data;
     if (s->identify_set)
@@ -668,8 +664,7 @@ static void ide_cfata_identify(IDEState *s)
     put_le16(p + 6, s->sectors);               /* Default sectors per track */
     put_le16(p + 7, s->nb_sectors >> 16);      /* Sectors per card */
     put_le16(p + 8, s->nb_sectors);            /* Sectors per card */
-    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
-    padstr((char *)(p + 10), buf, 20); /* Serial number in ASCII */
+    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
     put_le16(p + 22, 0x0004);                  /* ECC bytes */
     padstr((char *) (p + 23), QEMU_VERSION, 8);        /* Firmware Revision */
     padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
@@ -2714,6 +2709,11 @@ static void ide_init2(IDEState *ide_state,
             }
         }
         s->drive_serial = drive_serial++;
+        strncpy(s->drive_serial_str, drive_get_serial(s->bs),
+                sizeof(s->drive_serial_str));
+        if (strlen(s->drive_serial_str) == 0)
+            snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
+                    "QM%05d", s->drive_serial);
         s->irq = irq;
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 9a08411..4c4b921 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -13,6 +13,8 @@
  * the host adapter emulator.
  */
 
+#include <qemu-common.h>
+#include <sysemu.h>
 //#define DEBUG_SCSI
 
 #ifdef DEBUG_SCSI
@@ -68,6 +70,7 @@ struct SCSIDeviceState
        or from the AIO completion routines.  */
     scsi_completionfn completion;
     void *opaque;
+    char drive_serial_str[21];
 };
 
 /* Global pool of SCSIRequest structures.  */
@@ -408,6 +411,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t 
tag,
                     break;
                 case 0x80:
                     {
+                        int l;
+
                         /* Device serial number, optional */
                         if (len < 4) {
                             BADF("Error: EVPD[Serial number] Inquiry buffer "
@@ -416,6 +421,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t 
tag,
                         }
 
                         DPRINTF("Inquiry EVPD[Serial number] buffer size 
%d\n", len);
+                        l = MIN(len, strlen(s->drive_serial_str));
 
                         r->buf_len = 0;
 
@@ -428,9 +434,9 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t 
tag,
 
                         outbuf[r->buf_len++] = 0x80; // this page
                         outbuf[r->buf_len++] = 0x00;
-                        outbuf[r->buf_len++] = 0x01; // 1 byte data follow
-
-                        outbuf[r->buf_len++] = '0';  // 1 byte data follow 
+                        outbuf[r->buf_len++] = l;
+                        memcpy(&outbuf[r->buf_len], s->drive_serial_str, l);
+                        r->buf_len += l;
                     }
 
                     break;
@@ -812,7 +818,10 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
     } else {
         s->cluster_size = 1;
     }
-
+    strncpy(s->drive_serial_str, drive_get_serial(s->bdrv),
+            sizeof(s->drive_serial_str));
+    if (strlen(s->drive_serial_str) == 0)
+        strcpy(s->drive_serial_str, "0"); 
     d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
     d->state = s;
     d->destroy = scsi_destroy;
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 698e0d5..7bfacbd 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -274,6 +274,8 @@ These options have the same definition as they have in 
@option{-hdachs}.
 Specify which disk @var{format} will be used rather than detecting
 the format.  Can be used to specifiy format=raw to avoid interpreting
 an untrusted format header.
address@hidden address@hidden
+This option specifies the serial number to assign to the device.
 @end table
 
 By default, writethrough caching is used for all block device.  This means that
diff --git a/sysemu.h b/sysemu.h
index 94cffaf..7228df0 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -131,6 +131,7 @@ typedef struct DriveInfo {
     BlockInterfaceType type;
     int bus;
     int unit;
+    char serial[21];
 } DriveInfo;
 
 #define MAX_IDE_DEVS   2
@@ -142,6 +143,7 @@ extern DriveInfo drives_table[MAX_DRIVES+1];
 
 extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
 extern int drive_get_max_bus(BlockInterfaceType type);
+extern const char *drive_get_serial(BlockDriverState *bdrv);
 
 /* serial ports */
 
diff --git a/vl.c b/vl.c
index a1a9cf4..e14210b 100644
--- a/vl.c
+++ b/vl.c
@@ -2196,6 +2196,17 @@ int drive_get_max_bus(BlockInterfaceType type)
     return max_bus;
 }
 
+const char *drive_get_serial(BlockDriverState *bdrv)
+{
+    int index;
+
+    for (index = 0; index < nb_drives; index++)
+        if (drives_table[index].bdrv == bdrv)
+            return drives_table[index].serial;
+
+    return "\0";
+}
+
 static void bdrv_format_print(void *opaque, const char *name)
 {
     fprintf(stderr, " %s", name);
@@ -2207,6 +2218,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
     char buf[128];
     char file[1024];
     char devname[128];
+    char serial[21];
     const char *mediastr = "";
     BlockInterfaceType type;
     enum { MEDIA_DISK, MEDIA_CDROM } media;
@@ -2222,7 +2234,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
     static const char * const params[] = { "bus", "unit", "if", "index",
                                            "cyls", "heads", "secs", "trans",
                                            "media", "snapshot", "file",
-                                           "cache", "format", NULL };
+                                           "cache", "format", "serial", NULL };
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
@@ -2409,6 +2421,9 @@ static int drive_init(struct drive_opt *arg, int snapshot,
     else
         pstrcpy(file, sizeof(file), arg->file);
 
+    if (!get_param_value(serial, sizeof(serial), "serial", str))
+           memset(serial, 0,  sizeof(serial));
+
     /* compute bus and unit according index */
 
     if (index != -1) {
@@ -2472,6 +2487,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
     drives_table[nb_drives].type = type;
     drives_table[nb_drives].bus = bus_id;
     drives_table[nb_drives].unit = unit_id;
+    strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
     nb_drives++;
 
     switch(type) {
@@ -3826,7 +3842,7 @@ static void help(int exitcode)
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 
master)\n"
           "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
            "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
-           "       [,cache=writethrough|writeback|none][,format=f]\n"
+           "       
[,cache=writethrough|writeback|none][,format=f][,serial=s]\n"
           "                use 'file' as a drive image\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"
--
                        Gleb.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]