El kernel de Linux no encuentra el initrd correctamente

11

Había compilado un kernel de Linux y quería depurarlo en QEMU. Creé un archivo para iniciar haciendo los comandos

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

Luego lo hice qemu -kernel bzImage -initrd disk.imgy obtuve la siguiente pantalla que dice:

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

Mi pantalla QEMU

¿Qué he hecho mal y qué puedo hacer para solucionarlo?

Codificador404
fuente
El mismo mensaje de error que este, pero no especifica los pasos que tomó para alcanzarlo: unix.stackexchange.com/questions/48302/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Respuestas:

8

El kernel le dice que no sabe qué dispositivo contiene el sistema de archivos raíz. Su montaje en bucle no es necesario. (Desmontarlo antes de continuar).

Prueba un comando como

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

El -hda disk.imgparámetro le dice a qemu que simule un dispositivo de disco basado en su disk.img.

El -append root=/dev/sdainterruptor es utilizado por qemu para decirle al kernel al respecto del dispositivo raíz. Esto se hace agregando el root=/dev/sdaa la línea de comandos del núcleo. Puede comparar esto con la línea de comandos del núcleo de su propio núcleo haciendo cat /proc/cmdline(Esto es seguro). Debería ver allí también un rootparámetro.

t-8ch
fuente
¿Cómo desmontaría los archivos?
Coder404
umount /mnt/rootfs
t-8ch
Cuando hago eso, obtengo umount: / mnt / rootfs no está montado (según mtab)
Coder404
Presumiblemente, Coder404 no quiere conectar un disco a esa máquina y simplemente ejecutarlo initen el initrd. Aquí está pasando los disk.imgdos como un disco duro y uno initrdque no tiene sentido.
Stéphane Chazelas
@StephaneChazelas gracias por la pista de -initrdque no debería haber estado allí.
t-8ch
8

Lo que sucede es que estás intentando arrancar Linux de la manera "Obsoleto". Ahí es donde se initrdencuentra un ramdisk en lugar de un archivo comprimido de cpio descomprimido por el núcleo en un ramfs, y con la antigua forma de cambiar al dispositivo final.

En ese modo, el núcleo monta el disk.img como un disco ram como el sistema de archivos raíz y luego se ejecuta /linuxrcallí. Lo más probable en su caso, no existe tal archivo. Cuando /linuxrc(que se supone que debe hacer lo necesario para abrir el dispositivo de bloque para el sistema de archivos raíz real) sale, el núcleo monta el sistema de archivos raíz real.

Los mensajes anteriores muestran que monta el disco RAM con éxito (1,0: 1 es para ram, por lo tanto /dev/ram0) pero no el sistema de archivos raíz real / dev / sda1 (8,1: 8 es sd, 1 es a1). Presumiblemente, dado que no especificó una línea de comando del núcleo ( -append), que /dev/sda1proviene de una CONFIG_CMDLINE pasada en el momento de la compilación del núcleo o usando rdev.

Si su disk.img está destinado a contener un sistema de archivos raíz de, digamos, una pequeña distribución de Linux con /sbin/init..., entonces probablemente desee escribirlo en su lugar:

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

Luego, el núcleo trataría el disco RAM como el sistema de archivos raíz real (aunque aún podría utilizar pivot_roototro).

Para poder ver los mensajes del núcleo más fácilmente, recomiendo usar la salida en serie:

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

Como alternativa, puede usar un ramfs de inicio en lugar de un disco de inicio:

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

(se proporciona busyboxla versión vinculada estáticamente) y obtendrá un shell y otras utilidades de busybox en ese núcleo).

Tenga en cuenta que el kernel ahora se ejecuta /initen oposición /linuxrco /sbin/initen ese modo.

Stéphane Chazelas
fuente
La línea 3 de la salida mostrada muestra que el núcleo montó el sistema de archivos ext2 del disco de inicio. Por lo tanto, probablemente no sea un módulo faltante.
t-8ch
Ah sí, me lo había perdido, gracias @ t-8ch. Creo que sé lo que está pasando y he actualizado mi respuesta.
Stéphane Chazelas
0

CONFIG_BLK_DEV_INITRD=y

Esta opción de configuración del kernel también es necesaria. Habilita el soporte de initrd en el kernel de Linux.

Afortunadamente Buildroot lo establece de forma predeterminada para nosotros cuando BR2_TARGET_ROOTFS_CPIO=yse da.

Luego pasa el CPIO a QEMU con la qemu -initrdopción. Mi comando QEMU completo es:

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

Aquí es un minimalista ejemplo totalmente automatizado Buildroot + QEMU: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

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