mirror of https://github.com/xqemu/xqemu.git
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
This commit is contained in:
parent
ff4b91c2f7
commit
fa879c6414
18
hw/ide.c
18
hw/ide.c
|
@ -386,6 +386,7 @@ typedef struct IDEState {
|
||||||
PCIDevice *pci_dev;
|
PCIDevice *pci_dev;
|
||||||
struct BMDMAState *bmdma;
|
struct BMDMAState *bmdma;
|
||||||
int drive_serial;
|
int drive_serial;
|
||||||
|
char drive_serial_str[21];
|
||||||
/* ide regs */
|
/* ide regs */
|
||||||
uint8_t feature;
|
uint8_t feature;
|
||||||
uint8_t error;
|
uint8_t error;
|
||||||
|
@ -531,7 +532,6 @@ static void ide_identify(IDEState *s)
|
||||||
{
|
{
|
||||||
uint16_t *p;
|
uint16_t *p;
|
||||||
unsigned int oldsize;
|
unsigned int oldsize;
|
||||||
char buf[20];
|
|
||||||
|
|
||||||
if (s->identify_set) {
|
if (s->identify_set) {
|
||||||
memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
|
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 + 4, 512 * s->sectors); /* XXX: retired, remove ? */
|
||||||
put_le16(p + 5, 512); /* XXX: retired, remove ? */
|
put_le16(p + 5, 512); /* XXX: retired, remove ? */
|
||||||
put_le16(p + 6, s->sectors);
|
put_le16(p + 6, s->sectors);
|
||||||
snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
|
padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
|
||||||
padstr((char *)(p + 10), buf, 20); /* serial number */
|
|
||||||
put_le16(p + 20, 3); /* XXX: retired, remove ? */
|
put_le16(p + 20, 3); /* XXX: retired, remove ? */
|
||||||
put_le16(p + 21, 512); /* cache size in sectors */
|
put_le16(p + 21, 512); /* cache size in sectors */
|
||||||
put_le16(p + 22, 4); /* ecc bytes */
|
put_le16(p + 22, 4); /* ecc bytes */
|
||||||
|
@ -601,7 +600,6 @@ static void ide_identify(IDEState *s)
|
||||||
static void ide_atapi_identify(IDEState *s)
|
static void ide_atapi_identify(IDEState *s)
|
||||||
{
|
{
|
||||||
uint16_t *p;
|
uint16_t *p;
|
||||||
char buf[20];
|
|
||||||
|
|
||||||
if (s->identify_set) {
|
if (s->identify_set) {
|
||||||
memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
|
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;
|
p = (uint16_t *)s->io_buffer;
|
||||||
/* Removable CDROM, 50us response, 12 byte packets */
|
/* Removable CDROM, 50us response, 12 byte packets */
|
||||||
put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
|
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), s->drive_serial_str, 20); /* serial number */
|
||||||
padstr((char *)(p + 10), buf, 20); /* serial number */
|
|
||||||
put_le16(p + 20, 3); /* buffer type */
|
put_le16(p + 20, 3); /* buffer type */
|
||||||
put_le16(p + 21, 512); /* cache size in sectors */
|
put_le16(p + 21, 512); /* cache size in sectors */
|
||||||
put_le16(p + 22, 4); /* ecc bytes */
|
put_le16(p + 22, 4); /* ecc bytes */
|
||||||
|
@ -652,7 +649,6 @@ static void ide_cfata_identify(IDEState *s)
|
||||||
{
|
{
|
||||||
uint16_t *p;
|
uint16_t *p;
|
||||||
uint32_t cur_sec;
|
uint32_t cur_sec;
|
||||||
char buf[20];
|
|
||||||
|
|
||||||
p = (uint16_t *) s->identify_data;
|
p = (uint16_t *) s->identify_data;
|
||||||
if (s->identify_set)
|
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 + 6, s->sectors); /* Default sectors per track */
|
||||||
put_le16(p + 7, s->nb_sectors >> 16); /* Sectors per card */
|
put_le16(p + 7, s->nb_sectors >> 16); /* Sectors per card */
|
||||||
put_le16(p + 8, s->nb_sectors); /* 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), s->drive_serial_str, 20); /* serial number */
|
||||||
padstr((char *)(p + 10), buf, 20); /* Serial number in ASCII */
|
|
||||||
put_le16(p + 22, 0x0004); /* ECC bytes */
|
put_le16(p + 22, 0x0004); /* ECC bytes */
|
||||||
padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */
|
padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */
|
||||||
padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
|
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++;
|
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->irq = irq;
|
||||||
s->sector_write_timer = qemu_new_timer(vm_clock,
|
s->sector_write_timer = qemu_new_timer(vm_clock,
|
||||||
ide_sector_write_timer_cb, s);
|
ide_sector_write_timer_cb, s);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
* the host adapter emulator.
|
* the host adapter emulator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <qemu-common.h>
|
||||||
|
#include <sysemu.h>
|
||||||
//#define DEBUG_SCSI
|
//#define DEBUG_SCSI
|
||||||
|
|
||||||
#ifdef DEBUG_SCSI
|
#ifdef DEBUG_SCSI
|
||||||
|
@ -68,6 +70,7 @@ struct SCSIDeviceState
|
||||||
or from the AIO completion routines. */
|
or from the AIO completion routines. */
|
||||||
scsi_completionfn completion;
|
scsi_completionfn completion;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
char drive_serial_str[21];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Global pool of SCSIRequest structures. */
|
/* Global pool of SCSIRequest structures. */
|
||||||
|
@ -408,6 +411,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
|
||||||
break;
|
break;
|
||||||
case 0x80:
|
case 0x80:
|
||||||
{
|
{
|
||||||
|
int l;
|
||||||
|
|
||||||
/* Device serial number, optional */
|
/* Device serial number, optional */
|
||||||
if (len < 4) {
|
if (len < 4) {
|
||||||
BADF("Error: EVPD[Serial number] Inquiry buffer "
|
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);
|
DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len);
|
||||||
|
l = MIN(len, strlen(s->drive_serial_str));
|
||||||
|
|
||||||
r->buf_len = 0;
|
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++] = 0x80; // this page
|
||||||
outbuf[r->buf_len++] = 0x00;
|
outbuf[r->buf_len++] = 0x00;
|
||||||
outbuf[r->buf_len++] = 0x01; // 1 byte data follow
|
outbuf[r->buf_len++] = l;
|
||||||
|
memcpy(&outbuf[r->buf_len], s->drive_serial_str, l);
|
||||||
outbuf[r->buf_len++] = '0'; // 1 byte data follow
|
r->buf_len += l;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -812,7 +818,10 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
|
||||||
} else {
|
} else {
|
||||||
s->cluster_size = 1;
|
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 = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
|
||||||
d->state = s;
|
d->state = s;
|
||||||
d->destroy = scsi_destroy;
|
d->destroy = scsi_destroy;
|
||||||
|
|
|
@ -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
|
Specify which disk @var{format} will be used rather than detecting
|
||||||
the format. Can be used to specifiy format=raw to avoid interpreting
|
the format. Can be used to specifiy format=raw to avoid interpreting
|
||||||
an untrusted format header.
|
an untrusted format header.
|
||||||
|
@item serial=@var{serial}
|
||||||
|
This option specifies the serial number to assign to the device.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
By default, writethrough caching is used for all block device. This means that
|
By default, writethrough caching is used for all block device. This means that
|
||||||
|
|
2
sysemu.h
2
sysemu.h
|
@ -131,6 +131,7 @@ typedef struct DriveInfo {
|
||||||
BlockInterfaceType type;
|
BlockInterfaceType type;
|
||||||
int bus;
|
int bus;
|
||||||
int unit;
|
int unit;
|
||||||
|
char serial[21];
|
||||||
} DriveInfo;
|
} DriveInfo;
|
||||||
|
|
||||||
#define MAX_IDE_DEVS 2
|
#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_index(BlockInterfaceType type, int bus, int unit);
|
||||||
extern int drive_get_max_bus(BlockInterfaceType type);
|
extern int drive_get_max_bus(BlockInterfaceType type);
|
||||||
|
extern const char *drive_get_serial(BlockDriverState *bdrv);
|
||||||
|
|
||||||
/* serial ports */
|
/* serial ports */
|
||||||
|
|
||||||
|
|
20
vl.c
20
vl.c
|
@ -2196,6 +2196,17 @@ int drive_get_max_bus(BlockInterfaceType type)
|
||||||
return max_bus;
|
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)
|
static void bdrv_format_print(void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr, " %s", name);
|
fprintf(stderr, " %s", name);
|
||||||
|
@ -2207,6 +2218,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
|
||||||
char buf[128];
|
char buf[128];
|
||||||
char file[1024];
|
char file[1024];
|
||||||
char devname[128];
|
char devname[128];
|
||||||
|
char serial[21];
|
||||||
const char *mediastr = "";
|
const char *mediastr = "";
|
||||||
BlockInterfaceType type;
|
BlockInterfaceType type;
|
||||||
enum { MEDIA_DISK, MEDIA_CDROM } media;
|
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",
|
static const char * const params[] = { "bus", "unit", "if", "index",
|
||||||
"cyls", "heads", "secs", "trans",
|
"cyls", "heads", "secs", "trans",
|
||||||
"media", "snapshot", "file",
|
"media", "snapshot", "file",
|
||||||
"cache", "format", NULL };
|
"cache", "format", "serial", NULL };
|
||||||
|
|
||||||
if (check_params(buf, sizeof(buf), params, str) < 0) {
|
if (check_params(buf, sizeof(buf), params, str) < 0) {
|
||||||
fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
|
fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
|
||||||
|
@ -2409,6 +2421,9 @@ static int drive_init(struct drive_opt *arg, int snapshot,
|
||||||
else
|
else
|
||||||
pstrcpy(file, sizeof(file), arg->file);
|
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 */
|
/* compute bus and unit according index */
|
||||||
|
|
||||||
if (index != -1) {
|
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].type = type;
|
||||||
drives_table[nb_drives].bus = bus_id;
|
drives_table[nb_drives].bus = bus_id;
|
||||||
drives_table[nb_drives].unit = unit_id;
|
drives_table[nb_drives].unit = unit_id;
|
||||||
|
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
|
||||||
nb_drives++;
|
nb_drives++;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
@ -3826,7 +3842,7 @@ static void help(int exitcode)
|
||||||
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
|
"-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"
|
"-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"
|
" [,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"
|
" use 'file' as a drive image\n"
|
||||||
"-mtdblock file use 'file' as on-board Flash memory image\n"
|
"-mtdblock file use 'file' as on-board Flash memory image\n"
|
||||||
"-sd file use 'file' as SecureDigital card image\n"
|
"-sd file use 'file' as SecureDigital card image\n"
|
||||||
|
|
Loading…
Reference in New Issue