On Thu, May 28, 2026 at 6:16 AM Philippe Mathieu-Daudé
<[email protected]> wrote:
>
> From: Djordje Todorovic <[email protected]>
>
> Check the hart endianness property and use it throughout the boot code:
>
> - ELF loading: pass ELFDATA2MSB or ELFDATA2LSB based on endianness
> - Firmware dynamic info
> - Reset vector: instructions (entries 0-5) remain always little-endian,
>   data words (entries 6-9) use target data endianness.
>
> Signed-off-by: Djordje Todorovic <[email protected]>
> Co-developed-by: Philippe Mathieu-Daudé <[email protected]>
> Signed-off-by: Philippe Mathieu-Daudé <[email protected]>

Reviewed-by: Alistair Francis <[email protected]>

Alistair

> ---
>  hw/riscv/boot.c | 40 ++++++++++++++++++++++++++++------------
>  1 file changed, 28 insertions(+), 12 deletions(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 4297949f6be..7c9cd614681 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -407,21 +407,31 @@ void riscv_rom_copy_firmware_info(MachineState *machine,
>      struct fw_dynamic_info64 dinfo64;
>      void *dinfo_ptr = NULL;
>      size_t dinfo_len;
> +    const bool rv32 = riscv_is_32bit(harts);
> +    const bool be = harts->harts[0].cfg.big_endian;
>
> -    if (riscv_is_32bit(harts)) {
> -        dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
> -        dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
> -        dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
> -        dinfo32.next_addr = cpu_to_le32(kernel_entry);
> +    if (rv32) {
> +        dinfo32.magic = be ? cpu_to_be32(FW_DYNAMIC_INFO_MAGIC_VALUE)
> +                           : cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
> +        dinfo32.version = be ? cpu_to_be32(FW_DYNAMIC_INFO_VERSION)
> +                             : cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
> +        dinfo32.next_mode = be ? cpu_to_be32(FW_DYNAMIC_INFO_NEXT_MODE_S)
> +                               : cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
> +        dinfo32.next_addr = be ? cpu_to_be32(kernel_entry)
> +                               : cpu_to_le32(kernel_entry);
>          dinfo32.options = 0;
>          dinfo32.boot_hart = 0;
>          dinfo_ptr = &dinfo32;
>          dinfo_len = sizeof(dinfo32);
>      } else {
> -        dinfo64.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
> -        dinfo64.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
> -        dinfo64.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
> -        dinfo64.next_addr = cpu_to_le64(kernel_entry);
> +        dinfo64.magic = be ? cpu_to_be64(FW_DYNAMIC_INFO_MAGIC_VALUE)
> +                           : cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
> +        dinfo64.version = be ? cpu_to_be64(FW_DYNAMIC_INFO_VERSION)
> +                             : cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
> +        dinfo64.next_mode = be ? cpu_to_be64(FW_DYNAMIC_INFO_NEXT_MODE_S)
> +                               : cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
> +        dinfo64.next_addr = be ? cpu_to_be64(kernel_entry)
> +                               : cpu_to_le64(kernel_entry);
>          dinfo64.options = 0;
>          dinfo64.boot_hart = 0;
>          dinfo_ptr = &dinfo64;
> @@ -455,6 +465,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
> RISCVHartArrayState *harts
>                                 uint64_t fdt_load_addr)
>  {
>      const bool rv32 = riscv_is_32bit(harts);
> +    const bool big_endian = harts->harts[0].cfg.big_endian;
>      uint32_t reset_vec[CODE_WORDS + DATA_WORDS];
>
>      /* .text (RISC-V instructions are always little-endian) */
> @@ -480,9 +491,14 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
> RISCVHartArrayState *harts
>      }
>      reset_vec[5] = const_le32(0x00028067);      /*     jr     t0 */
>
> -    /* .data */
> -    stq_le_p(&reset_vec[6], start_addr);        /* start:       .dword */
> -    stq_le_p(&reset_vec[8], fdt_load_addr);     /* fdt_laddr:   .dword */
> +    /* .data (must match the firmware's data endianness) */
> +    if (big_endian) {
> +        stq_be_p(&reset_vec[6], start_addr);    /* start:       .dword */
> +        stq_be_p(&reset_vec[8], fdt_load_addr); /* fdt_laddr:   .dword */
> +    } else {
> +        stq_le_p(&reset_vec[6], start_addr);
> +        stq_le_p(&reset_vec[8], fdt_load_addr);
> +    }
>
>      rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>                            rom_base, &address_space_memory);
> --
> 2.53.0
>
>

Reply via email to