web-dev-qa-db-fra.com

Le noyau Linux ne trouve pas correctement l'initrd

J'avais compilé un noyau Linux et je voulais le déboguer à Qemu. J'ai créé un fichier pour démarrer en faisant les commandes

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

Alors j'ai fait qemu -kernel bzImage -initrd disk.img et obtenu l'écran ci-dessous qui dit:

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

My QEMU screen

Qu'est-ce que j'ai mal fait et que puis-je faire pour le réparer?

11
Coder404

Le noyau vous dit que cela ne sait pas quel -appareil contient le système de fichiers racine. Votre monture de boucle n'est pas nécessaire. (Démonter-le-le avant de continuer).

Essayez une commande comme

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

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

Le -append root=/dev/sda Le commutateur est utilisé par QEMU pour dire au noyau de son périphérique root. Ceci est fait en ajoutant le root=/dev/sda à la ligne de commande du noyau. Vous pouvez comparer cela à la commande Kernel de votre propre noyau en faisant cat /proc/cmdline (C'est sûr). Vous devriez y voir un paramètre root.

8
t-8ch

Ce qui se passe est que vous essayez de démarrer Linux de la manière "obsolète". C'est là que le initrd est un ramdisk par opposition à une archive CPIO compressée déballée par le noyau dans une RAMFS et avec l'ancienne façon de passer au périphérique final.

Dans ce mode, le noyau monte le disque.img en tant que ramdisk comme système de fichiers racine, puis exécute /linuxrc là-bas. Très probablement dans votre cas, il n'y a pas de fichier de ce type. Lorsque /linuxrc (qui est censé faire tout ce qui est nécessaire pour faire monter le dispositif de blocage du système de fichiers racines réel), puis le noyau monte le système de fichiers racine réel.

Les messages ci-dessus montrent qu'il monte le disque RAM avec succès (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 depuis que vous n'avez pas spécifié de ligne de commande de noyau (-append), cette /dev/sda1 vient à partir d'une config_cmdline passée à l'heure de compilation du noyau ou à l'aide de rdev.

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

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

Ensuite, le noyau traiterait le disque RAM comme système de fichiers racine réel (bien que vous puissiez toujours pivot_root à un autre).

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

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

Comme une alternative, vous pouvez utiliser un init Ramfs au lieu d'un Ramdisk 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 busybox est la version liée statique) et vous obtiendrez une coquille et d'autres utilitaires d'actionnement dans ce noyau).

Notez que le noyau fonctionne maintenant /init par opposition à /linuxrc ou /sbin/init dans ce mode.

7
Stéphane Chazelas

CONFIG_BLK_DEV_INITRD=y

Cette option de configuration du noyau est également requise. Il permet une prise en charge initiale du noyau Linux.

Hôtel Buildroot le définit par défaut pour nous lorsque BR2_TARGET_ROOTFS_CPIO=y est donné.

Vous passez ensuite le CPIO à QEMU avec le qemu -initrd option. Ma commande plein qemu 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 entièrement automatisé de véhicules uemu: https://github.com/cirosantilli/lithub.com/cirosantilli/lithuux-kernel-module-cheat/tree/b3868A3B009F2AB44FA6D3DB3D174FA6D3CF7B69#IRIIT