aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi/scsi-disk.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-07-14 18:14:12 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-07-14 18:14:12 +0100
commit285f64fcbf86dac2be6dbd0a8a32872bcff3cacb (patch)
tree1a30f398cbd4007b5ce8d955e24890eec84c90a6 /hw/scsi/scsi-disk.c
parent8482ab545e52f50facacfe1118b22b97462724ab (diff)
parentc0b3607d5938f5ee7fd16ff1e102afe938fd4b39 (diff)
downloadqemu-285f64fcbf86dac2be6dbd0a8a32872bcff3cacb.zip
qemu-285f64fcbf86dac2be6dbd0a8a32872bcff3cacb.tar.gz
qemu-285f64fcbf86dac2be6dbd0a8a32872bcff3cacb.tar.bz2
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* SCSI fuzzing fix (Mauro) * pre-install data files in the build directory (Akihiko) * SCSI fixes for Mac OS (Mark) # gpg: Signature made Wed 13 Jul 2022 15:59:00 BST # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: pc-bios/s390-ccw: add -Wno-array-bounds q800: add default vendor and product information for scsi-cd devices q800: add default vendor and product information for scsi-hd devices scsi-disk: allow MODE SELECT block descriptor to set the block size scsi-disk: allow the MODE_PAGE_R_W_ERROR AWRE bit to be changeable for CDROM drives q800: implement compat_props to enable quirk_mode_page_truncated for scsi-cd devices scsi-disk: add SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED quirk for Macintosh scsi-disk: add FORMAT UNIT command q800: implement compat_props to enable quirk_mode_page_vendor_specific_apple for scsi devices scsi-disk: add SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE quirk for Macintosh q800: implement compat_props to enable quirk_mode_sense_rom_use_dbd for scsi-cd devices scsi-disk: add SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD quirk for Macintosh q800: implement compat_props to enable quirk_mode_page_apple_vendor for scsi-cd devices scsi-disk: add MODE_PAGE_APPLE_VENDOR quirk for Macintosh scsi-disk: add new quirks bitmap to SCSIDiskState meson: Prefix each element of firmware path module: Use bundle mechanism datadir: Use bundle mechanism cutils: Introduce bundle mechanism scsi/lsi53c895a: really fix use-after-free in lsi_do_msgout (CVE-2022-0216) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/scsi/scsi-disk.c')
-rw-r--r--hw/scsi/scsi-disk.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 91acb5c..f5cdb9a 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -94,6 +94,7 @@ struct SCSIDiskState {
uint16_t port_index;
uint64_t max_unmap_size;
uint64_t max_io_size;
+ uint32_t quirks;
QEMUBH *bh;
char *version;
char *serial;
@@ -1078,12 +1079,14 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
int page_control)
{
static const int mode_sense_valid[0x3f] = {
+ [MODE_PAGE_VENDOR_SPECIFIC] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_HD_GEOMETRY] = (1 << TYPE_DISK),
[MODE_PAGE_FLEXIBLE_DISK_GEOMETRY] = (1 << TYPE_DISK),
[MODE_PAGE_CACHING] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_R_W_ERROR] = (1 << TYPE_DISK) | (1 << TYPE_ROM),
[MODE_PAGE_AUDIO_CTL] = (1 << TYPE_ROM),
[MODE_PAGE_CAPABILITIES] = (1 << TYPE_ROM),
+ [MODE_PAGE_APPLE_VENDOR] = (1 << TYPE_ROM),
};
uint8_t *p = *p_outbuf + 2;
@@ -1185,6 +1188,10 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
case MODE_PAGE_R_W_ERROR:
length = 10;
if (page_control == 1) { /* Changeable Values */
+ if (s->qdev.type == TYPE_ROM) {
+ /* Automatic Write Reallocation Enabled */
+ p[0] = 0x80;
+ }
break;
}
p[0] = 0x80; /* Automatic Write Reallocation Enabled */
@@ -1228,6 +1235,36 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
p[19] = (16 * 176) & 0xff;
break;
+ case MODE_PAGE_APPLE_VENDOR:
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR)) {
+ length = 0x1e;
+ if (page_control == 1) { /* Changeable Values */
+ break;
+ }
+
+ memset(p, 0, length);
+ strcpy((char *)p + 8, "APPLE COMPUTER, INC ");
+ break;
+ } else {
+ return -1;
+ }
+
+ case MODE_PAGE_VENDOR_SPECIFIC:
+ if (s->qdev.type == TYPE_DISK && (s->quirks &
+ (1 << SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE))) {
+ length = 0x2;
+ if (page_control == 1) { /* Changeable Values */
+ p[0] = 0xff;
+ p[1] = 0xff;
+ break;
+ }
+ p[0] = 0;
+ p[1] = 0;
+ break;
+ } else {
+ return -1;
+ }
+
default:
return -1;
}
@@ -1263,10 +1300,27 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
dev_specific_param |= 0x80; /* Readonly. */
}
} else {
- /* MMC prescribes that CD/DVD drives have no block descriptors,
- * and defines no device-specific parameter. */
- dev_specific_param = 0x00;
- dbd = true;
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD)) {
+ /* Use DBD from the request... */
+ dev_specific_param = 0x00;
+
+ /*
+ * ... unless we receive a request for MODE_PAGE_APPLE_VENDOR
+ * which should never return a block descriptor even though DBD is
+ * not set, otherwise CDROM detection fails in MacOS
+ */
+ if (s->quirks & (1 << SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR) &&
+ page == MODE_PAGE_APPLE_VENDOR) {
+ dbd = true;
+ }
+ } else {
+ /*
+ * MMC prescribes that CD/DVD drives have no block descriptors,
+ * and defines no device-specific parameter.
+ */
+ dev_specific_param = 0x00;
+ dbd = true;
+ }
}
if (r->req.cmd.buf[0] == MODE_SENSE) {
@@ -1502,7 +1556,10 @@ static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
goto invalid_param;
}
if (page_len > len) {
- goto invalid_param_len;
+ if (!(s->quirks & SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED)) {
+ goto invalid_param_len;
+ }
+ trace_scsi_disk_mode_select_page_truncated(page, page_len, len);
}
if (!change) {
@@ -1537,9 +1594,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
int bd_len;
int pass;
- /* We only support PF=1, SP=0. */
if ((r->req.cmd.buf[1] & 0x11) != 0x10) {
- goto invalid_field;
+ if (!(s->quirks &
+ (1 << SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE))) {
+ /* We only support PF=1, SP=0. */
+ goto invalid_field;
+ }
}
if (len < hdr_len) {
@@ -1556,6 +1616,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
goto invalid_param;
}
+ /* Allow changing the block size */
+ if (bd_len && p[6] != (s->qdev.blocksize >> 8)) {
+ s->qdev.blocksize = p[6] << 8;
+ trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
+ }
+
len -= bd_len;
p += bd_len;
@@ -2127,6 +2193,9 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
trace_scsi_disk_emulate_command_WRITE_SAME(
req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16, r->req.cmd.xfer);
break;
+ case FORMAT_UNIT:
+ trace_scsi_disk_emulate_command_FORMAT_UNIT(r->req.cmd.xfer);
+ break;
default:
trace_scsi_disk_emulate_command_UNKNOWN(buf[0],
scsi_command_name(buf[0]));
@@ -2532,6 +2601,7 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[VERIFY_10] = &scsi_disk_emulate_reqops,
[VERIFY_12] = &scsi_disk_emulate_reqops,
[VERIFY_16] = &scsi_disk_emulate_reqops,
+ [FORMAT_UNIT] = &scsi_disk_emulate_reqops,
[READ_6] = &scsi_disk_dma_reqops,
[READ_10] = &scsi_disk_dma_reqops,
@@ -3036,6 +3106,9 @@ static Property scsi_hd_properties[] = {
DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0),
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
5),
+ DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE,
+ 0),
DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -3084,6 +3157,15 @@ static Property scsi_cd_properties[] = {
DEFAULT_MAX_IO_SIZE),
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
5),
+ DEFINE_PROP_BIT("quirk_mode_page_apple_vendor", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR, 0),
+ DEFINE_PROP_BIT("quirk_mode_sense_rom_use_dbd", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD, 0),
+ DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState,
+ quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE,
+ 0),
+ DEFINE_PROP_BIT("quirk_mode_page_truncated", SCSIDiskState, quirks,
+ SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED, 0),
DEFINE_PROP_END_OF_LIST(),
};