Ядро Linux не находит initrd правильно

11

Я скомпилировал ядро ​​Linux и хотел отладить его в QEMU. Я создал файл для загрузки с помощью команд

$ qemu-img create -f raw disk.img 200M
$ mkfs.ext2 -F disk.img
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs

Затем я сделал qemu -kernel bzImage -initrd disk.imgи получил экран ниже, на котором написано:

Kernel panic - not syncing: VFS: unable to mount root fs on unknown block

Мой экран QEMU

Что я сделал не так и что я могу сделать, чтобы это исправить?

Coder404
источник
То же сообщение об ошибке, что и здесь, но в нем не указаны шаги, которые он предпринял для его достижения: unix.stackexchange.com/questions/48302/…
Сиро Сантилли 冠状 病毒 审查 六四 事件 法轮功

Ответы:

8

Ядро говорит вам, что оно не знает, какое устройство содержит корневую файловую систему. Ваше крепление петли не обязательно. (Размонтируйте его, прежде чем продолжить).

Попробуйте команду как

qemu -kernel bzImage -hda disk.img -append root=/dev/sda

-hda disk.imgПараметр указывает QEMU для имитации дискового устройства на основе вашегоdisk.img .

-append root=/dev/sdaПереключатель используется QEMU , чтобы сообщить ядру о его корневом устройстве. Это делается путем добавления root=/dev/sdaк командной строке ядра. Вы можете сравнить это с командной строкой ядра вашего собственного ядра, выполнив cat /proc/cmdline(Это безопасно). Там rootтоже должен быть параметр.

т-8ch
источник
Как бы я размонтировать файлы?
Coder404
umount /mnt/rootfs
t-8ch
Когда я это делаю, я получаю umount: / mnt / rootfs не монтируется (согласно mtab)
Coder404
Предположительно Coder404 не хочет , чтобы прикрепить диск к этой машине и просто запустить initв initrd. Здесь вы передаете disk.imgкак жесткий диск, initrdкоторый не имеет смысла.
Стефан Шазелас
@StephaneChazelas спасибо за подсказку о -initrdтом, что не должно быть там.
t-8ch
8

Происходит то, что вы пытаетесь загрузить Linux «устаревшим» способом. Вот гдеinitrd находится виртуальный диск, а не сжатый архив cpio, распакованный ядром в ramfs, и со старым способом переключения на конечное устройство.

В этом режиме ядро ​​монтирует disk.img как виртуальный диск в качестве корневой файловой системы, а затем запускается /linuxrcтам. Скорее всего в вашем случае такого файла нет. Когда /linuxrcпроисходит выход (который должен делать все необходимое для запуска блочного устройства для настоящей корневой файловой системы), тогда ядро ​​монтирует настоящую корневую файловую систему.

Сообщения выше показывают , что монтирует баран диск успешно (1,0: 1 для ram, так /dev/ram0) , но не файловой системы вещественного корня / DEV / sda1 (8,1: 8 sd, 1 a1). Предположительно, поскольку вы не указали командную строку ядра ( -append), это /dev/sda1происходит из CONFIG_CMDLINE, переданного во время компиляции ядра или с использованиемrdev .

Если ваш disk.img должен содержать корневую файловую систему, скажем, небольшой дистрибутив Linux с /sbin/init..., то вы, вероятно, захотите написать вместо него:

kvm -kernel kernel.img -initrd disk.img -append 'root=/dev/ram0`

Тогда ядро ​​будет рассматривать RAM-диск как настоящую корневую файловую систему (хотя вы все еще можете pivot_root можете использовать другую).

Чтобы было легче видеть сообщения ядра, я бы рекомендовал использовать последовательный вывод:

kvm -kernel kernel.img -initrd disk.img -nographic -append "root=/dev/ram0 console=ttyS0"

В качестве альтернативы вы можете использовать init ramfs вместо init ramdisk:

mkdir -p RAMFS/{bin,dev} 
cd RAMFS/bin
cp /bin/busybox .
"$PWD/busybox" --install .
cd ..
cp -a /dev/{null,tty,zero,console} dev
printf '%s\n' "#! /bin/sh" "exec /bin/sh" > init
chmod +x init
find . | cpio -oHnewc | gzip > ../initramfs.gz
cd ..
kvm -kernel kernel.img -initrd initramfs.gz

(при условии busybox статически связанная версия), и вы получите оболочку и другие утилиты busybox в этом ядре).

Обратите внимание , что ядро теперь работает /initв противоположность /linuxrcили /sbin/initв этом режиме.

Стефан Шазелас
источник
Строка 3 показанного вывода показывает, что ядро ​​смонтировало файловую систему ext2 initramdisk. Так что это, вероятно, не отсутствующий модуль.
t-8ch
О да, я пропустил это, спасибо @ t-8ch. Я думаю, что знаю, что происходит, и обновил свой ответ.
Стефан Шазелас
0

CONFIG_BLK_DEV_INITRD=y

Эта опция конфигурации ядра также требуется. Включает поддержку initrd в ядре Linux.

К счастью, Buildroot устанавливает его по умолчанию для нас, когда BR2_TARGET_ROOTFS_CPIO=yон предоставляется.

Затем вы передаете CPIO в QEMU с qemu -initrdопцией. Моя полная команда QEMU:

./buildroot/output.x86_64~/host/usr/bin/qemu-system-x86_64 -m 128M -monitor telnet::45454,server,nowait -netdev user,hostfwd=tcp::45455-:45455,id=net0 -smp 1  -M pc -append ' nopat nokaslr norandmaps printk.devkmsg=on printk.time=y console=ttyS0' -device edu -device lkmc_pci_min -device virtio-net-pci,netdev=net0 -kernel ./buildroot/output.x86_64~/images/bzImage  -nographic  -initrd './buildroot/output.x86_64~/images/rootfs.cpio'

Вот минималистичный полностью автоматизированный пример Buildroot + QEMU: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
источник