@samitouri / QOSamiQemu / commits / b3773ac91e

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);