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 <c.speich@avm.de>
---
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