On 5/22/25 04:33, Jamin Lin wrote:
> 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.
>
> - Replaces the "address_space_write()" call with "address_space_stl_le()",
> which performs an explicit 32-bit little-endian write.
> - 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_lin@aspeedtech.com>
> Fixes: 7436db1 ("aspeed/soc: fix incorrect dram size for AST2700")
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Thanks,
C.
> ---
> hw/arm/aspeed_ast27x0.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
> index 1974a25766..82a5ecff04 100644
> --- a/hw/arm/aspeed_ast27x0.c
> +++ b/hw/arm/aspeed_ast27x0.c
> @@ -346,8 +346,9 @@ static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data,
> * 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);
> + address_space_stl_le(&s->dram_as, addr % ram_size, data,
> + MEMTXATTRS_UNSPECIFIED, &result);
> +
> if (result != MEMTX_OK) {
> qemu_log_mask(LOG_GUEST_ERROR,
> "%s: DRAM write failed, addr:0x%" HWADDR_PRIx
> @@ -360,9 +361,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,
> },
> };
>