hw/riscv/boot: Honour data endianness
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 <djordje.todorovic@htecgroup.com> Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Message-ID: <20260527201348.29511-11-philmd@linaro.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Djordje Todorovic committed
May 27, 2026 at 22:13 UTC
b3773ac91ec956312400287fbbc58426502060ae
1 file changed
+28
-12
hw/riscv/boot.c
+28
-12
@@ -407,21 +407,31 @@ void riscv_rom_copy_firmware_info(MachineState *machine,
407
struct fw_dynamic_info64 dinfo64;
408
void *dinfo_ptr = NULL;
409
size_t dinfo_len;
410
+ const bool rv32 = riscv_is_32bit(harts);
411
+ const bool be = harts->harts[0].cfg.big_endian;
412
411
- if (riscv_is_32bit(harts)) {
412
- dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
413
- dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
414
- dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
415
- dinfo32.next_addr = cpu_to_le32(kernel_entry);
413
+ if (rv32) {
414
+ dinfo32.magic = be ? cpu_to_be32(FW_DYNAMIC_INFO_MAGIC_VALUE)
415
+ : cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
416
+ dinfo32.version = be ? cpu_to_be32(FW_DYNAMIC_INFO_VERSION)
417
+ : cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
418
+ dinfo32.next_mode = be ? cpu_to_be32(FW_DYNAMIC_INFO_NEXT_MODE_S)
419
+ : cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
420
+ dinfo32.next_addr = be ? cpu_to_be32(kernel_entry)
421
+ : cpu_to_le32(kernel_entry);
422
dinfo32.options = 0;
423
dinfo32.boot_hart = 0;
424
dinfo_ptr = &dinfo32;
425
dinfo_len = sizeof(dinfo32);
426
} else {
421
- dinfo64.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
422
- dinfo64.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
423
- dinfo64.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
424
- dinfo64.next_addr = cpu_to_le64(kernel_entry);
427
+ dinfo64.magic = be ? cpu_to_be64(FW_DYNAMIC_INFO_MAGIC_VALUE)
428
+ : cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
429
+ dinfo64.version = be ? cpu_to_be64(FW_DYNAMIC_INFO_VERSION)
430
+ : cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
431
+ dinfo64.next_mode = be ? cpu_to_be64(FW_DYNAMIC_INFO_NEXT_MODE_S)
432
+ : cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
433
+ dinfo64.next_addr = be ? cpu_to_be64(kernel_entry)
434
+ : cpu_to_le64(kernel_entry);
435
dinfo64.options = 0;
436
dinfo64.boot_hart = 0;
437
dinfo_ptr = &dinfo64;
@@ -455,6 +465,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
465
uint64_t fdt_load_addr)
466
{
467
const bool rv32 = riscv_is_32bit(harts);
468
+ const bool big_endian = harts->harts[0].cfg.big_endian;
469
uint32_t reset_vec[CODE_WORDS + DATA_WORDS];
470
471
/* .text (RISC-V instructions are always little-endian) */
@@ -480,9 +491,14 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
491
}
492
reset_vec[5] = const_le32(0x00028067); /* jr t0 */
493
483
- /* .data */
484
- stq_le_p(&reset_vec[6], start_addr); /* start: .dword */
485
- stq_le_p(&reset_vec[8], fdt_load_addr); /* fdt_laddr: .dword */
494
+ /* .data (must match the firmware's data endianness) */
495
+ if (big_endian) {
496
+ stq_be_p(&reset_vec[6], start_addr); /* start: .dword */
497
+ stq_be_p(&reset_vec[8], fdt_load_addr); /* fdt_laddr: .dword */
498
+ } else {
499
+ stq_le_p(&reset_vec[6], start_addr);
500
+ stq_le_p(&reset_vec[8], fdt_load_addr);
501
+ }
502
503
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
504
rom_base, &address_space_memory);