Le noyau Linux ne trouve pas correctement l'initrd

11

J'avais compilé un noyau Linux et je voulais le déboguer dans QEMU. J'ai créé un fichier pour démarrer à partir des commandes

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

Ensuite, je l'ai fait qemu -kernel bzImage -initrd disk.imget j'ai obtenu l'écran ci-dessous qui dit:

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

Mon écran QEMU

Qu'est-ce que j'ai fait de mal et que puis-je faire pour y remédier?

Coder404
la source
Même message d'erreur que celui-ci, mais ne spécifiant pas les étapes qu'il a suivies
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Réponses:

8

Le noyau vous dit qu'il ne sait pas quel périphérique contient le système de fichiers racine. Votre support de boucle n'est pas nécessaire. (Démontez-le avant de continuer).

Essayez une commande comme

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

Le -hda disk.imgparamètre indique à qemu de simuler un périphérique de disque basé sur votre disk.img.

Le -append root=/dev/sdacommutateur est utilisé par qemu pour informer le noyau de son périphérique racine. Cela se fait en ajoutant le root=/dev/sdaà la ligne de commande du noyau. Vous pouvez comparer cela à la ligne de commande du noyau de votre propre noyau en faisant cat /proc/cmdline(c'est sûr). Vous devriez également y voir un rootparamètre.

t-8ch
la source
Comment démonter les fichiers?
Coder404
umount /mnt/rootfs
t-8ch
Quand je fais cela, j'obtiens umount: / mnt / rootfs n'est pas monté (selon mtab)
Coder404
Vraisemblablement, Coder404 ne veut pas attacher de disque à cette machine et exécuter simplement le initdans le initrd. Ici, vous passez les disk.imgdeux en tant que disque dur et ce initrdqui n'a pas de sens.
Stéphane Chazelas
@StephaneChazelas merci pour l'indication à -initrdce sujet qui n'aurait pas dû être là.
t-8ch
8

Ce qui se passe, c'est que vous essayez de démarrer Linux de manière "obsolète". C'est là que se initrdtrouve un ramdisk par opposition à une archive cpio compressée décompressée par le noyau dans un ramfs, et avec l'ancienne façon de basculer vers le périphérique final.

Dans ce mode, le noyau monte le disk.img en tant que disque virtuel en tant que système de fichiers racine, puis s'exécute /linuxrcdedans. Très probablement dans votre cas, il n'y a pas un tel fichier. Lorsque /linuxrc(qui est censé faire tout ce qui est nécessaire pour afficher le périphérique de blocage pour le système de fichiers racine réel) se ferme, le noyau monte le véritable système de fichiers racine.

Les messages ci-dessus montrent qu'il monte correctement le disque RAM (1,0: 1 est pour ram, donc /dev/ram0) mais pas le vrai système de fichiers racine / dev / sda1 (8,1: 8 est sd, 1 est a1). Vraisemblablement, puisque vous n'avez pas spécifié de ligne de commande du noyau ( -append), cela /dev/sda1provient d'une CONFIG_CMDLINE passée au moment de la compilation du noyau ou de l'utilisation rdev.

Si votre disk.img est censé contenir un système de fichiers racine, disons une petite distribution Linux avec /sbin/init..., alors vous voudrez probablement l'écrire à la place:

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

Ensuite, le noyau traiterait le disque RAM comme le véritable système de fichiers racine (bien que vous puissiez toujours pivot_rooten utiliser un autre).

Pour pouvoir voir les messages du noyau plus facilement, je recommande d'utiliser la sortie série:

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

Comme alternative, vous pouvez utiliser un ramfs init au lieu d'un disque ram init:

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

(fourni busyboxest la version liée statiquement) et vous obtiendrez un shell et d'autres utilitaires busybox dans ce noyau).

Notez que le noyau fonctionne désormais /initpar opposition à /linuxrcou /sbin/initdans ce mode.

Stéphane Chazelas
la source
La ligne 3 de la sortie montrée montre que le noyau a monté le système de fichiers ext2 de l'initramdisk. Ce n'est donc probablement pas un module manquant.
t-8ch
Oh oui, je l'avais manqué, merci @ t-8ch. Je pense que je sais ce qui se passe et j'ai mis à jour ma réponse.
Stéphane Chazelas
0

CONFIG_BLK_DEV_INITRD=y

Cette option de configuration du noyau est également requise. Il active la prise en charge initrd sur le noyau Linux.

Luckly Buildroot le définit par défaut pour nous quand BR2_TARGET_ROOTFS_CPIO=yest donné.

Vous passez ensuite le CPIO à QEMU avec l' qemu -initrdoption. Ma commande QEMU complète est:

./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'

Voici un exemple minimaliste Buildroot + QEMU entièrement automatisé: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
la source