Currently, erased blocks are filled with 0xFF. However SCR Bit 55 (DATA_STAT_AFTER_ERASE) indicates that an erase produces zeros. One of them is wrong.
This patch does two things. First it fixes the reporting of DATA_STAT_AFTER_ERASE in SCR to correctly reflect the content of erased blocks. We also increase the Product Revision (REV in CID) to indicate to the guest that DATA_STAT_AFTER_ERASE is now reliable. Secondly, we introduce a erase-blocks-as-zero option, which allows the user to choose if erased blocks should contain 0xFF or 0x00. The default is still 0xFF to remain compatible with current users. Signed-off-by: Christian Speich <[email protected]> --- hw/sd/sd.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 23764ed99f36cf39ee7abe02f08e51897c05e718..af7e40faf67c66995b2b615080265dc31da150a6 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -139,6 +139,7 @@ struct SDState { /* Static properties */ uint8_t spec_version; + bool erase_blocks_as_zero; uint64_t boot_part_size; BlockBackend *blk; uint8_t boot_config; @@ -409,6 +410,9 @@ static void sd_set_scr(SDState *sd) sd->scr[0] |= 2; /* Spec Version 2.00 or Version 3.0X */ sd->scr[1] = (2 << 4) /* SDSC Card (Security Version 1.01) */ | 0b0101; /* 1-bit or 4-bit width bus modes */ + if (!sd->erase_blocks_as_zero) { + sd->scr[1] |= (1 << 7); /* DATA_STAT_AFTER_ERASE: Erase produces 0xFF */ + } sd->scr[2] = 0x00; /* Extended Security is not supported. */ if (sd->spec_version >= SD_PHY_SPECv3_01_VERS) { sd->scr[2] |= 1 << 7; /* Spec Version 3.0X */ @@ -426,7 +430,7 @@ static void sd_set_scr(SDState *sd) #define MID 0xaa #define OID "XY" #define PNM "QEMU!" -#define PRV 0x01 +#define PRV 0x02 #define MDT_YR 2006 #define MDT_MON 2 @@ -1115,7 +1119,12 @@ static void sd_erase(SDState *sd) sd->erase_end = INVALID_ADDRESS; sd->csd[14] |= 0x40; - memset(sd->data, 0xff, erase_len); + if (sd->erase_blocks_as_zero) { + memset(sd->data, 0x0, erase_len); + } else { + memset(sd->data, 0xFF, erase_len); + } + for (erase_addr = erase_start; erase_addr <= erase_end; erase_addr += erase_len) { if (sdsc) { @@ -2971,6 +2980,8 @@ static void emmc_realize(DeviceState *dev, Error **errp) static const Property sdmmc_common_properties[] = { DEFINE_PROP_DRIVE("drive", SDState, blk), + DEFINE_PROP_BOOL("erase-blocks-as-zero", SDState, erase_blocks_as_zero, + false), }; static const Property sd_properties[] = { -- 2.43.0
