a12214d1c4
Commit30896374
started to pass the full BlockConf from usb-storage to scsi-disk, while previously only a few select properties would be forwarded. This enables the user to set more properties, e.g. the block size, that are actually taking effect. However, now the calls to blkconf_apply_backend_options() and blkconf_blocksizes() in usb_msd_storage_realize() that modify some of these properties take effect, too, instead of being silently ignored. This means at least that the block sizes get an unconditional default of 512 bytes before the configuration is passed to scsi-disk. Before commit30896374
, the property wouldn't be set for scsi-disk and therefore the device dependent defaults would apply - 512 for scsi-hd, but 2048 for scsi-cd. The latter default has now become 512, too, which makes at least Windows 11 installation fail when installing from usb-storage. Fix this by simply not calling these functions any more in usb-storage and passing BlockConf on unmodified (except for the BlockBackend). The same functions are called by the SCSI code anyway and it sets the right defaults for the actual media type. Fixes:3089637461
('scsi: Don't ignore most usb-storage properties') Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2260 Reported-by: Jonas Svensson Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Hanna Czenczek <hreitz@redhat.com> Message-id: 20240412144202.13786-1-kwolf@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
145 lines
4.1 KiB
C
145 lines
4.1 KiB
C
/*
|
|
* USB Mass Storage Device emulation
|
|
*
|
|
* Copyright (c) 2006 CodeSourcery.
|
|
* Written by Paul Brook
|
|
*
|
|
* This code is licensed under the LGPL.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "qapi/visitor.h"
|
|
#include "hw/usb.h"
|
|
#include "hw/usb/desc.h"
|
|
#include "hw/usb/msd.h"
|
|
#include "sysemu/sysemu.h"
|
|
#include "sysemu/block-backend.h"
|
|
|
|
static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
|
|
.tcq = false,
|
|
.max_target = 0,
|
|
.max_lun = 0,
|
|
|
|
.transfer_data = usb_msd_transfer_data,
|
|
.complete = usb_msd_command_complete,
|
|
.cancel = usb_msd_request_cancelled,
|
|
.load_request = usb_msd_load_request,
|
|
};
|
|
|
|
static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
|
|
{
|
|
MSDState *s = USB_STORAGE_DEV(dev);
|
|
BlockBackend *blk = s->conf.blk;
|
|
SCSIDevice *scsi_dev;
|
|
|
|
if (!blk) {
|
|
error_setg(errp, "drive property not set");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Hack alert: this pretends to be a block device, but it's really
|
|
* a SCSI bus that can serve only a single device, which it
|
|
* creates automatically. But first it needs to detach from its
|
|
* blockdev, or else scsi_bus_legacy_add_drive() dies when it
|
|
* attaches again. We also need to take another reference so that
|
|
* blk_detach_dev() doesn't free blk while we still need it.
|
|
*
|
|
* The hack is probably a bad idea.
|
|
*/
|
|
blk_ref(blk);
|
|
blk_detach_dev(blk, DEVICE(s));
|
|
s->conf.blk = NULL;
|
|
|
|
usb_desc_create_serial(dev);
|
|
usb_desc_init(dev);
|
|
dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
|
|
scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev),
|
|
&usb_msd_scsi_info_storage);
|
|
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
|
|
&s->conf, dev->serial, errp);
|
|
blk_unref(blk);
|
|
if (!scsi_dev) {
|
|
return;
|
|
}
|
|
usb_msd_handle_reset(dev);
|
|
s->scsi_dev = scsi_dev;
|
|
}
|
|
|
|
static Property msd_properties[] = {
|
|
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
|
|
DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
|
|
DEFINE_PROP_BOOL("removable", MSDState, removable, false),
|
|
DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false),
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
};
|
|
|
|
static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
|
|
{
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
|
|
|
uc->realize = usb_msd_storage_realize;
|
|
device_class_set_props(dc, msd_properties);
|
|
}
|
|
|
|
static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
|
|
void *opaque, Error **errp)
|
|
{
|
|
USBDevice *dev = USB_DEVICE(obj);
|
|
MSDState *s = USB_STORAGE_DEV(dev);
|
|
|
|
visit_type_int32(v, name, &s->conf.bootindex, errp);
|
|
}
|
|
|
|
static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
|
|
void *opaque, Error **errp)
|
|
{
|
|
USBDevice *dev = USB_DEVICE(obj);
|
|
MSDState *s = USB_STORAGE_DEV(dev);
|
|
int32_t boot_index;
|
|
Error *local_err = NULL;
|
|
|
|
if (!visit_type_int32(v, name, &boot_index, errp)) {
|
|
return;
|
|
}
|
|
/* check whether bootindex is present in fw_boot_order list */
|
|
check_boot_index(boot_index, &local_err);
|
|
if (local_err) {
|
|
goto out;
|
|
}
|
|
/* change bootindex to a new one */
|
|
s->conf.bootindex = boot_index;
|
|
|
|
if (s->scsi_dev) {
|
|
object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index,
|
|
&error_abort);
|
|
}
|
|
|
|
out:
|
|
error_propagate(errp, local_err);
|
|
}
|
|
|
|
static void usb_msd_instance_init(Object *obj)
|
|
{
|
|
object_property_add(obj, "bootindex", "int32",
|
|
usb_msd_get_bootindex,
|
|
usb_msd_set_bootindex, NULL, NULL);
|
|
object_property_set_int(obj, "bootindex", -1, NULL);
|
|
}
|
|
|
|
static const TypeInfo msd_info = {
|
|
.name = "usb-storage",
|
|
.parent = TYPE_USB_STORAGE,
|
|
.class_init = usb_msd_class_storage_initfn,
|
|
.instance_init = usb_msd_instance_init,
|
|
};
|
|
|
|
static void register_types(void)
|
|
{
|
|
type_register_static(&msd_info);
|
|
}
|
|
|
|
type_init(register_types)
|