From 01aeb226ea41309e099daa08d1a00664a735c7ae Mon Sep 17 00:00:00 2001 From: Mitchell-Johnson Date: Sat, 19 Sep 2026 04:50:05 -0700 Subject: [PATCH] Disks: show eMMC firmware revision as text when it is text Co-Authored-By: Claude Fable 5.1 --- internal/storage/storage.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/storage/storage.go b/internal/storage/storage.go index eb3e108..6fdf169 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -7,6 +7,7 @@ package storage import ( "bytes" "context" + "encoding/hex" "encoding/json" "errors" "os" @@ -223,15 +224,21 @@ func mmcHealth(s Smart) Smart { s.SelfTestNote = "not a feature of eMMC or SD" s.Serial = strings.TrimSpace(readStrFile(dir + "serial")) s.Firmware = strings.TrimSpace(readStrFile(dir + "fwrev")) + // fwrev is eight raw bytes in hex; vendors usually put ASCII in them ("0001") + if b, err := hex.DecodeString(strings.TrimPrefix(s.Firmware, "0x")); err == nil { + if t := strings.TrimRight(string(b), "\x00 "); t != "" && strings.IndexFunc(t, func(r rune) bool { return r < 0x20 || r > 0x7e }) < 0 { + s.Firmware = t + } + } s.Model = strings.TrimSpace(readStrFile(dir + "name")) - hex := func(v string) int { n, _ := strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 32); return int(n) } + hx := func(v string) int { n, _ := strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 32); return int(n) } life := strings.Fields(readStrFile(dir + "life_time")) eol := strings.TrimSpace(readStrFile(dir + "pre_eol_info")) if len(life) != 2 || eol == "" { s.Error = "This card reports no health data (SD cards don't; eMMC 5.0 and later does)." return s } - m := &MMCHealth{LifeA: hex(life[0]), LifeB: hex(life[1]), PreEOL: hex(eol)} + m := &MMCHealth{LifeA: hx(life[0]), LifeB: hx(life[1]), PreEOL: hx(eol)} s.MMC = m ok := m.PreEOL <= 1 && m.LifeA < 10 && m.LifeB < 10 s.Passed = &ok