mirror of https://gitee.com/openkylin/qemu.git
atapi: classify read_cd as conditionally returning data
For the purposes of byte_count_limit verification, add a new flag that identifies read_cd as sometimes returning data, then check the BCL in its command handler after we know that it will indeed return data. Reported-by: Hervé Poussineau <hpoussin@reactos.org> Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 1477970211-25754-2-git-send-email-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
parent
83c83f9a52
commit
e7bd708ec8
|
@ -637,6 +637,23 @@ static unsigned int event_status_media(IDEState *s,
|
||||||
return 8; /* We wrote to 4 extra bytes from the header */
|
return 8; /* We wrote to 4 extra bytes from the header */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before transferring data or otherwise signalling acceptance of a command
|
||||||
|
* marked CONDDATA, we must check the validity of the byte_count_limit.
|
||||||
|
*/
|
||||||
|
static bool validate_bcl(IDEState *s)
|
||||||
|
{
|
||||||
|
/* TODO: Check IDENTIFY data word 125 for defacult BCL (currently 0) */
|
||||||
|
if (s->atapi_dma || atapi_byte_count_limit(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Move abort back into core.c and introduce proper error flow between
|
||||||
|
* ATAPI layer and IDE core layer */
|
||||||
|
ide_abort_command(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void cmd_get_event_status_notification(IDEState *s,
|
static void cmd_get_event_status_notification(IDEState *s,
|
||||||
uint8_t *buf)
|
uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
@ -1028,12 +1045,19 @@ static void cmd_read_cd(IDEState *s, uint8_t* buf)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer_request = buf[9];
|
transfer_request = buf[9] & 0xf8;
|
||||||
switch(transfer_request & 0xf8) {
|
if (transfer_request == 0x00) {
|
||||||
case 0x00:
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
ide_atapi_cmd_ok(s);
|
ide_atapi_cmd_ok(s);
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check validity of BCL before transferring data */
|
||||||
|
if (!validate_bcl(s)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (transfer_request) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
/* normal read */
|
/* normal read */
|
||||||
ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
|
ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
|
||||||
|
@ -1266,6 +1290,14 @@ enum {
|
||||||
* See ATA8-ACS3 "7.21.5 Byte Count Limit"
|
* See ATA8-ACS3 "7.21.5 Byte Count Limit"
|
||||||
*/
|
*/
|
||||||
NONDATA = 0x04,
|
NONDATA = 0x04,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONDDATA implies a command that transfers data only conditionally based
|
||||||
|
* on the presence of suboptions. It should be exempt from the BCL check at
|
||||||
|
* command validation time, but it needs to be checked at the command
|
||||||
|
* handler level instead.
|
||||||
|
*/
|
||||||
|
CONDDATA = 0x08,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct AtapiCmd {
|
static const struct AtapiCmd {
|
||||||
|
@ -1289,7 +1321,7 @@ static const struct AtapiCmd {
|
||||||
[ 0xad ] = { cmd_read_dvd_structure, CHECK_READY },
|
[ 0xad ] = { cmd_read_dvd_structure, CHECK_READY },
|
||||||
[ 0xbb ] = { cmd_set_speed, NONDATA },
|
[ 0xbb ] = { cmd_set_speed, NONDATA },
|
||||||
[ 0xbd ] = { cmd_mechanism_status, 0 },
|
[ 0xbd ] = { cmd_mechanism_status, 0 },
|
||||||
[ 0xbe ] = { cmd_read_cd, CHECK_READY },
|
[ 0xbe ] = { cmd_read_cd, CHECK_READY | CONDDATA },
|
||||||
/* [1] handler detects and reports not ready condition itself */
|
/* [1] handler detects and reports not ready condition itself */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1348,15 +1380,12 @@ void ide_atapi_cmd(IDEState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nondata commands permit the byte_count_limit to be 0.
|
/* Commands that don't transfer DATA permit the byte_count_limit to be 0.
|
||||||
* If this is a data-transferring PIO command and BCL is 0,
|
* If this is a data-transferring PIO command and BCL is 0,
|
||||||
* we abort at the /ATA/ level, not the ATAPI level.
|
* we abort at the /ATA/ level, not the ATAPI level.
|
||||||
* See ATA8 ACS3 section 7.17.6.49 and 7.21.5 */
|
* See ATA8 ACS3 section 7.17.6.49 and 7.21.5 */
|
||||||
if (cmd->handler && !(cmd->flags & NONDATA)) {
|
if (cmd->handler && !(cmd->flags & (NONDATA | CONDDATA))) {
|
||||||
/* TODO: Check IDENTIFY data word 125 for default BCL (currently 0) */
|
if (!validate_bcl(s)) {
|
||||||
if (!(atapi_byte_count_limit(s) || s->atapi_dma)) {
|
|
||||||
/* TODO: Move abort back into core.c and make static inline again */
|
|
||||||
ide_abort_command(s);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue