hw/sd/sdcard: Add sd_cmd_GEN_CMD handler (CMD56)

"General command" (GEN_CMD, CMD56) is described as:

  GEN_CMD is the same as the single block read or write
  commands (CMD24 or CMD17). The difference is that [...]
  the data block is not a memory payload data but has a
  vendor specific format and meaning.

Thus this block must not be stored overwriting data block
on underlying storage drive. Handle as RAZ/WI.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-Id: <20240703134356.85972-3-philmd@linaro.org>
This commit is contained in:
Philippe Mathieu-Daudé 2024-06-20 11:57:54 +02:00
parent a7487722dc
commit e7364ae74c
1 changed files with 20 additions and 34 deletions

View File

@ -243,7 +243,6 @@ static const char *sd_cmd_name(SDState *sd, uint8_t cmd)
[25] = "WRITE_MULTIPLE_BLOCK",
[26] = "MANUF_RSVD",
[40] = "DPS_spec",
[56] = "GEN_CMD",
[60] = "MANUF_RSVD", [61] = "MANUF_RSVD",
[62] = "MANUF_RSVD", [63] = "MANUF_RSVD",
};
@ -902,9 +901,6 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
}
}
#define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len)
#define APP_WRITE_BLOCK(a, len)
static void sd_erase(SDState *sd)
{
uint64_t erase_start = sd->erase_start;
@ -1641,6 +1637,22 @@ static sd_rsp_type_t sd_cmd_APP_CMD(SDState *sd, SDRequest req)
return sd_r1;
}
/* CMD56 */
static sd_rsp_type_t sd_cmd_GEN_CMD(SDState *sd, SDRequest req)
{
if (sd->state != sd_transfer_state) {
return sd_invalid_state_for_cmd(sd, req);
}
/* Vendor specific command: our model is RAZ/WI */
if (req.arg & 1) {
memset(sd->data, 0, sizeof(sd->data));
return sd_cmd_to_sendingdata(sd, req, 0, NULL, 0);
} else {
return sd_cmd_to_receivingdata(sd, req, 0, 0);
}
}
/* CMD58 */
static sd_rsp_type_t spi_cmd_READ_OCR(SDState *sd, SDRequest req)
{
@ -1836,22 +1848,6 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
case 26: /* CMD26: PROGRAM_CID */
return sd_cmd_to_receivingdata(sd, req, 0, sizeof(sd->cid));
/* Application specific commands (Class 8) */
case 56: /* CMD56: GEN_CMD */
switch (sd->state) {
case sd_transfer_state:
sd->data_offset = 0;
if (req.arg & 1)
sd->state = sd_sendingdata_state;
else
sd->state = sd_receivingdata_state;
return sd_r1;
default:
break;
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "SD: Unknown CMD%i\n", req.cmd);
return sd_illegal;
@ -2187,11 +2183,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
break;
case 56: /* CMD56: GEN_CMD */
sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sd->blk_len) {
APP_WRITE_BLOCK(sd->data_start, sd->data_offset);
sd->state = sd_transfer_state;
}
sd_generic_write_byte(sd, value);
break;
default:
@ -2233,6 +2225,7 @@ uint8_t sd_read_byte(SDState *sd)
case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
case 30: /* CMD30: SEND_WRITE_PROT */
case 51: /* ACMD51: SEND_SCR */
case 56: /* CMD56: GEN_CMD */
sd_generic_read_byte(sd, &ret);
break;
@ -2260,15 +2253,6 @@ uint8_t sd_read_byte(SDState *sd)
}
break;
case 56: /* CMD56: GEN_CMD */
if (sd->data_offset == 0)
APP_READ_BLOCK(sd->data_start, sd->blk_len);
ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= sd->blk_len)
sd->state = sd_transfer_state;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown command\n", __func__);
return 0x00;
@ -2323,6 +2307,7 @@ static const SDProto sd_proto_spi = {
[52] = {9, sd_spi, "IO_RW_DIRECT", sd_cmd_optional},
[53] = {9, sd_spi, "IO_RW_EXTENDED", sd_cmd_optional},
[55] = {8, sd_spi, "APP_CMD", sd_cmd_APP_CMD},
[56] = {8, sd_spi, "GEN_CMD", sd_cmd_GEN_CMD},
[57] = {10, sd_spi, "DIRECT_SECURE_WRITE", sd_cmd_optional},
[58] = {0, sd_spi, "READ_OCR", spi_cmd_READ_OCR},
[59] = {0, sd_spi, "CRC_ON_OFF", spi_cmd_CRC_ON_OFF},
@ -2383,6 +2368,7 @@ static const SDProto sd_proto_sd = {
[52] = {9, sd_bc, "IO_RW_DIRECT", sd_cmd_optional},
[53] = {9, sd_bc, "IO_RW_EXTENDED", sd_cmd_optional},
[55] = {8, sd_ac, "APP_CMD", sd_cmd_APP_CMD},
[56] = {8, sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD},
[57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional},
[58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
[59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},