As we have no interest in the underlying block geometry,
directly call blk_getlength(). We have to care about machines
creating SD card with not drive attached (probably incorrect
API use). Simply emit a warning when such Frankenstein cards
of zero size are reset.

Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org>
---
 hw/sd/sd.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index e5adcc8055..548745614e 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -545,18 +545,30 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
 static void sd_reset(DeviceState *dev)
 {
     SDState *sd = SD_CARD(dev);
-    uint64_t size;
-    uint64_t sect;
 
     trace_sdcard_reset();
     if (sd->blk) {
-        blk_get_geometry(sd->blk, &sect);
-    } else {
-        sect = 0;
-    }
-    size = sect << 9;
+        int64_t size = blk_getlength(sd->blk);
+
+        if (size == -ENOMEDIUM) {
+            /*
+             * FIXME blk should be set once per device in sd_realize(),
+             * and we shouldn't be checking it in sed_reset(). But this
+             * is how the reparent currently works.
+             */
+            char *id = object_get_canonical_path_component(OBJECT(dev));
+
+            warn_report("sd-card '%s' created with no drive.",
+                        id ? id : "unknown");
+            g_free(id);
+            size = 0;
+        }
+        assert(size >= 0);
+        sd->size = size;
+    } else {
+        sd->size = 0;
+    }
 
-    sd->size = size;
     sd->state = sd_idle_state;
     sd->rca = 0x0000;
     sd_set_ocr(sd);
-- 
2.21.3


Reply via email to