Куда QEMU загружает DTB?

Я пишу свой собственный загрузчик для 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

Как видите, все, что я сделал до сих пор, это:

  1. Настройка стека
  2. Предположительно, я загрузил DTB в x0 (точно так, как требует протокол загрузки Linux)
  3. Ветвь к расположению ядра linux

Итак, я еще не загрузил initramfs.cpio.gz, который содержит файловую систему, но я уже должен получить хоть какой-то вывод из ядра с момента загрузки DTB.

У меня вопрос, правильно ли я загрузил? И я думаю, что простой ответ - нет. Но в основном я понятия не имею, куда qemu помещает dtb в мою оперативную память, и, просмотрев всю документацию, я не могу найти эту информацию.

Я был бы очень признателен, если бы кто-нибудь сказал мне, где QEMU загружает dtb, чтобы я мог поместить его в x0, и ядро ​​могло бы с удовольствием его прочитать!

Заранее спасибо!

вы решаете куда ставить ядро ​​и dtb а потом говорите системе, в общем. кстати, вы можете кормить файлы qemu elf. просто посмотрите на загрузчик, такой как u-boot или какой-то другой, хотя да, они массивные и свои собственные звери ... на самом деле зайдите на форум baremetal для raspberry pi. есть дампы кода, используемого для запуска ядра linux, это несколько десятков строк кода, которые сообщают ядру, где что находится, и большая часть этого кода связана с переводом ядра в правильный режим, это очень тривиально запустить ядро ​​линукса.

old_timer 28.11.2022 16:32
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Где dtb (если есть) зависит от платы. Документация QEMU для платы Arm 'virt' сообщает вам, где находится DTB:

https://www.qemu.org/docs/master/system/arm/virt.html#hardware-configuration-information-for-bare-metal-programming

Однако ваша командная строка неверна. «-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, но он все еще не загружался.

Vladouch 25.11.2022 12:26

Неудивительно, что если вы отбросите эту строку, загрузится ядро. Это потому, что загрузчик QEMU делает всю работу за вас, а ваш код просто мешает. Если у вас должен быть initrd, то либо (а) включите его в большой двоичный объект, как вы уже сделали для ядра, либо (б) вашему загрузчику нужно будет извлечь его из устройства fw_cfg. Если вы собираетесь работать с fw_cfg, вы также можете извлечь из него образ ядра.

Peter Maydell 25.11.2022 14:13

Другие вопросы по теме