Задать вопрос
@senorodion
Разработчик серверного ПО

Как разместить бинарный файл и передать ему управление?

Хочу использовать самый минимум: без crate-ов, без прямых инструкций процессору, без bootloader и bios, для таргета riscv64gc-unknown-none-elf и со следующим main.rs:
#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[unsafe(no_mangle)]
pub extern "C" fn _start() -> ! {
    loop {}
}


Наводящие вопросы:
1. Какой минимальный набор изменений требуется в main.rs чтобы было понимание что выполнение находится в _start?
2. Какой командой лучше запускать qemu чтобы происходило размещение в памяти и передача управления ELF?
3. Если запускать через -device loader, какой адрес (dts в спойлере ниже) необходимо указать (и можно ли так вообще)?
4. Можно ли запускать через параметр -kernel и, если да, то как?

Что уже пробовал и от чего в отталкиваюсь:
qemu-system-riscv64 -machine virt -bios none -device loader,addr=0x40000000,file=target/riscv64gc-unknown-none-elf/debug/binproject -display none -nographic

qemu-system-riscv64 -machine virt -bios none -device loader,addr=0x0,file=target/riscv64gc-unknown-none-elf/debug/binproject -display none -nographic

qemu-system-riscv64 -machine virt -bios none -device loader,addr=0x80000000,file=target/riscv64gc-unknown-none-elf/debug/binproject -display none -nographic

qemu-system-riscv64 -machine virt -bios none -kernel target/riscv64gc-unknown-none-elf/debug/binproject -display none -nographic


Запуская команды выше, результат примерно один - мигающая консольная строка (что наверное и должно быть судя по коду но если вернуть графику то в окне вместо такой же пустой консольной строки уже другая с вводом команд в qemu).

dts
/dts-v1/;

