O kernel do Linux não está encontrando o initrd corretamente

11

Eu compilei um kernel do linux e queria depurá-lo no QEMU. Criei um arquivo para inicializar executando os comandos

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

Então eu fiz qemu -kernel bzImage -initrd disk.imge peguei a tela abaixo que diz:

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

Minha tela QEMU

O que fiz de errado e o que posso fazer para corrigi-lo?

Coder404
fonte
A mesma mensagem de erro que essa, mas não especifica as etapas que ele executou para alcançá-la: unix.stackexchange.com/questions/48302/…
Ciro Santilli

Respostas:

8

O kernel está lhe dizendo que não sabe qual dispositivo contém o sistema de arquivos raiz. Sua montagem em loop não é necessária. (Desmonte antes de continuar).

Tente um comando como

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

O -hda disk.imgparâmetro diz ao qemu para simular um dispositivo de disco com base no seu disk.img.

O -append root=/dev/sdaswitch é usado pelo qemu para informar o kernel sobre seu dispositivo raiz. Isso é feito anexando a root=/dev/sdalinha de comando ao kernel. Você pode comparar isso com a linha de comando do kernel do seu próprio kernel fazendo cat /proc/cmdline(Isso é seguro). Você deve ver também um rootparâmetro.

t-8ch
fonte
Como eu desmontaria os arquivos?
Coder404
umount /mnt/rootfs
precisa
Quando eu faço que eu recebo umount: / mnt / rootfs não está montado (de acordo com mtab)
Coder404
Presumivelmente, o Coder404 não deseja anexar um disco a essa máquina e apenas executar inito initrd. Aqui você está passando os disk.imgdois como um disco rígido e um initrdque não faz sentido.
Stéphane Chazelas
@StephaneChazelas, obrigado pela dica sobre -initrdisso não deveria estar lá.
precisa
8

O que está acontecendo é que você está tentando inicializar o Linux da maneira "Obsoleta". É aí que initrdexiste um ramdisk em oposição a um arquivo cpio compactado descompactado pelo kernel em um ramfs e com a maneira antiga de mudar para o dispositivo final.

Nesse modo, o kernel monta o disk.img como um ramdisk como o sistema de arquivos raiz e depois é executado /linuxrcnele. Provavelmente no seu caso, não existe esse arquivo. Quando /linuxrc(que é suposto fazer o que for necessário para abrir o dispositivo de bloco para o sistema de arquivos raiz real) sai, o kernel monta o sistema de arquivos raiz real.

As mensagens acima mostram que ele monta o disco ram com êxito (1,0: 1 é para ram, portanto /dev/ram0), mas não o sistema de arquivos raiz real / dev / sda1 (8,1: 8 é sd, 1 é a1). Presumivelmente, como você não especificou uma linha de comando do kernel ( -append), que /dev/sda1vem de um CONFIG_CMDLINE transmitido no momento da compilação ou uso do kernel rdev.

Se o seu disk.img deve conter um sistema de arquivos raiz, como por exemplo uma pequena distribuição Linux com /sbin/init..., provavelmente você deseja escrevê-lo:

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

Então, o kernel trataria o disco ram como o sistema de arquivos raiz real (embora você ainda possa usar pivot_rootoutro).

Para poder ver as mensagens do kernel mais facilmente, eu recomendo usar a saída serial:

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

Como alternativa, você pode usar um init ramfs em vez de um 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

(fornecida busyboxé a versão vinculada estaticamente) e você obterá um shell e outros utilitários do busybox nesse kernel).

Observe que o kernel agora roda /initem oposição a /linuxrcou /sbin/initnesse modo.

Stéphane Chazelas
fonte
A linha 3 da saída mostrada mostra que o kernel montou o sistema de arquivos ext2 do initramdisk. Portanto, provavelmente não é um módulo ausente.
T-8ch
Ah, sim, eu tinha perdido isso, obrigado @ t-8ch. Acho que sei o que está acontecendo e atualizei minha resposta.
Stéphane Chazelas 11/03/2013
0

CONFIG_BLK_DEV_INITRD=y

Esta opção de configuração do kernel também é necessária. Ativa o suporte ao initrd no kernel do Linux.

Felizmente o Buildroot o define por padrão para nós quando BR2_TARGET_ROOTFS_CPIO=yé dado.

Em seguida, você passa o CPIO para QEMU com a qemu -initrdopção Meu comando QEMU completo é:

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

Aqui está um exemplo minimalista e totalmente automatizado do Buildroot + QEMU: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/b3868a3b009f2ab44fa6d3db3d174930b3cf7b69#initrd

Ciro Santilli adicionou uma nova foto
fonte