On big-endian hosts, the aspeed_ram_capacity_write() function previously passed the address of a 64-bit "data" variable directly to address_space_write(), assuming host and guest endianness matched.
However, the data is expected to be written in little-endian format to DRAM. On big-endian hosts, this led to incorrect data being written into DRAM, which caused the guest firmware to misdetect the DRAM size. As a result, U-Boot fails to boot and hangs. - Explicitly converting the 32-bit portion of "data" to little-endian format using cpu_to_le32(), storing it in a temporary "uint32_t le_data". - Updating the MemoryRegionOps to restrict access to exactly 4 bytes using .valid.{min,max}_access_size = 4 and .impl.min_access_size = 4. Signed-off-by: Jamin Lin <jamin_...@aspeedtech.com> Fixes: 7436db1 ("aspeed/soc: fix incorrect dram size for AST2700") --- hw/arm/aspeed_ast27x0.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index 1974a25766..7ed0919b3f 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -335,24 +335,34 @@ static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, AspeedSoCState *s = ASPEED_SOC(opaque); ram_addr_t ram_size; MemTxResult result; + uint32_t le_data; ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size", &error_abort); assert(ram_size > 0); + if (size != 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unsupported write size: %d (only 4-byte allowed)\n", + __func__, size); + return; + } + + le_data = cpu_to_le32((uint32_t)data); + /* * Emulate ddr capacity hardware behavior. * If writes the data to the address which is beyond the ram size, * it would write the data to the "address % ram_size". */ result = address_space_write(&s->dram_as, addr % ram_size, - MEMTXATTRS_UNSPECIFIED, &data, 4); + MEMTXATTRS_UNSPECIFIED, &le_data, 4); if (result != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed, addr:0x%" HWADDR_PRIx - ", data :0x%" PRIx64 "\n", - __func__, addr % ram_size, data); + ", data :0x%x\n", + __func__, addr % ram_size, le_data); } } @@ -360,9 +370,10 @@ static const MemoryRegionOps aspeed_ram_capacity_ops = { .read = aspeed_ram_capacity_read, .write = aspeed_ram_capacity_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { - .min_access_size = 1, - .max_access_size = 8, + .min_access_size = 4, + .max_access_size = 4, }, }; -- 2.43.0