Я пишу свой собственный загрузчик для aarch64, который должен загружать Linux, и для его правильного выполнения мне нужно следовать протоколу загрузки Linux.
Вот некоторые сопоставления памяти: находятся в моем файле компоновщика
FLASH_START = 0x000100000;
RAM_START = 0x40000000;
TEXT_START = 0x40080000;
Вот команда, которую я использую для запуска своего виртуала, дающего 4 ядра и 2 ГБ ОЗУ.
qemu-system-aarch64 -nographic -machine virt -cpu cortex-a72 -kernel pflash.bin -initrd initramfs.cpio.gz -serial mon:stdio -m 2G -smp 4
pflash.bin имеет следующий вид:
dd if=/dev/zero of=pflash.bin bs=1M count=512
dd if=my_bootloader.img of=pflash.bin conv=notrunc bs=1M count=20
dd if=Kernel of=pflash.bin conv=notrunc bs=1M seek=50
Где: Kernel — файл образа ядра Linux,
а my_bootloader.img — это просто objcopy файла elf:
aarch64-linux-gnu-objcopy -O binary my_bootloader.elf my_bootloader.img
И файл elf создается следующим образом:
aarch64-linux-gnu-ld -nostdlib -T link.ld my_bootloader.o -o my_bootloader.elf
Вот мой_bootloader.S
.section ".text.startup"
.global _start
_start:
ldr x30, =STACK_TOP
mov sp, x30
ldr x0, =RAM_START
ldr x1, =0x43280000
br x1
ret
Как видите, все, что я сделал до сих пор, это:
Итак, я еще не загрузил initramfs.cpio.gz, который содержит файловую систему, но я уже должен получить хоть какой-то вывод из ядра с момента загрузки DTB.
У меня вопрос, правильно ли я загрузил? И я думаю, что простой ответ - нет. Но в основном я понятия не имею, куда qemu помещает dtb в мою оперативную память, и, просмотрев всю документацию, я не могу найти эту информацию.
Я был бы очень признателен, если бы кто-нибудь сказал мне, где QEMU загружает dtb, чтобы я мог поместить его в x0, и ядро могло бы с удовольствием его прочитать!
Заранее спасибо!
Где dtb (если есть) зависит от платы. Документация QEMU для платы Arm 'virt' сообщает вам, где находится DTB:
Однако ваша командная строка неверна. «-kernel pflash.bin» говорит, что «этот файл является ядром Linux, загрузите его так, как должно загружаться ядро Linux». То, что вы хотите, это «загрузить этот файл во флэш-память и запустить его так, как ЦП запустится после сброса на реальном оборудовании». Для этого вам нужен один из других способов загрузки гостевого двоичного файла (-bios, вероятно, самый простой). И вы, вероятно, не хотите передавать QEMU параметр -initrd, поскольку он предназначен либо для (а) встроенного загрузчика QEMU, либо (б) для загрузчиков, поддерживающих QEMU, которые знают, как извлечь ядро и initrd из fw- кфг устройство.
PS: Если вы укажете QEMU предоставить более одного гостевого ЦП, тогда вашему загрузчику придется иметь дело со вторичными ЦП. Это означает либо использование PSCI для их запуска, либо обработку того факта, что все процессоры начинают выполнять один и тот же код после сброса (какой из них зависит от того, как вы решите запустить QEMU). Вам лучше начать с '-smp 1', а позже вернуться и заняться SMP.
Спасибо за ваш ответ, дело в том, что он действительно загружается, когда я избавляюсь от этой строки в моем my_bootloadr.S: ldr x0, =RAM_START
. Проблема в том, что перед загрузкой реального ядра мне нужно будет выполнить CLI, к которому я перейду сразу после инициализации стека (для ясности я удалил его из своего кода в посте), и как только я перейду к нему , я предполагаю, что ссылка на DTB, который в конечном итоге установил QEMU, потеряна. -initrd является обязательным для того, что я пытаюсь сделать... Для документа QEMU я попытался установить адрес ОЗУ на 0x40000_0000, но он все еще не загружался.
Неудивительно, что если вы отбросите эту строку, загрузится ядро. Это потому, что загрузчик QEMU делает всю работу за вас, а ваш код просто мешает. Если у вас должен быть initrd, то либо (а) включите его в большой двоичный объект, как вы уже сделали для ядра, либо (б) вашему загрузчику нужно будет извлечь его из устройства fw_cfg. Если вы собираетесь работать с fw_cfg, вы также можете извлечь из него образ ядра.
вы решаете куда ставить ядро и dtb а потом говорите системе, в общем. кстати, вы можете кормить файлы qemu elf. просто посмотрите на загрузчик, такой как u-boot или какой-то другой, хотя да, они массивные и свои собственные звери ... на самом деле зайдите на форум baremetal для raspberry pi. есть дампы кода, используемого для запуска ядра linux, это несколько десятков строк кода, которые сообщают ядру, где что находится, и большая часть этого кода связана с переводом ядра в правильный режим, это очень тривиально запустить ядро линукса.