Skip to contentSkip to conversation

add "serial" parameter to -drive flag

PATCH Superseded Gleb Natapov 2 participants 5 messages Dec 23, 2008

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add "serial" parameter to -drive flag

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.

hw/ide.c +8 -9
index 69ab773..f32435a 100644
@@ -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,10 @@ 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)
+            sprintf(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);
hw/scsi-disk.c +13 -4
index 9a08411..4c4b921 100644
@@ -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;
qemu-doc.texi +2 -0
index 698e0d5..7bfacbd 100644
@@ -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.
+@item serial=@var{serial}
+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
sysemu.h +2 -0
index 94cffaf..7228df0 100644
@@ -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 */
 
vl.c +18 -2
index a1a9cf4..e14210b 100644
@@ -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.

#1 lore raw
Quoted 6 lines · 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.

Quoted 7 lines

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

+ sprintf(s->drive_serial_str, "QM%05d", s->drive_serial);

You better watch out, this degrades snprintf to sprintf.

#2 lore raw
Quoted 9 lines · Blue Swirl
Quoted 7 lines · 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.

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

Quoted 8 lines
Quoted 5 lines

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

+ sprintf(s->drive_serial_str, "QM%05d", s->drive_serial);

You better watch out, this degrades snprintf to sprintf.

I can use snprintf, but in this case we know exactly the length of the resulting string.

--
Gleb.

#3 lore raw
Quoted 14 lines · Gleb Natapov
Quoted 13 lines · Blue Swirl
Quoted 11 lines · 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.

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

+ sprintf(s->drive_serial_str, "QM%05d", s->drive_serial);

You better watch out, this degrades snprintf to sprintf.

I can use snprintf, but in this case we know exactly the length of the
resulting string.

True, but OpenBSD linker issues warnings when sprintf and friends are used.

#4 lore raw
Quoted 17 lines · Blue Swirl
Quoted 16 lines · Gleb Natapov
Quoted 15 lines · Blue Swirl
Quoted 13 lines · 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.

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);

+ sprintf(s->drive_serial_str, "QM%05d", s->drive_serial);

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

You better watch out, this degrades snprintf to sprintf.

I can use snprintf, but in this case we know exactly the length of the
resulting string.

True, but OpenBSD linker issues warnings when sprintf and friends are used.

Ah. Will fix.

--
Gleb.