From 0529fa5e5947889079204076648e5e10fc5e2c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 1 Sep 2017 10:39:18 +0200 Subject: [PATCH] aspeed/sdmc: rework the locking register of the memory controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lock register is unlocked with a write of a special value and locked with a write of any other value. When unlocked, reads return one and when locked a zero. Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_sdmc.c | 28 +++++++++++++++++++--------- include/hw/misc/aspeed_sdmc.h | 1 + 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index f0b3053fae36..04bab39db079 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -83,17 +83,22 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size) { AspeedSDMCState *s = ASPEED_SDMC(opaque); + uint64_t val = 0; addr >>= 2; - if (addr >= ARRAY_SIZE(s->regs)) { + switch (addr) { + case R_PROT: + val = s->unlocked; + break; + default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", __func__, addr); - return 0; + break; } - return s->regs[addr]; + return val; } static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, @@ -103,19 +108,18 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, addr >>= 2; - if (addr >= ARRAY_SIZE(s->regs)) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", - __func__, addr); + if (addr == R_PROT) { + s->unlocked = (data == PROT_KEY_UNLOCK); return; } - if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) { + if (!s->unlocked) { /* TODO protect : MCR04 ∼ MCR7C */ qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); return; } - if (addr == R_CONF) { + switch (addr) { + case R_CONF: /* Make sure readonly bits are kept */ switch (s->silicon_rev) { case AST2400_A0_SILICON_REV: @@ -128,6 +132,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, default: g_assert_not_reached(); } + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return; } s->regs[addr] = data; diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h index 551c8afdf4be..a4415d9efc2f 100644 --- a/include/hw/misc/aspeed_sdmc.h +++ b/include/hw/misc/aspeed_sdmc.h @@ -28,6 +28,7 @@ typedef struct AspeedSDMCState { uint32_t ram_bits; uint64_t ram_size; + bool unlocked; } AspeedSDMCState; #endif /* ASPEED_SDMC_H */