/ {
	#address-cells = <0x02>;
	#size-cells = <0x02>;
	compatible = "riscv-virtio";
	model = "riscv-virtio,qemu";

	poweroff {
		value = <0x5555>;
		offset = <0x00>;
		regmap = <0x04>;
		compatible = "syscon-poweroff";
	};

	reboot {
		value = <0x7777>;
		offset = <0x00>;
		regmap = <0x04>;
		compatible = "syscon-reboot";
	};

	platform-bus@4000000 {
		interrupt-parent = <0x03>;
		ranges = <0x00 0x00 0x4000000 0x2000000>;
		#address-cells = <0x01>;
		#size-cells = <0x01>;
		compatible = "qemu,platform", "simple-bus";
	};

	memory@80000000 {
		device_type = "memory";
		reg = <0x00 0x80000000 0x00 0x8000000>;
	};

	cpus {
		#address-cells = <0x01>;
		#size-cells = <0x00>;
		timebase-frequency = <0x989680>;

		cpu@0 {
			phandle = <0x01>;
			device_type = "cpu";
			reg = <0x00>;
			status = "okay";
			compatible = "riscv";
			riscv,cbop-block-size = <0x40>;
			riscv,cboz-block-size = <0x40>;
			riscv,cbom-block-size = <0x40>;
			riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "h", "zic64b", "zicbom", "zicbop", "zicboz", "ziccamoa", "ziccif", "zicclsm", "ziccrse", "zicntr", "zicsr", "zifencei", "zihintntl", "zihintpause", "zihpm", "zmmul", "za64rs", "zaamo", "zalrsc", "zawrs", "zfa", "zca", "zcd", "zba", "zbb", "zbc", "zbs", "sdtrig", "shcounterenw", "shgatpa", "shtvala", "shvsatpa", "shvstvala", "shvstvecd", "ssccptr", "sscounterenw", "ssstrict", "sstc", "sstvala", "sstvecd", "ssu64xl", "svadu", "svvptc";
			riscv,isa-base = "rv64i";
			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
			mmu-type = "riscv,sv57";

			interrupt-controller {
				#interrupt-cells = <0x01>;
				interrupt-controller;
				compatible = "riscv,cpu-intc";
				phandle = <0x02>;
			};
		};

		cpu-map {

			cluster0 {

				core0 {
					cpu = <0x01>;
				};
			};
		};
	};

	pmu {
		riscv,event-to-mhpmcounters = <0x01 0x01 0x7fff9 0x02 0x02 0x7fffc 0x10019 0x10019 0x7fff8 0x1001b 0x1001b 0x7fff8 0x10021 0x10021 0x7fff8>;
		compatible = "riscv,pmu";
	};

	fw-cfg@10100000 {
		dma-coherent;
		reg = <0x00 0x10100000 0x00 0x18>;
		compatible = "qemu,fw-cfg-mmio";
	};

	flash@20000000 {
		bank-width = <0x04>;
		reg = <0x00 0x20000000 0x00 0x2000000 0x00 0x22000000 0x00 0x2000000>;
		compatible = "cfi-flash";
	};

	aliases {
		serial0 = "/soc/serial@10000000";
	};

	chosen {
		stdout-path = "/soc/serial@10000000";
		rng-seed = <0x90836de 0x6df1153d 0x8906d91e 0x2e5b1501 0xee9f0b32 0xde87873a 0x28a0363 0x4dd8e07d>;
	};

	soc {
		#address-cells = <0x02>;
		#size-cells = <0x02>;
		compatible = "simple-bus";
		ranges;

		rtc@101000 {
			interrupts = <0x0b>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x101000 0x00 0x1000>;
			compatible = "google,goldfish-rtc";
		};

		serial@10000000 {
			interrupts = <0x0a>;
			interrupt-parent = <0x03>;
			clock-frequency = "", "8@";
			reg = <0x00 0x10000000 0x00 0x100>;
			compatible = "ns16550a";
		};

		test@100000 {
			phandle = <0x04>;
			reg = <0x00 0x100000 0x00 0x1000>;
			compatible = "sifive,test1", "sifive,test0", "syscon";
		};

		virtio_mmio@10008000 {
			interrupts = <0x08>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10008000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10007000 {
			interrupts = <0x07>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10007000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10006000 {
			interrupts = <0x06>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10006000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10005000 {
			interrupts = <0x05>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10005000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10004000 {
			interrupts = <0x04>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10004000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10003000 {
			interrupts = <0x03>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10003000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10002000 {
			interrupts = <0x02>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10002000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		virtio_mmio@10001000 {
			interrupts = <0x01>;
			interrupt-parent = <0x03>;
			reg = <0x00 0x10001000 0x00 0x1000>;
			compatible = "virtio,mmio";
		};

		plic@c000000 {
			phandle = <0x03>;
			riscv,ndev = <0x5f>;
			reg = <0x00 0xc000000 0x00 0x600000>;
			interrupts-extended = <0x02 0x0b 0x02 0x09>;
			interrupt-controller;
			compatible = "sifive,plic-1.0.0", "riscv,plic0";
			#address-cells = <0x00>;
			#interrupt-cells = <0x01>;
		};

		clint@2000000 {
			interrupts-extended = <0x02 0x03 0x02 0x07>;
			reg = <0x00 0x2000000 0x00 0x10000>;
			compatible = "sifive,clint0", "riscv,clint0";
		};

		pci@30000000 {
			interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
			interrupt-map = <0x00 0x00 0x00 0x01 0x03 0x20 0x00 0x00 0x00 0x02 0x03 0x21 0x00 0x00 0x00 0x03 0x03 0x22 0x00 0x00 0x00 0x04 0x03 0x23 0x800 0x00 0x00 0x01 0x03 0x21 0x800 0x00 0x00 0x02 0x03 0x22 0x800 0x00 0x00 0x03 0x03 0x23 0x800 0x00 0x00 0x04 0x03 0x20 0x1000 0x00 0x00 0x01 0x03 0x22 0x1000 0x00 0x00 0x02 0x03 0x23 0x1000 0x00 0x00 0x03 0x03 0x20 0x1000 0x00 0x00 0x04 0x03 0x21 0x1800 0x00 0x00 0x01 0x03 0x23 0x1800 0x00 0x00 0x02 0x03 0x20 0x1800 0x00 0x00 0x03 0x03 0x21 0x1800 0x00 0x00 0x04 0x03 0x22>;
			ranges = <0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x04 0x00 0x04 0x00 0x04 0x00>;
			reg = <0x00 0x30000000 0x00 0x10000000>;
			dma-coherent;
			bus-range = <0x00 0xff>;
			linux,pci-domain = <0x00>;
			device_type = "pci";
			compatible = "pci-host-ecam-generic";
			#size-cells = <0x02>;
			#interrupt-cells = <0x01>;
			#address-cells = <0x03>;
		};
	};
};


Работаю из macOS (M1). Для упрощения ситуации, допускается смена target на aarch64-unknown-none. Заранее благодарен.
  • Вопрос задан
  • 105 просмотров
Подписаться 1 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Go-разработчик с нуля + нейросети
    9 месяцев
    Далее
  • Яндекс Практикум
    Специалист по информационной безопасности
    11 месяцев
    Далее
  • Skillbox
    DevOps-инженер
    7 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Какой минимальный набор изменений требуется в main.rs чтобы было понимание что выполнение находится в _start?

Можно вообще ничего не менять, а просто запускать QEMU с ключами -d in_asm,exec и смотреть в лог выполнения.

Какой командой лучше запускать qemu чтобы происходило размещение в памяти и передача управления ELF?

Насколько я вижу riscv машины игнорируют адрес точки входа в ELF-файлах которые им передаются через -kernel.

Если запускать через -device loader, какой адрес (dts в спойлере ниже) необходимо указать (и можно ли так вообще)?

0x80000000, elf должен быть слинкован так, чтобы точка входа была по этому адресу.

Можно ли запускать через параметр -kernel и, если да, то как?

bare metal на платформе virt и без извращений -- я не вижу как.

если вернуть графику то в окне вместо такой же пустой консольной строки уже другая с вводом команд в qemu).

Это интерфейс монитора qemu. Его можно отключить опцией -monitor none.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы